Bug 997325 - Implement main process scriptable only flag in XPIDL (r=mrbkap)

This commit is contained in:
Bill McCloskey 2015-03-06 08:34:08 -08:00
parent 423c9a7100
commit afd6d68422
14 changed files with 82 additions and 51 deletions

View File

@ -36,6 +36,7 @@
#include "xpcprivate.h"
#include "xpcpublic.h"
#include "nsContentUtils.h"
#include "nsXULAppAPI.h"
#include "WrapperFactory.h"
#include "mozilla/AddonPathService.h"
@ -372,35 +373,7 @@ mozJSComponentLoader::LoadModule(FileLocation &aFile)
return nullptr;
JSAutoCompartment ac(cx, entry->obj);
nsCOMPtr<nsIXPConnectJSObjectHolder> cm_holder;
rv = xpc->WrapNative(cx, entry->obj, cm,
NS_GET_IID(nsIComponentManager),
getter_AddRefs(cm_holder));
if (NS_FAILED(rv)) {
return nullptr;
}
JSObject* cm_jsobj = cm_holder->GetJSObject();
if (!cm_jsobj) {
return nullptr;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> file_holder;
RootedObject entryObj(cx, entry->obj);
rv = xpc->WrapNative(cx, entryObj, file,
NS_GET_IID(nsIFile),
getter_AddRefs(file_holder));
if (NS_FAILED(rv)) {
return nullptr;
}
JSObject* file_jsobj = file_holder->GetJSObject();
if (!file_jsobj) {
return nullptr;
}
RootedValue NSGetFactory_val(cx);
if (!JS_GetProperty(cx, entryObj, "NSGetFactory", &NSGetFactory_val) ||
@ -614,17 +587,19 @@ mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx,
if (testFile) {
*aRealFile = true;
nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
rv = xpc->WrapNative(aCx, obj, aComponentFile,
NS_GET_IID(nsIFile),
getter_AddRefs(locationHolder));
NS_ENSURE_SUCCESS(rv, nullptr);
if (XRE_GetProcessType() == GeckoProcessType_Default) {
nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
rv = xpc->WrapNative(aCx, obj, aComponentFile,
NS_GET_IID(nsIFile),
getter_AddRefs(locationHolder));
NS_ENSURE_SUCCESS(rv, nullptr);
RootedObject locationObj(aCx, locationHolder->GetJSObject());
NS_ENSURE_TRUE(locationObj, nullptr);
RootedObject locationObj(aCx, locationHolder->GetJSObject());
NS_ENSURE_TRUE(locationObj, nullptr);
if (!JS_DefineProperty(aCx, obj, "__LOCATION__", locationObj, 0))
return nullptr;
if (!JS_DefineProperty(aCx, obj, "__LOCATION__", locationObj, 0))
return nullptr;
}
}
nsAutoCString nativePath;

View File

@ -11,6 +11,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsPrintfCString.h"
using namespace JS;
using namespace mozilla;
@ -232,6 +233,27 @@ XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
if (NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
return nullptr;
bool mainProcessScriptableOnly;
if (NS_FAILED(aInfo->IsMainProcessScriptableOnly(&mainProcessScriptableOnly)))
return nullptr;
if (mainProcessScriptableOnly && XRE_GetProcessType() != GeckoProcessType_Default) {
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (console) {
char *intfNameChars;
aInfo->GetName(&intfNameChars);
nsPrintfCString errorMsg("Use of %s in content process is deprecated.", intfNameChars);
nsAutoString filename;
uint32_t lineno = 0;
nsJSUtils::GetCallingLocation(cx, filename, &lineno);
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
error->Init(NS_ConvertUTF8toUTF16(errorMsg),
filename, EmptyString(),
lineno, 0, nsIScriptError::warningFlag, "chrome javascript");
console->LogMessage(error);
}
}
if (NS_FAILED(aInfo->GetMethodCount(&methodCount)) ||
NS_FAILED(aInfo->GetConstantCount(&constCount)))
return nullptr;

View File

@ -232,7 +232,8 @@ def build_interface(iface, ifaces):
constants=consts, resolved=True, parent=parent,
scriptable=iface.attributes.scriptable,
function=iface.attributes.function,
builtinclass=iface.attributes.builtinclass)
builtinclass=iface.attributes.builtinclass,
main_process_scriptable_only=iface.attributes.main_process_scriptable_only)
def write_typelib(idl, fd, filename):
""" Generate the typelib. """

View File

@ -582,6 +582,7 @@ class InterfaceAttributes(object):
function = False
deprecated = False
noscript = False
main_process_scriptable_only = False
def setuuid(self, value):
self.uuid = value.lower()
@ -601,6 +602,9 @@ class InterfaceAttributes(object):
def setdeprecated(self):
self.deprecated = True
def setmain_process_scriptable_only(self):
self.main_process_scriptable_only = True
actions = {
'uuid': (True, setuuid),
'scriptable': (False, setscriptable),
@ -609,6 +613,7 @@ class InterfaceAttributes(object):
'noscript': (False, setnoscript),
'deprecated': (False, setdeprecated),
'object': (False, lambda self: True),
'main_process_scriptable_only': (False, setmain_process_scriptable_only),
}
def __init__(self, attlist, location):
@ -643,6 +648,8 @@ class InterfaceAttributes(object):
l.append("\tbuiltinclass\n")
if self.function:
l.append("\tfunction\n")
if self.main_process_scriptable_only:
l.append("\tmain_process_scriptable_only\n")
return "".join(l)
class ConstMember(object):

View File

@ -42,7 +42,7 @@ interface nsISimpleEnumerator;
* be safely passed to javascript via xpconnect. Therefore, the "native
* methods" are not scriptable.
*/
[scriptable, uuid(dfb5a307-7ecf-41dd-aee2-f1d623459c44), builtinclass]
[scriptable, main_process_scriptable_only, uuid(7441fb13-4d9f-42fd-836f-a165692938af), builtinclass]
interface nsIFile : nsISupports
{
/**

View File

@ -10,7 +10,7 @@
*
* @see nsIFile
*/
[scriptable, builtinclass, uuid(ce4ef184-7660-445e-9e59-6731bdc65505)]
[scriptable, builtinclass, uuid(7ba8c6ba-2ce2-48b1-bd60-4c32aac35f9c)]
interface nsILocalFile : nsIFile
{
};

View File

@ -16,7 +16,7 @@
[ptr] native FSRefPtr(FSRef);
native CFURLRef(CFURLRef);
[scriptable, builtinclass, uuid(E5DE2CC9-BF06-4329-8F91-5D2D45284500)]
[scriptable, builtinclass, uuid(623eca5b-c25d-4e27-be5a-789a66c4b2f7)]
interface nsILocalFileMac : nsILocalFile
{
/**

View File

@ -12,7 +12,7 @@ struct PRFileDesc;
[ptr] native PRFileDescStar(PRFileDesc);
[scriptable, builtinclass, uuid(ef454286-2848-4383-9101-660f190dd0a5)]
[scriptable, builtinclass, uuid(e7a3a954-384b-4aeb-a5f7-55626b0de9be)]
interface nsILocalFileWin : nsILocalFile
{
/**

View File

@ -544,6 +544,13 @@ ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal)
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal)
{
*aRetVal = false;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent)
{

View File

@ -24,7 +24,7 @@ class nsXPTType;
%}
/* this is NOT intended to be scriptable */
[uuid(3f1ae084-607e-45b2-8f1e-8d450b0f9c65)]
[uuid(4e698ffe-e9b5-42f3-9129-78a6c5fe0e9e)]
interface nsIInterfaceInfo : nsISupports
{
readonly attribute string name;
@ -32,6 +32,7 @@ interface nsIInterfaceInfo : nsISupports
boolean isScriptable();
boolean isBuiltinClass();
boolean isMainProcessScriptableOnly();
readonly attribute nsIInterfaceInfo parent;

View File

@ -170,6 +170,8 @@ XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* ifac
//XXX We should SetHeader too as part of the validation, no?
entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags));
entry->SetMainProcessScriptableOnlyFlag(
XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(iface->interface_descriptor->flags));
mWorkingSet.mIIDTable.Put(entry->IID(), entry);
mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);

View File

@ -180,21 +180,26 @@ public:
};
// Additional bit flags...
enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16};
enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
uint8_t GetResolveState() const {return mFlags.GetState();}
bool IsFullyResolved() const
{return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
void SetScriptableFlag(bool on)
void SetScriptableFlag(bool on)
{mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
bool GetScriptableFlag() const
{return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
void SetBuiltinClassFlag(bool on)
void SetBuiltinClassFlag(bool on)
{mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
bool GetBuiltinClassFlag() const
{return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
void SetMainProcessScriptableOnlyFlag(bool on)
{mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
bool GetMainProcessScriptableOnlyFlag() const
{return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
// AddRef/Release are special and are not considered for the NOTXPCOM flag.
@ -237,6 +242,10 @@ public:
*_retval = GetBuiltinClassFlag();
return NS_OK;
}
nsresult IsMainProcessScriptableOnly(bool *_retval) {
*_retval = GetMainProcessScriptableOnlyFlag();
return NS_OK;
}
// Except this one.
//nsresult GetParent(nsIInterfaceInfo * *aParent);
nsresult GetMethodCount(uint16_t *aMethodCount);
@ -321,6 +330,7 @@ public:
NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
// Except this one.
NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
{

View File

@ -848,7 +848,8 @@ class Interface(object):
def __init__(self, name, iid=UNRESOLVED_IID, namespace="",
resolved=False, parent=None, methods=[], constants=[],
scriptable=False, function=False, builtinclass=False):
scriptable=False, function=False, builtinclass=False,
main_process_scriptable_only=False):
self.resolved = resolved
#TODO: should validate IIDs!
self.iid = iid
@ -861,6 +862,7 @@ class Interface(object):
self.scriptable = scriptable
self.function = function
self.builtinclass = builtinclass
self.main_process_scriptable_only = main_process_scriptable_only
# For sanity, if someone constructs an Interface and passes
# in methods or constants, then it's resolved.
if self.methods or self.constants:
@ -930,13 +932,15 @@ class Interface(object):
(flags, ) = struct.unpack_from(">B", map, start)
offset = offset + struct.calcsize(">B")
# only the first two bits are flags
flags &= 0xE0
flags &= 0xf0
if flags & 0x80:
self.scriptable = True
if flags & 0x40:
self.function = True
if flags & 0x20:
self.builtinclass = True
if flags & 0x10:
self.main_process_scriptable_only = True
self.resolved = True
def write_directory_entry(self, file):
@ -977,6 +981,8 @@ class Interface(object):
flags |= 0x40
if self.builtinclass:
flags |= 0x20
if self.main_process_scriptable_only:
flags |= 0x10
file.write(struct.pack(">B", flags))
def write_names(self, file, data_pool_offset):

View File

@ -239,13 +239,13 @@ struct XPTInterfaceDescriptor {
#define XPT_ID_SCRIPTABLE 0x80
#define XPT_ID_FUNCTION 0x40
#define XPT_ID_BUILTINCLASS 0x20
#define XPT_ID_FLAGMASK 0xe0
#define XPT_ID_TAGMASK (~XPT_ID_FLAGMASK)
#define XPT_ID_TAG(id) ((id).flags & XPT_ID_TAGMASK)
#define XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY 0x10
#define XPT_ID_FLAGMASK 0xf0
#define XPT_ID_IS_SCRIPTABLE(flags) (!!(flags & XPT_ID_SCRIPTABLE))
#define XPT_ID_IS_FUNCTION(flags) (!!(flags & XPT_ID_FUNCTION))
#define XPT_ID_IS_BUILTINCLASS(flags) (!!(flags & XPT_ID_BUILTINCLASS))
#define XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(flags) (!!(flags & XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY))
extern XPT_PUBLIC_API(PRBool)
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,