Bug 1091970 - [e10s] Cache object tag in add-on shims for remote objects (r=mrbkap)

This commit is contained in:
Bill McCloskey 2014-11-04 17:40:08 -08:00
parent 6ed288e283
commit 7cf195d449
12 changed files with 122 additions and 15 deletions

View File

@ -441,6 +441,7 @@
@BINPATH@/components/nsUpdateTimerManager.js
@BINPATH@/components/addoncompat.manifest
@BINPATH@/components/multiprocessShims.js
@BINPATH@/components/remoteTagService.js
@BINPATH@/components/pluginGlue.manifest
@BINPATH@/components/ProcessSingleton.manifest
@BINPATH@/components/MainProcessSingleton.js

View File

@ -37,6 +37,7 @@ struct RemoteObject
uint64_t serializedId;
bool isCallable;
bool isConstructor;
nsCString objectTag;
};
union ObjectVariant

View File

@ -13,6 +13,8 @@
#include "xpcprivate.h"
#include "WrapperFactory.h"
#include "nsIRemoteTagService.h"
using namespace js;
using namespace JS;
using namespace mozilla;
@ -24,10 +26,15 @@ struct AuxCPOWData
bool isCallable;
bool isConstructor;
AuxCPOWData(ObjectId id, bool isCallable, bool isConstructor)
// The object tag is just some auxilliary information that clients can use
// however they see fit.
nsCString objectTag;
AuxCPOWData(ObjectId id, bool isCallable, bool isConstructor, const nsACString &objectTag)
: id(id),
isCallable(isCallable),
isConstructor(isConstructor)
isConstructor(isConstructor),
objectTag(objectTag)
{}
};
@ -803,6 +810,17 @@ IsWrappedCPOW(JSObject *obj)
return IsCPOW(unwrapped);
}
void
GetWrappedCPOWTag(JSObject *obj, nsACString &out)
{
JSObject *unwrapped = js::UncheckedUnwrap(obj, true);
MOZ_ASSERT(IsCPOW(unwrapped));
AuxCPOWData *aux = AuxCPOWDataOf(unwrapped);
if (aux)
out = aux->objectTag;
}
nsresult
InstanceOf(JSObject *proxy, const nsID *id, bool *bp)
{
@ -884,9 +902,21 @@ WrapperOwner::ok(JSContext *cx, const ReturnStatus &status)
}
static RemoteObject
MakeRemoteObject(ObjectId id, JSObject *obj)
MakeRemoteObject(JSContext *cx, ObjectId id, HandleObject obj)
{
return RemoteObject(id.serialize(), JS::IsCallable(obj), JS::IsConstructor(obj));
nsCString objectTag;
nsCOMPtr<nsIRemoteTagService> service =
do_GetService("@mozilla.org/addons/remote-tag-service;1");
if (service) {
RootedValue objVal(cx, ObjectValue(*obj));
service->GetRemoteObjectTag(objVal, objectTag);
}
return RemoteObject(id.serialize(),
JS::IsCallable(obj),
JS::IsConstructor(obj),
objectTag);
}
bool
@ -910,7 +940,7 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob
ObjectId id = objectIdMap(waiveXray).find(obj);
if (!id.isNull()) {
MOZ_ASSERT(id.hasXrayWaiver() == waiveXray);
*objVarp = MakeRemoteObject(id, obj);
*objVarp = MakeRemoteObject(cx, id, obj);
return true;
}
@ -925,7 +955,7 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob
if (!objectIdMap(waiveXray).add(cx, obj, id))
return false;
*objVarp = MakeRemoteObject(id, obj);
*objVarp = MakeRemoteObject(cx, id, obj);
return true;
}
@ -964,7 +994,10 @@ WrapperOwner::fromRemoteObjectVariant(JSContext *cx, RemoteObject objVar)
// Incref once we know the decref will be called.
incref();
AuxCPOWData *aux = new AuxCPOWData(objId, objVar.isCallable(), objVar.isConstructor());
AuxCPOWData *aux = new AuxCPOWData(objId,
objVar.isCallable(),
objVar.isConstructor(),
objVar.objectTag());
SetProxyExtra(obj, 0, PrivateValue(this));
SetProxyExtra(obj, 1, PrivateValue(aux));

View File

@ -163,6 +163,9 @@ InstanceOf(JSObject *obj, const nsID *id, bool *bp);
bool
DOMInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp);
void
GetWrappedCPOWTag(JSObject *obj, nsACString &out);
} // jsipc
} // mozilla

View File

@ -8,6 +8,7 @@ XPIDL_SOURCES += [
'mozIJSSubScriptLoader.idl',
'nsIAddonInterposition.idl',
'nsIJSRuntimeService.idl',
'nsIRemoteTagService.idl',
'nsIScriptError.idl',
'nsIXPConnect.idl',
'nsIXPCScriptable.idl',

View File

@ -0,0 +1,13 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#include "nsISupports.idl"
[scriptable,uuid(59dbe3d0-6084-11e4-9803-0800200c9a66)]
interface nsIRemoteTagService : nsISupports
{
ACString getRemoteObjectTag(in jsval target);
};

View File

@ -122,7 +122,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(ad41689c-ed0e-4a92-8f19-a53c2dba5711)]
[scriptable, uuid(2617a800-63c1-11e4-9803-0800200c9a66)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -435,6 +435,15 @@ interface nsIXPCComponents_Utils : nsISupports
*/
bool isCrossProcessWrapper(in jsval obj);
/**
* CPOWs can have user data attached to them. This data originates
* in the local process via the
* nsIRemoteTagService.getRemoteObjectTag method. It's sent along
* with the CPOW to the remote process, where it can be fetched
* with this function, getCrossProcessWrapperTag.
*/
ACString getCrossProcessWrapperTag(in jsval obj);
/*
* To be called from JS only. This is for Gecko internal use only, and may
* disappear at any moment.

View File

@ -3106,6 +3106,16 @@ nsXPCComponents_Utils::IsCrossProcessWrapper(HandleValue obj, bool *out)
return NS_OK;
}
NS_IMETHODIMP
nsXPCComponents_Utils::GetCrossProcessWrapperTag(HandleValue obj, nsACString &out)
{
if (obj.isPrimitive() || !jsipc::IsWrappedCPOW(&obj.toObject()))
return NS_ERROR_INVALID_ARG;
jsipc::GetWrappedCPOWTag(&obj.toObject(), out);
return NS_OK;
}
/* void recomputerWrappers(jsval vobj); */
NS_IMETHODIMP
nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext *cx)

View File

@ -1,2 +1,4 @@
component {1363d5f0-d95e-11e3-9c1a-0800200c9a66} multiprocessShims.js
contract @mozilla.org/addons/multiprocess-shims;1 {1363d5f0-d95e-11e3-9c1a-0800200c9a66}
component {dfd07380-6083-11e4-9803-0800200c9a66} remoteTagService.js
contract @mozilla.org/addons/remote-tag-service;1 {dfd07380-6083-11e4-9803-0800200c9a66}

View File

@ -9,6 +9,7 @@ TEST_DIRS += ['tests']
EXTRA_COMPONENTS += [
'addoncompat.manifest',
'multiprocessShims.js',
'remoteTagService.js',
]
EXTRA_JS_MODULES += [

View File

@ -77,13 +77,7 @@ AddonInterpositionService.prototype = {
// determines the type of the target object.
getObjectTag: function(target) {
if (Cu.isCrossProcessWrapper(target)) {
if (target instanceof Ci.nsIDocShellTreeItem) {
return "ContentDocShellTreeItem";
}
if (target instanceof Ci.nsIDOMDocument) {
return "ContentDocument";
}
return Cu.getCrossProcessWrapperTag(target);
}
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

View File

@ -0,0 +1,39 @@
/* 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/. */
"use strict";
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function RemoteTagServiceService()
{
}
RemoteTagServiceService.prototype = {
classID: Components.ID("{dfd07380-6083-11e4-9803-0800200c9a66}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRemoteTagService, Ci.nsISupportsWeakReference]),
/**
* CPOWs can have user data attached to them. This data originates
* in the local process from this function, getRemoteObjectTag. It's
* sent along with the CPOW to the remote process, where it can be
* fetched with Components.utils.getCrossProcessWrapperTag.
*/
getRemoteObjectTag: function(target) {
if (target instanceof Ci.nsIDocShellTreeItem) {
return "ContentDocShellTreeItem";
}
if (target instanceof Ci.nsIDOMDocument) {
return "ContentDocument";
}
return "generic";
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RemoteTagServiceService]);