2015-07-10 02:54:59 +03:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
2012-05-21 15:12:37 +04:00
/* 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/. */
2000-03-28 09:10:05 +04:00
/* Implementation of xptiInterfaceInfoManager. */
2013-11-28 05:05:00 +04:00
# include "mozilla/XPTInterfaceInfoManager.h"
2013-11-07 09:35:30 +04:00
2013-11-07 09:35:30 +04:00
# include "mozilla/FileUtils.h"
# include "mozilla/MemoryReporting.h"
2013-12-08 09:41:32 +04:00
# include "mozilla/StaticPtr.h"
2013-11-07 09:35:30 +04:00
2000-03-28 09:10:05 +04:00
# include "xptiprivate.h"
2002-04-27 09:33:09 +04:00
# include "nsDependentString.h"
# include "nsString.h"
2009-04-18 02:38:11 +04:00
# include "nsArrayEnumerator.h"
2010-06-10 22:11:11 +04:00
# include "nsDirectoryService.h"
2012-06-19 04:10:08 +04:00
# include "nsIMemoryReporter.h"
2000-03-28 09:10:05 +04:00
Rollup of bug 645263 and bug 646259: Switch to mozilla:: sync primitives. r=cjones,dbaron,doublec,ehsan src=bsmedberg
Bug 645263, part 0: Count sync primitive ctor/dtors. r=dbaron
Bug 645263, part 1: Migrate content/media to mozilla:: sync primitives. r=doublec
Bug 645263, part 2: Migrate modules/plugin to mozilla:: sync primitives. sr=bsmedberg
Bug 645263, part 3: Migrate nsComponentManagerImpl to mozilla:: sync primitives. sr=bsmedberg
Bug 645263, part 4: Migrate everything else to mozilla:: sync primitives. r=dbaron
Bug 645263, part 5: Remove nsAutoLock.*. sr=bsmedberg
Bug 645263, part 6: Make editor test be nicer to deadlock detector. r=ehsan
Bug 645263, part 7: Disable tracemalloc backtraces for xpcshell tests. r=dbaron
Bug 646259: Fix nsCacheService to use a CondVar for notifying. r=cjones
2011-04-01 08:29:02 +04:00
using namespace mozilla ;
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS (
2013-11-07 09:35:30 +04:00
XPTInterfaceInfoManager ,
2013-12-08 10:09:10 +04:00
nsIInterfaceInfoManager ,
nsIMemoryReporter )
2000-03-28 09:10:05 +04:00
2013-12-08 09:41:32 +04:00
static StaticRefPtr < XPTInterfaceInfoManager > gInterfaceInfoManager ;
2000-03-28 09:10:05 +04:00
2012-06-19 04:10:08 +04:00
size_t
2013-11-07 09:35:30 +04:00
XPTInterfaceInfoManager : : SizeOfIncludingThis ( mozilla : : MallocSizeOf aMallocSizeOf )
2012-06-19 04:10:08 +04:00
{
size_t n = aMallocSizeOf ( this ) ;
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
// The entries themselves are allocated out of an arena accounted
// for elsewhere, so don't measure them
2015-07-31 07:19:57 +03:00
n + = mWorkingSet . mIIDTable . ShallowSizeOfExcludingThis ( aMallocSizeOf ) ;
n + = mWorkingSet . mNameTable . ShallowSizeOfExcludingThis ( aMallocSizeOf ) ;
2012-06-19 04:10:08 +04:00
return n ;
}
2013-12-08 10:09:10 +04:00
MOZ_DEFINE_MALLOC_SIZE_OF ( XPTIMallocSizeOf )
NS_IMETHODIMP
XPTInterfaceInfoManager : : CollectReports ( nsIHandleReportCallback * aHandleReport ,
2014-05-21 10:06:54 +04:00
nsISupports * aData , bool aAnonymize )
2012-06-19 04:10:08 +04:00
{
2013-12-08 10:09:10 +04:00
size_t amount = SizeOfIncludingThis ( XPTIMallocSizeOf ) ;
2013-11-07 09:35:30 +04:00
// Measure gXPTIStructArena here, too. This is a bit grotty because it
// doesn't belong to the XPTIInterfaceInfoManager, but there's no
// obviously better place to measure it.
2016-02-23 08:17:58 +03:00
amount + = XPT_SizeOfArenaIncludingThis ( gXPTIStructArena , XPTIMallocSizeOf ) ;
2013-11-07 09:35:30 +04:00
2016-08-24 08:23:45 +03:00
MOZ_COLLECT_REPORT (
2013-12-08 10:09:10 +04:00
" explicit/xpti-working-set " , KIND_HEAP , UNITS_BYTES , amount ,
" Memory used by the XPCOM typelib system. " ) ;
2016-08-24 08:23:45 +03:00
return NS_OK ;
2013-11-07 09:35:30 +04:00
}
2012-06-19 04:10:08 +04:00
2000-03-28 09:10:05 +04:00
// static
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager *
XPTInterfaceInfoManager : : GetSingleton ( )
2000-03-28 09:10:05 +04:00
{
2010-06-11 21:35:25 +04:00
if ( ! gInterfaceInfoManager ) {
2013-03-09 06:54:10 +04:00
gInterfaceInfoManager = new XPTInterfaceInfoManager ( ) ;
2013-11-07 09:35:30 +04:00
gInterfaceInfoManager - > InitMemoryReporter ( ) ;
2000-03-28 09:10:05 +04:00
}
return gInterfaceInfoManager ;
}
void
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : FreeInterfaceInfoManager ( )
2000-03-28 09:10:05 +04:00
{
2013-12-08 09:41:32 +04:00
gInterfaceInfoManager = nullptr ;
2000-03-28 09:10:05 +04:00
}
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : XPTInterfaceInfoManager ( )
2013-12-08 10:09:10 +04:00
: mWorkingSet ( ) ,
2013-03-09 06:54:10 +04:00
mResolveLock ( " XPTInterfaceInfoManager.mResolveLock " )
2000-03-28 09:10:05 +04:00
{
}
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : ~ XPTInterfaceInfoManager ( )
2000-03-28 09:10:05 +04:00
{
// We only do this on shutdown of the service.
mWorkingSet . InvalidateInterfaceInfos ( ) ;
2000-04-22 10:28:44 +04:00
2013-11-07 09:35:30 +04:00
UnregisterWeakMemoryReporter ( this ) ;
2000-03-28 09:10:05 +04:00
}
2013-11-07 09:35:30 +04:00
void
XPTInterfaceInfoManager : : InitMemoryReporter ( )
{
RegisterWeakMemoryReporter ( this ) ;
}
2011-11-08 21:10:51 +04:00
void
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : RegisterBuffer ( char * buf , uint32_t length )
2000-03-28 09:10:05 +04:00
{
2016-02-22 21:33:35 +03:00
XPTState state ;
XPT_InitXDRState ( & state , buf , length ) ;
2000-03-28 09:10:05 +04:00
2016-05-27 02:49:26 +03:00
XPTCursor curs ;
NotNull < XPTCursor * > cursor = WrapNotNull ( & curs ) ;
if ( ! XPT_MakeCursor ( & state , XPT_HEADER , 0 , cursor ) ) {
2011-11-08 21:10:51 +04:00
return ;
2000-03-28 09:10:05 +04:00
}
2012-07-30 18:20:58 +04:00
XPTHeader * header = nullptr ;
2016-05-27 02:49:26 +03:00
if ( XPT_DoHeader ( gXPTIStructArena , cursor , & header ) ) {
2011-11-08 21:10:51 +04:00
RegisterXPTHeader ( header ) ;
2000-03-28 09:10:05 +04:00
}
2010-06-10 20:51:29 +04:00
}
2000-03-28 09:10:05 +04:00
2010-06-10 20:51:29 +04:00
void
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : RegisterXPTHeader ( XPTHeader * aHeader )
2000-04-15 03:06:39 +04:00
{
2010-06-10 20:51:29 +04:00
if ( aHeader - > major_version > = XPT_MAJOR_INCOMPATIBLE_VERSION ) {
NS_ASSERTION ( ! aHeader - > num_interfaces , " bad libxpt " ) ;
LOG_AUTOREG ( ( " file is version %d.%d Type file of version %d.0 or higher can not be read. \n " , ( int ) header - > major_version , ( int ) header - > minor_version , ( int ) XPT_MAJOR_INCOMPATIBLE_VERSION ) ) ;
2000-04-15 03:06:39 +04:00
}
2000-03-28 09:10:05 +04:00
2010-06-10 20:51:29 +04:00
xptiTypelibGuts * typelib = xptiTypelibGuts : : Create ( aHeader ) ;
2000-09-20 01:42:47 +04:00
2011-04-29 23:21:57 +04:00
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
2012-08-22 19:56:38 +04:00
for ( uint16_t k = 0 ; k < aHeader - > num_interfaces ; k + + )
2010-06-10 20:51:29 +04:00
VerifyAndAddEntryIfNew ( aHeader - > interface_directory + k , k , typelib ) ;
}
2002-04-05 02:24:50 +04:00
2010-06-10 20:51:29 +04:00
void
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : VerifyAndAddEntryIfNew ( XPTInterfaceDirectoryEntry * iface ,
uint16_t idx ,
xptiTypelibGuts * typelib )
2000-03-28 09:10:05 +04:00
{
2010-06-10 20:51:29 +04:00
if ( ! iface - > interface_descriptor )
return ;
2011-08-05 22:34:13 +04:00
// The number of maximum methods is not arbitrary. It is the same value as
2014-06-30 19:39:46 +04:00
// in xpcom/reflect/xptcall/genstubs.pl; do not change this value
2011-08-05 22:34:13 +04:00
// without changing that one or you WILL see problems.
if ( iface - > interface_descriptor - > num_methods > 250 & &
! ( XPT_ID_IS_BUILTINCLASS ( iface - > interface_descriptor - > flags ) ) ) {
NS_ASSERTION ( 0 , " Too many methods to handle for the stub, cannot load " ) ;
fprintf ( stderr , " ignoring too large interface: %s \n " , iface - > name ) ;
return ;
}
2016-08-23 16:05:01 +03:00
2011-04-29 23:21:57 +04:00
mWorkingSet . mTableReentrantMonitor . AssertCurrentThreadIn ( ) ;
2010-06-10 20:51:29 +04:00
xptiInterfaceEntry * entry = mWorkingSet . mIIDTable . Get ( iface - > iid ) ;
2010-06-11 21:35:25 +04:00
if ( entry ) {
2000-03-28 09:10:05 +04:00
// XXX validate this info to find possible inconsistencies
2000-04-15 03:06:39 +04:00
LOG_AUTOREG ( ( " ignoring repeated interface: %s \n " , iface - > name ) ) ;
2010-06-10 20:51:29 +04:00
return ;
2000-03-28 09:10:05 +04:00
}
2016-08-23 16:05:01 +03:00
// Build a new xptiInterfaceEntry object and hook it up.
2000-03-28 09:10:05 +04:00
2010-06-10 20:51:29 +04:00
entry = xptiInterfaceEntry : : Create ( iface - > name ,
iface - > iid ,
iface - > interface_descriptor ,
typelib ) ;
2010-06-11 21:35:25 +04:00
if ( ! entry )
2010-06-10 20:51:29 +04:00
return ;
2000-03-28 09:10:05 +04:00
2000-04-15 03:06:39 +04:00
//XXX We should SetHeader too as part of the validation, no?
2002-01-11 02:49:47 +03:00
entry - > SetScriptableFlag ( XPT_ID_IS_SCRIPTABLE ( iface - > interface_descriptor - > flags ) ) ;
2011-06-16 23:21:25 +04:00
entry - > SetBuiltinClassFlag ( XPT_ID_IS_BUILTINCLASS ( iface - > interface_descriptor - > flags ) ) ;
2015-03-06 19:34:08 +03:00
entry - > SetMainProcessScriptableOnlyFlag (
XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY ( iface - > interface_descriptor - > flags ) ) ;
2000-04-15 03:06:39 +04:00
2010-06-10 20:51:29 +04:00
mWorkingSet . mIIDTable . Put ( entry - > IID ( ) , entry ) ;
mWorkingSet . mNameTable . Put ( entry - > GetTheName ( ) , entry ) ;
2002-01-11 02:49:47 +03:00
2010-06-10 20:51:29 +04:00
typelib - > SetEntryAt ( idx , entry ) ;
2000-04-15 03:06:39 +04:00
LOG_AUTOREG ( ( " added interface: %s \n " , iface - > name ) ) ;
2000-03-28 09:10:05 +04:00
}
2002-01-11 02:49:47 +03:00
// this is a private helper
2016-08-23 16:05:01 +03:00
static nsresult
2002-01-11 02:49:47 +03:00
EntryToInfo ( xptiInterfaceEntry * entry , nsIInterfaceInfo * * _retval )
2000-03-28 09:10:05 +04:00
{
2010-06-11 21:35:25 +04:00
if ( ! entry ) {
2012-07-30 18:20:58 +04:00
* _retval = nullptr ;
2016-08-23 16:05:01 +03:00
return NS_ERROR_FAILURE ;
2000-03-28 09:10:05 +04:00
}
2015-10-18 08:24:48 +03:00
RefPtr < xptiInterfaceInfo > info = entry - > InterfaceInfo ( ) ;
2013-05-04 05:54:31 +04:00
info . forget ( _retval ) ;
2016-08-23 16:05:01 +03:00
return NS_OK ;
2000-03-28 09:10:05 +04:00
}
2006-11-20 20:03:38 +03:00
xptiInterfaceEntry *
2013-03-09 06:54:10 +04:00
XPTInterfaceInfoManager : : GetInterfaceEntryForIID ( const nsIID * iid )
2006-11-20 20:03:38 +03:00
{
2011-04-29 23:21:57 +04:00
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
2010-06-10 20:51:29 +04:00
return mWorkingSet . mIIDTable . Get ( * iid ) ;
2006-11-20 20:03:38 +03:00
}
2013-03-09 06:54:10 +04:00
NS_IMETHODIMP
XPTInterfaceInfoManager : : GetInfoForIID ( const nsIID * iid , nsIInterfaceInfo * * _retval )
2002-01-11 02:49:47 +03:00
{
NS_ASSERTION ( iid , " bad param " ) ;
NS_ASSERTION ( _retval , " bad param " ) ;
2011-04-29 23:21:57 +04:00
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
2011-04-11 01:12:52 +04:00
xptiInterfaceEntry * entry = mWorkingSet . mIIDTable . Get ( * iid ) ;
2002-01-11 02:49:47 +03:00
return EntryToInfo ( entry , _retval ) ;
}
2013-03-09 06:54:10 +04:00
NS_IMETHODIMP
XPTInterfaceInfoManager : : GetInfoForName ( const char * name , nsIInterfaceInfo * * _retval )
2000-03-28 09:10:05 +04:00
{
NS_ASSERTION ( name , " bad param " ) ;
NS_ASSERTION ( _retval , " bad param " ) ;
2011-04-29 23:21:57 +04:00
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
2010-06-10 20:51:29 +04:00
xptiInterfaceEntry * entry = mWorkingSet . mNameTable . Get ( name ) ;
2002-01-11 02:49:47 +03:00
return EntryToInfo ( entry , _retval ) ;
2000-03-28 09:10:05 +04:00
}
2013-04-10 00:00:21 +04:00
void
XPTInterfaceInfoManager : : GetScriptableInterfaces ( nsCOMArray < nsIInterfaceInfo > & aInterfaces )
2000-03-28 09:10:05 +04:00
{
// I didn't want to incur the size overhead of using nsHashtable just to
2015-07-10 02:54:59 +03:00
// make building an enumerator easier. So, this code makes a snapshot of
2016-10-22 02:34:40 +03:00
// the table using an nsCOMArray and builds an enumerator for that.
2000-03-28 09:10:05 +04:00
// We can afford this transient cost.
2011-04-29 23:21:57 +04:00
ReentrantMonitorAutoEnter monitor ( mWorkingSet . mTableReentrantMonitor ) ;
2013-04-10 00:00:21 +04:00
aInterfaces . SetCapacity ( mWorkingSet . mNameTable . Count ( ) ) ;
2015-07-10 02:54:59 +03:00
for ( auto iter = mWorkingSet . mNameTable . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
2015-07-20 15:21:28 +03:00
xptiInterfaceEntry * entry = iter . UserData ( ) ;
2015-07-10 02:54:59 +03:00
if ( entry - > GetScriptableFlag ( ) ) {
nsCOMPtr < nsIInterfaceInfo > ii = entry - > InterfaceInfo ( ) ;
aInterfaces . AppendElement ( ii ) ;
}
}
2002-01-11 02:49:47 +03:00
}