Merge backout.

This commit is contained in:
Mounir Lamouri 2012-06-22 11:14:08 +02:00
commit a84af71501
20 changed files with 476 additions and 251 deletions

View File

@ -250,6 +250,64 @@ public:
return OwnerDoc()->IsHTML();
}
/**
* Get the namespace that this element's tag is defined in
* @return the namespace
*/
inline PRInt32 GetNameSpaceID() const
{
return mNodeInfo->NamespaceID();
}
/**
* Get the NodeInfo for this element
* @return the nodes node info
*/
inline nsINodeInfo* NodeInfo() const
{
return mNodeInfo;
}
inline bool IsInNamespace(PRInt32 aNamespace) const
{
return mNodeInfo->NamespaceID() == aNamespace;
}
inline bool IsHTML() const
{
return IsInNamespace(kNameSpaceID_XHTML);
}
inline bool IsHTML(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_XHTML);
}
inline bool IsSVG() const
{
return IsInNamespace(kNameSpaceID_SVG);
}
inline bool IsSVG(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_SVG);
}
inline bool IsXUL() const
{
return IsInNamespace(kNameSpaceID_XUL);
}
inline bool IsMathML() const
{
return IsInNamespace(kNameSpaceID_MathML);
}
inline bool IsMathML(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_MathML);
}
/**
* Returns an atom holding the name of the attribute of type ID on
* this content node (if applicable). Returns null for non-element

View File

@ -476,15 +476,6 @@ public:
return mNodeInfo->LocalName();
}
/**
* Get the namespace that this element's tag is defined in
* @return the namespace
*/
PRInt32 GetNameSpaceID() const
{
return mNodeInfo->NamespaceID();
}
/**
* Get the tag for this element. This will always return a non-null atom
* pointer (as implied by the naming of the method). For elements this is
@ -496,55 +487,6 @@ public:
return mNodeInfo->NameAtom();
}
/**
* Get the NodeInfo for this element
* @return the nodes node info
*/
nsINodeInfo* NodeInfo() const
{
return mNodeInfo;
}
bool IsInNamespace(PRInt32 aNamespace) const
{
return mNodeInfo->NamespaceID() == aNamespace;
}
bool IsHTML() const
{
return IsInNamespace(kNameSpaceID_XHTML);
}
bool IsHTML(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_XHTML);
}
bool IsSVG() const
{
return IsInNamespace(kNameSpaceID_SVG);
}
bool IsSVG(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_SVG);
}
bool IsXUL() const
{
return IsInNamespace(kNameSpaceID_XUL);
}
bool IsMathML() const
{
return IsInNamespace(kNameSpaceID_MathML);
}
bool IsMathML(nsIAtom* aTag) const
{
return mNodeInfo->Equals(aTag, kNameSpaceID_MathML);
}
nsINode*
InsertBefore(nsINode *aNewChild, nsINode *aRefChild, nsresult *aReturn)
{

View File

@ -78,98 +78,327 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj)
c->Drop();
}
static JSBool
XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp)
// XBL fields are represented on elements inheriting that field a bit trickily.
// Initially the element itself won't have a property for the field. When an
// attempt is made to access the field, the element's resolve hook won't find
// it. But the XBL prototype object, in the prototype chain of the element,
// will resolve an accessor property for the field on the XBL prototype object.
// That accessor, when used, will then (via InstallXBLField below) reify a
// property for the field onto the actual XBL-backed element.
//
// The accessor property is a plain old property backed by a getter function and
// a setter function. These properties are backed by the FieldGetter and
// FieldSetter natives; they're created by XBLResolve. The precise field to be
// reified is identified using two extra slots on the getter/setter functions.
// XBLPROTO_SLOT stores the XBL prototype object that provides the field.
// FIELD_SLOT stores the name of the field, i.e. its JavaScript property name.
//
// This two-step field installation process -- reify an accessor on the
// prototype, then have that reify an own property on the actual element -- is
// admittedly convoluted. Better would be for XBL-backed elements to be proxies
// that could resolve fields onto themselves. But given that XBL bindings are
// associated with elements mutably -- you can add/remove/change -moz-binding
// whenever you want, alas -- doing so would require all elements to be proxies,
// which isn't performant now. So we do this two-step instead.
static const uint32_t XBLPROTO_SLOT = 0;
static const uint32_t FIELD_SLOT = 1;
static bool
ObjectHasISupportsPrivate(JS::Handle<JSObject*> obj)
{
// Note: if we get here, that means that the implementation for some binding
// was installed, which means that AllowScripts() tested true. Hence no need
// to do checks like that here.
JSClass* clasp = ::JS_GetClass(obj);
const uint32_t HAS_PRIVATE_NSISUPPORTS =
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS;
return (clasp->flags & HAS_PRIVATE_NSISUPPORTS) == HAS_PRIVATE_NSISUPPORTS;
}
// Default to not resolving things.
NS_ASSERTION(*objp, "Must have starting object");
// Define a shadowing property on |this| for the XBL field defined by the
// contents of the callee's reserved slots. If the property was defined,
// *installed will be true, and idp will be set to the property name that was
// defined.
static JSBool
InstallXBLField(JSContext* cx,
JS::Handle<JSObject*> callee, JS::Handle<JSObject*> thisObj,
jsid* idp, bool* installed)
{
*installed = false;
JSObject* origObj = *objp;
*objp = NULL;
if (!JSID_IS_STRING(id)) {
return JS_TRUE;
}
nsDependentJSString fieldName(id);
jsval slotVal = ::JS_GetReservedSlot(obj, 0);
NS_ASSERTION(!JSVAL_IS_VOID(slotVal), "How did that happen?");
nsXBLPrototypeBinding* protoBinding =
static_cast<nsXBLPrototypeBinding*>(JSVAL_TO_PRIVATE(slotVal));
NS_ASSERTION(protoBinding, "Must have prototype binding!");
nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
if (!field) {
return JS_TRUE;
}
// We have this field. Time to install it. Get our node.
JSClass* nodeClass = ::JS_GetClass(origObj);
if (!nodeClass) {
return JS_FALSE;
}
if (~nodeClass->flags &
(JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
xpc::Throw(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
// First ensure |this| is a reasonable XBL bound node.
//
// FieldAccessorGuard already determined whether |thisObj| was acceptable as
// |this| in terms of not throwing a TypeError. Assert this for good measure.
MOZ_ASSERT(ObjectHasISupportsPrivate(thisObj));
// But there are some cases where we must accept |thisObj| but not install a
// property on it, or otherwise touch it. Hence this split of |this|-vetting
// duties.
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
do_QueryInterface(static_cast<nsISupports*>(::JS_GetPrivate(origObj)));
do_QueryInterface(static_cast<nsISupports*>(::JS_GetPrivate(thisObj)));
if (!xpcWrapper) {
// Looks like whatever |origObj| is it's not our nsIContent. It might well
// Looks like whatever |thisObj| is it's not our nsIContent. It might well
// be the proto our binding installed, however, where the private is the
// nsXBLDocumentInfo, so just baul out quietly. Do NOT throw an exception
// here.
// We could make this stricter by checking the class maybe, but whatever
return JS_TRUE;
//
// We could make this stricter by checking the class maybe, but whatever.
return true;
}
nsCOMPtr<nsIContent> content = do_QueryWrappedNative(xpcWrapper);
if (!content) {
nsCOMPtr<nsIContent> xblNode = do_QueryWrappedNative(xpcWrapper);
if (!xblNode) {
xpc::Throw(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
return false;
}
// Now that |this| is okay, actually install the field. Some of this
// installation work could have been done in XBLResolve, but this splitting
// of work seems simplest to implement and friendliest regarding lifetimes
// and potential cycles.
// Because of the possibility (due to XBL binding inheritance, because each
// XBL binding lives in its own global object) that |this| might be in a
// different compartment from the callee (not to mention that this method can
// be called with an arbitrary |this| regardless of how insane XBL is), and
// because in this method we've entered |this|'s compartment (see in
// Field[GS]etter where we attempt a cross-compartment call), we must enter
// the callee's compartment to access its reserved slots.
nsXBLPrototypeBinding* protoBinding;
nsDependentJSString fieldName;
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, callee)) {
return false;
}
JS::Rooted<JSObject*> xblProto(cx);
xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
JS::Value name = js::GetFunctionNativeReserved(callee, FIELD_SLOT);
JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
fieldName.init(fieldStr);
MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp));
JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
MOZ_ASSERT(protoBinding);
}
nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
MOZ_ASSERT(field);
// This mirrors code in nsXBLProtoImpl::InstallImplementation
nsIDocument* doc = content->OwnerDoc();
nsIScriptGlobalObject* global = doc->GetScriptGlobalObject();
nsIScriptGlobalObject* global = xblNode->OwnerDoc()->GetScriptGlobalObject();
if (!global) {
return JS_TRUE;
return true;
}
nsCOMPtr<nsIScriptContext> context = global->GetContext();
if (!context) {
return JS_TRUE;
return true;
}
nsresult rv = field->InstallField(context, thisObj, xblNode->NodePrincipal(),
protoBinding->DocURI(), installed);
if (NS_SUCCEEDED(rv)) {
return true;
}
// Now we either resolve or fail
bool didInstall;
nsresult rv = field->InstallField(context, origObj,
content->NodePrincipal(),
protoBinding->DocURI(),
&didInstall);
if (NS_FAILED(rv)) {
if (!::JS_IsExceptionPending(cx)) {
xpc::Throw(cx, rv);
return JS_FALSE;
}
return false;
}
// Determine whether the |this| passed to this method is valid for an XBL field
// access (which is to say, an object with an nsISupports private), taking into
// account proxies and/or wrappers around |this|. There are three possible
// outcomes from calling this method:
//
// 1. An error was hit, and this method returned false. In this case, the
// caller should propagate it.
// 2. The |this| passed in was directly acceptable for XBL field access. This
// method returned true and set *thisObj to a |this| that can be used for
// field definition (i.e. that passes ObjectHasISupportsPrivate). In this
// case, the caller should install the field on *thisObj.
// 3. The |this| passed in was a proxy/wrapper around an object usable for
// XBL field access. The method recursively (and successfully) invoked the
// native on the unwrapped |this|, then it returned true and set *thisObj
// to null. In this case, the caller should itself return true.
//
// Thus this method implements the JS_CallNonGenericMethodOnProxy idiom in
// jsapi.h.
//
// Note that a |this| valid for field access is *not* necessarily one on which
// the field value will be installed. It's just one where calling the specified
// method on it won't unconditionally throw a TypeError. Confusing? Perhaps,
// but it's compatible with what we did before we implemented XBL fields using
// this technique.
inline bool
FieldAccessorGuard(JSContext *cx, unsigned argc, JS::Value *vp, JSNative native, JSObject **thisObj)
{
JS::Rooted<JSObject*> obj(cx, JS_THIS_OBJECT(cx, vp));
if (!obj) {
xpc::Throw(cx, NS_ERROR_UNEXPECTED);
return false;
}
if (didInstall) {
*objp = origObj;
if (ObjectHasISupportsPrivate(obj)) {
*thisObj = obj;
return true;
}
// else we didn't resolve this field after all
return JS_TRUE;
// |this| wasn't an unwrapped object passing the has-private-nsISupports test.
// So try to unwrap |this| and recursively call the native on it.
//
// This |protoClass| gunk is needed for the JS engine to report an error if an
// object of the wrong class was passed as |this|, so that it can complain
// that it expected an object of type |protoClass|. It would be better if the
// error didn't try to specify the expected class of objects -- particularly
// because there's no one class of objects -- but it's what the API wants, so
// pass a class that's marginally correct as an answer.
JSClass* protoClass;
{
JS::Rooted<JSObject*> callee(cx, &JS_CALLEE(cx, vp).toObject());
JS::Rooted<JSObject*> xblProto(cx);
xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
JSAutoEnterCompartment ac;
if (!ac.enter(cx, xblProto)) {
return false;
}
protoClass = ::JS_GetClass(xblProto);
}
*thisObj = NULL;
return JS_CallNonGenericMethodOnProxy(cx, argc, vp, native, protoClass);
}
static JSBool
FieldGetter(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::Rooted<JSObject*> thisObj(cx);
if (!FieldAccessorGuard(cx, argc, vp, FieldGetter, thisObj.address())) {
return false;
}
if (!thisObj) {
return true; // FieldGetter was recursively invoked on an unwrapped |this|
}
bool installed = false;
JS::Rooted<JSObject*> callee(cx, &JS_CALLEE(cx, vp).toObject());
JS::Rooted<jsid> id(cx);
if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
return false;
}
if (!installed) {
JS_SET_RVAL(cx, vp, JS::UndefinedValue());
return true;
}
JS::Rooted<JS::Value> v(cx);
if (!JS_GetPropertyById(cx, thisObj, id, v.address())) {
return false;
}
JS_SET_RVAL(cx, vp, v);
return true;
}
static JSBool
FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::Rooted<JSObject*> thisObj(cx);
if (!FieldAccessorGuard(cx, argc, vp, FieldSetter, thisObj.address())) {
return false;
}
if (!thisObj) {
return true; // FieldSetter was recursively invoked on an unwrapped |this|
}
bool installed = false;
JS::Rooted<JSObject*> callee(cx, &JS_CALLEE(cx, vp).toObject());
JS::Rooted<jsid> id(cx);
if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
return false;
}
JS::Rooted<JS::Value> v(cx,
argc > 0 ? JS_ARGV(cx, vp)[0] : JS::UndefinedValue());
return JS_SetPropertyById(cx, thisObj, id, v.address());
}
static JSBool
XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp)
{
*objp = NULL;
if (!JSID_IS_STRING(id)) {
return true;
}
nsXBLPrototypeBinding* protoBinding =
static_cast<nsXBLPrototypeBinding*>(::JS_GetReservedSlot(obj, 0).toPrivate());
MOZ_ASSERT(protoBinding);
// If the field's not present, don't resolve it. Also don't resolve it if the
// field is empty; see also nsXBLProtoImplField::InstallField which also must
// implement the not-empty requirement.
nsDependentJSString fieldName(id);
nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
if (!field || field->IsEmpty()) {
return true;
}
// We have a field: now install a getter/setter pair which will resolve the
// field onto the actual object, when invoked.
JS::Rooted<JSObject*> global(cx, JS_GetGlobalForObject(cx, obj));
JS::Rooted<JSObject*> get(cx);
get = ::JS_GetFunctionObject(js::NewFunctionByIdWithReserved(cx, FieldGetter,
0, 0, global,
id));
if (!get) {
return false;
}
js::SetFunctionNativeReserved(get, XBLPROTO_SLOT, JS::ObjectValue(*obj));
js::SetFunctionNativeReserved(get, FIELD_SLOT,
JS::StringValue(JSID_TO_STRING(id)));
JS::Rooted<JSObject*> set(cx);
set = ::JS_GetFunctionObject(js::NewFunctionByIdWithReserved(cx, FieldSetter,
1, 0, global,
id));
if (!set) {
return false;
}
js::SetFunctionNativeReserved(set, XBLPROTO_SLOT, JS::ObjectValue(*obj));
js::SetFunctionNativeReserved(set, FIELD_SLOT,
JS::StringValue(JSID_TO_STRING(id)));
if (!::JS_DefinePropertyById(cx, obj, id, JS::UndefinedValue(),
JS_DATA_TO_FUNC_PTR(JSPropertyOp,
get.reference()),
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp,
set.reference()),
field->AccessorAttributes())) {
return false;
}
*objp = obj;
return true;
}
static JSBool
XBLEnumerate(JSContext *cx, JS::Handle<JSObject*> obj)
{
nsXBLPrototypeBinding* protoBinding =
static_cast<nsXBLPrototypeBinding*>(::JS_GetReservedSlot(obj, 0).toPrivate());
MOZ_ASSERT(protoBinding);
return protoBinding->ResolveAllFields(cx, obj);
}
nsXBLJSClass::nsXBLJSClass(const nsAFlatCString& aClassName)
@ -179,12 +408,12 @@ nsXBLJSClass::nsXBLJSClass(const nsAFlatCString& aClassName)
name = ToNewCString(aClassName);
flags =
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
JSCLASS_NEW_RESOLVE | JSCLASS_NEW_RESOLVE_GETS_START |
JSCLASS_NEW_RESOLVE |
// Our one reserved slot holds the relevant nsXBLPrototypeBinding
JSCLASS_HAS_RESERVED_SLOTS(1);
addProperty = delProperty = getProperty = ::JS_PropertyStub;
setProperty = ::JS_StrictPropertyStub;
enumerate = ::JS_EnumerateStub;
enumerate = XBLEnumerate;
resolve = (JSResolveOp)XBLResolve;
convert = ::JS_ConvertStub;
finalize = XBLFinalize;

View File

@ -88,7 +88,8 @@ nsXBLProtoImplField::InstallField(nsIScriptContext* aContext,
*aDidInstall = false;
if (mFieldTextLength == 0) {
// Empty fields are treated as not actually present.
if (IsEmpty()) {
return NS_OK;
}

View File

@ -41,6 +41,13 @@ public:
const PRUnichar* GetName() const { return mName; }
unsigned AccessorAttributes() const {
return JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER |
(mJSAttributes & (JSPROP_ENUMERATE | JSPROP_PERMANENT));
}
bool IsEmpty() const { return mFieldTextLength == 0; }
protected:
nsXBLProtoImplField* mNext;
PRUnichar* mName;

View File

@ -116,8 +116,9 @@ addLoadEvent(function() {
is(found, true, "Enumeration is broken");
is(d.four, 9, "Shouldn't have rerun field six");
is(d.five, 5, "Should have run field 7");
is(d.five, 11, "Shouldn't have run field 7");
is(d.seven, 7, "Should be 7")
is(d.five, 5, "Should have run field 7");
d = $("display2");
is(typeof(d.eight), "undefined", "Recursive resolve should bail out");

View File

@ -574,8 +574,7 @@ static const char kDOMStringBundleURL[] =
#define ELEMENT_SCRIPTABLE_FLAGS \
((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_ENUMERATE)
nsIXPCScriptable::WANT_POSTCREATE)
#define EXTERNAL_OBJ_SCRIPTABLE_FLAGS \
((ELEMENT_SCRIPTABLE_FLAGS & \
@ -8188,27 +8187,6 @@ nsElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
NS_IMETHODIMP
nsElementSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, bool *_retval)
{
// Make sure to not call the superclass here!
nsCOMPtr<nsIContent> content(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
nsIDocument* doc = content->OwnerDoc();
nsRefPtr<nsXBLBinding> binding = doc->BindingManager()->GetBinding(content);
if (!binding) {
// Nothing else to do here
return NS_OK;
}
*_retval = binding->ResolveAllFields(cx, obj);
return NS_OK;
}
// Generic array scriptable helper.

View File

@ -562,8 +562,6 @@ public:
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, bool *_retval);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{

View File

@ -1090,6 +1090,7 @@ nsGlobalWindow::FreeInnerObjects()
}
if (mScreen) {
mScreen->Reset();
mScreen = nsnull;
}

View File

@ -63,8 +63,25 @@ nsScreen::nsScreen()
{
}
void
nsScreen::Reset()
{
hal::UnlockScreenOrientation();
if (mEventListener) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
if (target) {
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mEventListener, true);
}
mEventListener = nsnull;
}
}
nsScreen::~nsScreen()
{
Reset();
hal::UnregisterScreenConfigurationObserver(this);
}
@ -318,6 +335,7 @@ NS_IMETHODIMP
nsScreen::MozLockOrientation(const nsAString& aOrientation, bool* aReturn)
{
ScreenOrientation orientation;
*aReturn = false;
if (aOrientation.EqualsLiteral("portrait")) {
orientation = eScreenOrientation_Portrait;
@ -332,37 +350,31 @@ nsScreen::MozLockOrientation(const nsAString& aOrientation, bool* aReturn)
} else if (aOrientation.EqualsLiteral("landscape-secondary")) {
orientation = eScreenOrientation_LandscapeSecondary;
} else {
*aReturn = false;
return NS_OK;
}
if (!GetOwner()) {
*aReturn = false;
return NS_OK;
}
if (!IsChromeType(GetOwner()->GetDocShell())) {
// Chrome code and apps can always lock the screen orientation.
if (!IsChromeType(GetOwner()->GetDocShell()) &&
!static_cast<nsGlobalWindow*>(GetOwner())->IsPartOfApp()) {
nsCOMPtr<nsIDOMDocument> doc;
GetOwner()->GetDocument(getter_AddRefs(doc));
if (!doc) {
*aReturn = false;
return NS_OK;
}
// Apps and frames contained in apps can lock orientation.
// But non-apps can lock orientation only if they're fullscreen.
if (!static_cast<nsGlobalWindow*>(GetOwner())->IsPartOfApp()) {
// Non-apps content can lock orientation only if fullscreen.
bool fullscreen;
doc->GetMozFullScreen(&fullscreen);
if (!fullscreen) {
*aReturn = false;
return NS_OK;
}
}
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
if (!target) {
*aReturn = false;
return NS_OK;
}

View File

@ -26,7 +26,7 @@ class nsScreen : public nsDOMEventTargetHelper
public:
static already_AddRefed<nsScreen> Create(nsPIDOMWindow* aWindow);
void Invalidate();
void Reset();
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMSCREEN

View File

@ -17,8 +17,6 @@ const DEBUG = RIL.DEBUG_RIL;
const RADIOINTERFACELAYER_CID =
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
const DATACALLINFO_CID =
Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
const nsIAudioManager = Ci.nsIAudioManager;
const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
@ -131,20 +129,6 @@ XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
});
function DataCallInfo(state, cid, apn) {
this.callState = state;
this.cid = cid;
this.apn = apn;
}
DataCallInfo.protoptype = {
classID: DATACALLINFO_CID,
classInfo: XPCOMUtils.generateCI({classID: DATACALLINFO_CID,
classDescription: "DataCallInfo",
interfaces: [Ci.nsIDataCallInfo]}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInfo]),
};
function RadioInterfaceLayer() {
debug("Starting RIL Worker");
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
@ -897,21 +881,15 @@ RadioInterfaceLayer.prototype = {
}
this._deliverDataCallCallback("dataCallStateChanged",
[datacall.cid, datacall.ifname, datacall.state]);
[datacall]);
},
/**
* Handle data call list.
*/
handleDataCallList: function handleDataCallList(message) {
let datacalls = [];
for each (let datacall in message.datacalls) {
datacalls.push(new DataCallInfo(datacall.state,
datacall.cid,
datacall.apn));
}
this._deliverDataCallCallback("receiveDataCallList",
[datacalls, datacalls.length]);
[message.datacalls, message.datacalls.length]);
},
/**
@ -1715,14 +1693,14 @@ let RILNetworkInterface = {
// nsIRILDataCallback
dataCallStateChanged: function dataCallStateChanged(cid, interfaceName, callState) {
debug("Data call ID: " + cid + ", interface name: " + interfaceName);
dataCallStateChanged: function dataCallStateChanged(datacall) {
debug("Data call ID: " + datacall.cid + ", interface name: " + datacall.ifname);
if (this.connecting &&
(callState == RIL.GECKO_NETWORK_STATE_CONNECTING ||
callState == RIL.GECKO_NETWORK_STATE_CONNECTED)) {
(datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTING ||
datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED)) {
this.connecting = false;
this.cid = cid;
this.name = interfaceName;
this.cid = datacall.cid;
this.name = datacall.ifname;
if (!this.registeredAsNetworkInterface) {
let networkManager = Cc["@mozilla.org/network/manager;1"]
.getService(Ci.nsINetworkManager);
@ -1730,14 +1708,14 @@ let RILNetworkInterface = {
this.registeredAsNetworkInterface = true;
}
}
if (this.cid != cid) {
if (this.cid != datacall.cid) {
return;
}
if (this.state == callState) {
if (this.state == datacall.state) {
return;
}
this.state = callState;
this.state = datacall.state;
Services.obs.notifyObservers(this,
kNetworkInterfaceStateChangedTopic,
null);

View File

@ -62,30 +62,25 @@ interface nsIRILTelephonyCallback : nsISupports
in AString error);
};
[scriptable, uuid(66a55943-e63b-4731-aece-9c04bfc14019)]
[scriptable, uuid(8a711703-1ee5-4675-9d9a-0b188e944cfe)]
interface nsIRILDataCallInfo : nsISupports
{
readonly attribute unsigned long callState;
readonly attribute unsigned long state;
readonly attribute AString cid;
readonly attribute AString apn;
readonly attribute AString ifname;
};
[scriptable, uuid(cea91bcb-3cfb-42bb-8638-dae89e8870fc)]
[scriptable, uuid(5bcac053-c245-46f0-bb45-d0039bfb89f5)]
interface nsIRILDataCallback : nsISupports
{
/**
* Notified when a data call changes state.
*
* @param cid
* The CID of the data call.
* @param interfaceName
* Name of the associated network interface.
* @param dataState
* One of the nsIRadioInterfaceLayer::DATACALL_STATE_* values.
* @param dataCall
* A nsIRILDataCallInfo object.
*/
void dataCallStateChanged(in AString cid,
in AString interfaceName,
in unsigned short callState);
void dataCallStateChanged(in nsIRILDataCallInfo dataCall);
/**
* Called when nsIRadioInterfaceLayer is asked to enumerate the current

View File

@ -1406,23 +1406,10 @@ typedef JSBool
*
* The *objp out parameter, on success, should be null to indicate that id
* was not resolved; and non-null, referring to obj or one of its prototypes,
* if id was resolved.
* if id was resolved. The hook may assume *objp is null on entry.
*
* This hook instead of JSResolveOp is called via the JSClass.resolve member
* if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
*
* Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
* extends this hook by passing in the starting object on the prototype chain
* via *objp. Thus a resolve hook implementation may define the property id
* being resolved in the object in which the id was first sought, rather than
* in a prototype object whose class led to the resolve hook being called.
*
* When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
* null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
* JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
* This is not good practice, but enough existing hook implementations count
* on it that we can't break compatibility by passing the starting object in
* *objp without a new JSClass flag.
*/
typedef JSBool
(* JSNewResolveOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
@ -3661,10 +3648,7 @@ struct JSClass {
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
#define JSCLASS_NEW_RESOLVE_GETS_START (1<<4) /* JSNewResolveOp gets starting
object in prototype chain
passed in via *objp in/out
parameter */
/* (1<<4) is unused */
#define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) /* Correctly implements GC read
and write barriers */
#define JSCLASS_DOCUMENT_OBSERVER (1<<6) /* DOM document observer */

View File

@ -4643,9 +4643,9 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &
/*
* Call obj's resolve hook.
*
* cx, start, id, and flags are the parameters initially passed to the ongoing
* lookup; objp and propp are its out parameters. obj is an object along
* start's prototype chain.
* cx, id, and flags are the parameters initially passed to the ongoing lookup;
* objp and propp are its out parameters. obj is an object along the prototype
* chain from where the lookup started.
*
* There are four possible outcomes:
*
@ -4661,7 +4661,7 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &
* and return true.
*/
static JSBool
CallResolveOp(JSContext *cx, JSObject *start, HandleObject obj, HandleId id, unsigned flags,
CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
JSObject **objp, JSProperty **propp, bool *recursedp)
{
Class *clasp = obj->getClass();
@ -4690,8 +4690,7 @@ CallResolveOp(JSContext *cx, JSObject *start, HandleObject obj, HandleId id, uns
if (flags == RESOLVE_INFER)
flags = js_InferFlags(cx, 0);
RootedObject obj2(cx);
obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START) ? start : NULL;
RootedObject obj2(cx, NULL);
if (!newresolve(cx, obj, id, flags, obj2.address()))
return false;
@ -4742,7 +4741,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
/* Try obj's class resolve hook if id was not found in obj's scope. */
if (current->getClass()->resolve != JS_ResolveStub) {
bool recursed;
if (!CallResolveOp(cx, obj, current, id, flags, objp, propp, &recursed))
if (!CallResolveOp(cx, current, id, flags, objp, propp, &recursed))
return false;
if (recursed)
break;

View File

@ -36,6 +36,8 @@ public class GeckoScreenOrientationListener
static public final short eScreenOrientation_LandscapeSecondary = 8;
static public final short eScreenOrientation_Landscape = 12;
static private final short kDefaultScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
private short mOrientation;
private OrientationEventListenerImpl mListener = null;
@ -150,6 +152,7 @@ public class GeckoScreenOrientationListener
break;
default:
Log.e(LOGTAG, "Unexpected value received! (" + aOrientation + ")");
return;
}
GeckoApp.mAppContext.setRequestedOrientation(orientation);
@ -157,7 +160,11 @@ public class GeckoScreenOrientationListener
}
public void unlockScreenOrientation() {
GeckoApp.mAppContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
if (GeckoApp.mAppContext.getRequestedOrientation() == kDefaultScreenOrientation) {
return;
}
GeckoApp.mAppContext.setRequestedOrientation(kDefaultScreenOrientation);
updateScreenOrientation();
}
}

View File

@ -1106,6 +1106,13 @@ nsCacheService::Init()
{
NS_TIME_FUNCTION;
// Thie method must be called on the main thread because mCacheIOThread must
// only be modified on the main thread.
if (!NS_IsMainThread()) {
NS_ERROR("nsCacheService::Init called off the main thread");
return NS_ERROR_NOT_SAME_THREAD;
}
NS_ASSERTION(!mInitialized, "nsCacheService already initialized.");
if (mInitialized)
return NS_ERROR_ALREADY_INITIALIZED;
@ -1158,6 +1165,12 @@ nsCacheService::ShutdownCustomCacheDeviceEnum(const nsAString& aProfileDir,
void
nsCacheService::Shutdown()
{
// Thie method must be called on the main thread because mCacheIOThread must
// only be modified on the main thread.
if (!NS_IsMainThread()) {
NS_RUNTIMEABORT("nsCacheService::Shutdown called off the main thread");
}
nsCOMPtr<nsIThread> cacheIOThread;
Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_SHUTDOWN> totalTimer;
@ -1469,13 +1482,29 @@ NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy)
NS_IMETHODIMP nsCacheService::GetCacheIOTarget(nsIEventTarget * *aCacheIOTarget)
{
nsCacheServiceAutoLock lock;
NS_ENSURE_ARG_POINTER(aCacheIOTarget);
if (!mCacheIOThread)
return NS_ERROR_NOT_AVAILABLE;
// Because mCacheIOThread can only be changed on the main thread, it can be
// read from the main thread without the lock. This is useful to prevent
// blocking the main thread on other cache operations.
if (!NS_IsMainThread()) {
Lock();
}
nsresult rv;
if (mCacheIOThread) {
NS_ADDREF(*aCacheIOTarget = mCacheIOThread);
return NS_OK;
rv = NS_OK;
} else {
*aCacheIOTarget = nsnull;
rv = NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
Unlock();
}
return rv;
}
/**

View File

@ -60,7 +60,7 @@ AccumulateCacheHitTelemetry(mozilla::Telemetry::ID deviceHistogram,
PRUint32 hitOrMiss)
{
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::HTTP_CACHE_DISPOSITION, hitOrMiss);
mozilla::Telemetry::HTTP_CACHE_DISPOSITION_2, hitOrMiss);
if (deviceHistogram != UNKNOWN_DEVICE) {
mozilla::Telemetry::Accumulate(deviceHistogram, hitOrMiss);
}
@ -2879,13 +2879,13 @@ HttpCacheQuery::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
if (cacheDeviceID) {
if (!strcmp(cacheDeviceID, kDiskDeviceID)) {
mCacheEntryDeviceTelemetryID
= mozilla::Telemetry::HTTP_DISK_CACHE_DISPOSITION;
= mozilla::Telemetry::HTTP_DISK_CACHE_DISPOSITION_2;
} else if (!strcmp(cacheDeviceID, kMemoryDeviceID)) {
mCacheEntryDeviceTelemetryID
= mozilla::Telemetry::HTTP_MEMORY_CACHE_DISPOSITION;
= mozilla::Telemetry::HTTP_MEMORY_CACHE_DISPOSITION_2;
} else if (!strcmp(cacheDeviceID, kOfflineDeviceID)) {
mCacheEntryDeviceTelemetryID
= mozilla::Telemetry::HTTP_OFFLINE_CACHE_DISPOSITION;
= mozilla::Telemetry::HTTP_OFFLINE_CACHE_DISPOSITION_2;
} else {
MOZ_NOT_REACHED("unknown cache device ID");
}

View File

@ -195,11 +195,11 @@ HISTOGRAM(SPDY_SETTINGS_IW, 1, 1000, 50, EXPONENTIAL, "SPDY: Settings IW (round
#undef _HTTP_HIST
#undef HTTP_HISTOGRAMS
HISTOGRAM(HTTP_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM(DISK_CACHE_CORRUPT, 0, 1, 2, BOOLEAN, "Was the HTTP disk cache corrupt at startup?")
HISTOGRAM(HTTP_DISK_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Disk Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM(HTTP_MEMORY_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Memory Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM(HTTP_OFFLINE_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Offline Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM_ENUMERATED_VALUES(HTTP_CACHE_DISPOSITION_2, 5, "HTTP Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM_ENUMERATED_VALUES(HTTP_DISK_CACHE_DISPOSITION_2, 5, "HTTP Disk Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM_ENUMERATED_VALUES(HTTP_MEMORY_CACHE_DISPOSITION_2, 5, "HTTP Memory Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM_ENUMERATED_VALUES(HTTP_OFFLINE_CACHE_DISPOSITION_2, 5, "HTTP Offline Cache Hit, Reval, Failed-Reval, Miss")
HISTOGRAM(CACHE_DEVICE_SEARCH, 1, 100, 100, LINEAR, "Time to search cache (ms)")
HISTOGRAM(CACHE_MEMORY_SEARCH, 1, 100, 100, LINEAR, "Time to search memory cache (ms)")
HISTOGRAM(CACHE_DISK_SEARCH, 1, 100, 100, LINEAR, "Time to search disk cache (ms)")

View File

@ -605,7 +605,13 @@ nsScreenGonk::GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop,
static uint32_t
ColorDepth()
{
return gNativeWindow->getDevice()->format == GGL_PIXEL_FORMAT_RGB_565 ? 16 : 24;
switch (gNativeWindow->getDevice()->format) {
case GGL_PIXEL_FORMAT_RGB_565:
return 16;
case GGL_PIXEL_FORMAT_RGBA_8888:
return 32;
}
return 24; // GGL_PIXEL_FORMAT_RGBX_8888
}
NS_IMETHODIMP