Bug 997325 - Implement main process scriptable only flag in XPIDL (r=mrbkap)
authorBill McCloskey <billm@mozilla.com>
Fri, 06 Mar 2015 08:34:08 -0800
changeset 264887 1652874e2d978dab14dd56b39342ccb93ddee650
parent 264886 638492d777fca9f6e7bbefc1de2c5c40137a4414
child 264888 a1f0b23f51049f8abe0faef128c60e52962d9426
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs997325
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 997325 - Implement main process scriptable only flag in XPIDL (r=mrbkap)
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/XPCWrappedNativeInfo.cpp
xpcom/idl-parser/typelib.py
xpcom/idl-parser/xpidl.py
xpcom/io/nsIFile.idl
xpcom/io/nsILocalFile.idl
xpcom/io/nsILocalFileMac.idl
xpcom/io/nsILocalFileWin.idl
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
xpcom/reflect/xptinfo/xptiprivate.h
xpcom/typelib/xpt/tools/xpt.py
xpcom/typelib/xpt/xpt_struct.h
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -31,16 +31,17 @@
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "jsprf.h"
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
+#include "nsXULAppAPI.h"
 #include "WrapperFactory.h"
 
 #include "mozilla/AddonPathService.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/MacroForEach.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -367,45 +368,17 @@ mozJSComponentLoader::LoadModule(FileLoc
         return nullptr;
 
     nsCOMPtr<nsIComponentManager> cm;
     rv = NS_GetComponentManager(getter_AddRefs(cm));
     if (NS_FAILED(rv))
         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) ||
         NSGetFactory_val.isUndefined()) {
         return nullptr;
     }
 
     if (JS_TypeOfValue(cx, NSGetFactory_val) != JSTYPE_FUNCTION) {
@@ -609,27 +582,29 @@ mozJSComponentLoader::PrepareObjectForLo
     nsCOMPtr<nsIFile> testFile;
     if (NS_SUCCEEDED(rv)) {
         fileURL->GetFile(getter_AddRefs(testFile));
     }
 
     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;
     rv = aURI->GetSpec(nativePath);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     // Expose the URI from which the script was imported through a special
     // variable that we insert into the JSM.
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -6,16 +6,17 @@
 
 /* Manage the shared info about interfaces for use by wrappedNatives. */
 
 #include "xpcprivate.h"
 #include "jswrapper.h"
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
+#include "nsPrintfCString.h"
 
 using namespace JS;
 using namespace mozilla;
 
 /***************************************************************************/
 
 // XPCNativeMember
 
@@ -227,16 +228,37 @@ XPCNativeInterface::NewInstance(nsIInter
     // then make our object, but avoid init'ing *any* members until asked?
     // Find out how often we create these objects w/o really looking at
     // (or using) the members.
 
     bool canScript;
     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;
 
     // If the interface does not have nsISupports in its inheritance chain
     // then we know we can't reflect its methods. However, some interfaces that
     // are used just to reflect constants are declared this way. We need to
     // go ahead and build the thing. But, we'll ignore whatever methods it may
--- a/xpcom/idl-parser/typelib.py
+++ b/xpcom/idl-parser/typelib.py
@@ -227,17 +227,18 @@ def build_interface(iface, ifaces):
         if not parent:
             parent = xpt.Interface(name=iface.base)
             ifaces.append(parent)
 
     return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods,
                          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. """
 
     # We only care about interfaces
     ifaces = []
     for p in idl.productions:
         if p.kind == 'interface':
--- a/xpcom/idl-parser/xpidl.py
+++ b/xpcom/idl-parser/xpidl.py
@@ -577,16 +577,17 @@ class Interface(object):
 
 class InterfaceAttributes(object):
     uuid = None
     scriptable = False
     builtinclass = False
     function = False
     deprecated = False
     noscript = False
+    main_process_scriptable_only = False
 
     def setuuid(self, value):
         self.uuid = value.lower()
 
     def setscriptable(self):
         self.scriptable = True
 
     def setfunction(self):
@@ -596,24 +597,28 @@ class InterfaceAttributes(object):
         self.noscript = True
 
     def setbuiltinclass(self):
         self.builtinclass = True
 
     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),
         'builtinclass': (False, setbuiltinclass),
         'function':   (False, setfunction),
         '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):
         def badattribute(self):
             raise IDLError("Unexpected interface attribute '%s'" % name, location)
 
         for name, val, aloc in attlist:
             hasval, action = self.actions.get(name, (False, badattribute))
@@ -638,16 +643,18 @@ class InterfaceAttributes(object):
         if self.uuid:
             l.append("\tuuid: %s\n" % self.uuid)
         if self.scriptable:
             l.append("\tscriptable\n")
         if self.builtinclass:
             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):
     kind = 'const'
     def __init__(self, type, name, value, location, doccomments):
         self.type = type
         self.name = name
         self.value = value
--- a/xpcom/io/nsIFile.idl
+++ b/xpcom/io/nsIFile.idl
@@ -37,17 +37,17 @@ interface nsISimpleEnumerator;
  * All methods with string parameters have two forms.  The preferred
  * form operates on UCS-2 encoded characters strings.  An alternate
  * form operates on characters strings encoded in the "native" charset.
  *
  * A string containing characters encoded in the native charset cannot
  * 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
 {
     /**
      *  Create Types
      *
      *  NORMAL_FILE_TYPE - A normal file.
      *  DIRECTORY_TYPE   - A directory/folder.
      */
--- a/xpcom/io/nsILocalFile.idl
+++ b/xpcom/io/nsILocalFile.idl
@@ -5,13 +5,13 @@
 
 #include "nsIFile.idl"
 
 /**
  * An empty interface to provide backwards compatibility for existing code.
  *
  * @see nsIFile
  */
-[scriptable, builtinclass, uuid(ce4ef184-7660-445e-9e59-6731bdc65505)]
+[scriptable, builtinclass, uuid(7ba8c6ba-2ce2-48b1-bd60-4c32aac35f9c)]
 interface nsILocalFile : nsIFile
 {
 };
 
--- a/xpcom/io/nsILocalFileMac.idl
+++ b/xpcom/io/nsILocalFileMac.idl
@@ -11,17 +11,17 @@
 %}
 
       native OSType(OSType);
       native FSSpec(FSSpec);
       native FSRef(FSRef);
 [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
 {
    /**
     * initWithCFURL
     *
     * Init this object with a CFURLRef
     *
     * NOTE: Supported only for XP_MACOSX
--- a/xpcom/io/nsILocalFileWin.idl
+++ b/xpcom/io/nsILocalFileWin.idl
@@ -7,17 +7,17 @@
 #include "nsILocalFile.idl"
 
 %{C++
 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
 {
    /**
     * getVersionInfoValue
     *
     * Retrieve a metadata field from the file's VERSIONINFO block.
     * Throws NS_ERROR_FAILURE if no value is found, or the value is empty.
     *
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -540,16 +540,23 @@ ShimInterfaceInfo::IsScriptable(bool* aR
 NS_IMETHODIMP
 ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal)
 {
     *aRetVal = true;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal)
+{
+    *aRetVal = false;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent)
 {
     *aParent = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 ShimInterfaceInfo::GetMethodCount(uint16_t* aCount)
--- a/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
+++ b/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
@@ -19,24 +19,25 @@
 
 %{C++
 class nsXPTMethodInfo;
 class nsXPTParamInfo;
 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;
     readonly attribute nsIIDPtr InterfaceIID;
 
     boolean isScriptable();
     boolean isBuiltinClass();
+    boolean isMainProcessScriptableOnly();
 
     readonly attribute nsIInterfaceInfo parent;
 
     /**
     * These include counts for parent (and all ancestors).
     */
     readonly attribute uint16_t methodCount;
     readonly attribute uint16_t constantCount;
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
@@ -165,16 +165,18 @@ XPTInterfaceInfoManager::VerifyAndAddEnt
                                        iface->interface_descriptor,
                                        typelib);
     if (!entry)
         return;
 
     //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);
 
     typelib->SetEntryAt(idx, entry);
 
     LOG_AUTOREG(("      added interface: %s\n", iface->name));
 }
--- a/xpcom/reflect/xptinfo/xptiprivate.h
+++ b/xpcom/reflect/xptinfo/xptiprivate.h
@@ -175,31 +175,36 @@ public:
 
     enum {
         PARTIALLY_RESOLVED    = 1,
         FULLY_RESOLVED        = 2,
         RESOLVE_FAILED        = 3
     };
     
     // 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.
     void SetHasNotXPCOMFlag()
     {
         mFlags.SetFlagBit(HASNOTXPCOM, true);
     }
     bool GetHasNotXPCOMFlag() const
@@ -232,16 +237,20 @@ public:
 
     nsresult GetName(char * *aName);
     nsresult GetIID(nsIID * *aIID);
     nsresult IsScriptable(bool *_retval);
     nsresult IsBuiltinClass(bool *_retval) {
         *_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);
     nsresult GetConstantCount(uint16_t *aConstantCount);
     nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
     nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
     nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
     nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
@@ -316,16 +325,17 @@ class xptiInterfaceInfo final : public n
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
 
     // Use delegation to implement (most!) of nsIInterfaceInfo.
     NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
     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
     {
         if(!EnsureResolved() || !EnsureParent())
             return NS_ERROR_UNEXPECTED;
         NS_IF_ADDREF(*aParent = mParent);
         return NS_OK;
     }
--- a/xpcom/typelib/xpt/tools/xpt.py
+++ b/xpcom/typelib/xpt/tools/xpt.py
@@ -843,29 +843,31 @@ class Interface(object):
     """
     _direntry = struct.Struct(">16sIII")
     _descriptorstart = struct.Struct(">HH")
 
     UNRESOLVED_IID = "00000000-0000-0000-0000-000000000000"
 
     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
         self.name = name
         self.namespace = namespace
         # if unresolved, all the members following this are unusable
         self.parent = parent
         self.methods = list(methods)
         self.constants = list(constants)
         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:
             # make sure it has a valid IID
             if self.iid == Interface.UNRESOLVED_IID:
                 raise DataError, "Cannot instantiate Interface %s containing methods or constants with an unresolved IID" % self.name
             self.resolved = True
         # These are only used for writing out the interface
@@ -925,23 +927,25 @@ class Interface(object):
         for i in range(num_constants):
             c, offset = Constant.read(typelib, map, data_pool, offset)
             self.constants.append(c)
         # Read flags
         start = data_pool + offset - 1
         (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):
         """
         Write an InterfaceDirectoryEntry for this interface
         to |file|, which is assumed to be seeked to the correct offset.
 
         """
@@ -972,16 +976,18 @@ class Interface(object):
             c.write(typelib, file)
         flags = 0
         if self.scriptable:
             flags |= 0x80
         if self.function:
             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):
         """
         Write this interface's name and namespace to |file|,
         as well as the names of all of its methods and constants.
         Assumes that |file| is currently seeked to an unused portion
         of the data pool.
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -234,23 +234,23 @@ struct XPTInterfaceDescriptor {
     */
 
     uint16_t                num_additional_types;
 };
 
 #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,
                             uint16_t num_interfaces, const char *name,
                             uint16_t *indexp);
 
 extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
 XPT_NewInterfaceDescriptor(XPTArena *arena,