xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /* Implementation of xptiInterfaceInfoManager. */
michael@0 8
michael@0 9 #include "mozilla/XPTInterfaceInfoManager.h"
michael@0 10
michael@0 11 #include "mozilla/FileUtils.h"
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13 #include "mozilla/StaticPtr.h"
michael@0 14
michael@0 15 #include "xptiprivate.h"
michael@0 16 #include "nsDependentString.h"
michael@0 17 #include "nsString.h"
michael@0 18 #include "nsISupportsArray.h"
michael@0 19 #include "nsArrayEnumerator.h"
michael@0 20 #include "nsDirectoryService.h"
michael@0 21 #include "nsIMemoryReporter.h"
michael@0 22
michael@0 23 using namespace mozilla;
michael@0 24
michael@0 25 NS_IMPL_ISUPPORTS(
michael@0 26 XPTInterfaceInfoManager,
michael@0 27 nsIInterfaceInfoManager,
michael@0 28 nsIMemoryReporter)
michael@0 29
michael@0 30 static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
michael@0 31
michael@0 32 size_t
michael@0 33 XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
michael@0 34 {
michael@0 35 size_t n = aMallocSizeOf(this);
michael@0 36 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 37 // The entries themselves are allocated out of an arena accounted
michael@0 38 // for elsewhere, so don't measure them
michael@0 39 n += mWorkingSet.mIIDTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
michael@0 40 n += mWorkingSet.mNameTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
michael@0 41 return n;
michael@0 42 }
michael@0 43
michael@0 44 MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
michael@0 45
michael@0 46 NS_IMETHODIMP
michael@0 47 XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
michael@0 48 nsISupports* aData)
michael@0 49 {
michael@0 50 size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
michael@0 51
michael@0 52 // Measure gXPTIStructArena here, too. This is a bit grotty because it
michael@0 53 // doesn't belong to the XPTIInterfaceInfoManager, but there's no
michael@0 54 // obviously better place to measure it.
michael@0 55 amount += XPT_SizeOfArena(gXPTIStructArena, XPTIMallocSizeOf);
michael@0 56
michael@0 57 return MOZ_COLLECT_REPORT(
michael@0 58 "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
michael@0 59 "Memory used by the XPCOM typelib system.");
michael@0 60 }
michael@0 61
michael@0 62 // static
michael@0 63 XPTInterfaceInfoManager*
michael@0 64 XPTInterfaceInfoManager::GetSingleton()
michael@0 65 {
michael@0 66 if (!gInterfaceInfoManager) {
michael@0 67 gInterfaceInfoManager = new XPTInterfaceInfoManager();
michael@0 68 gInterfaceInfoManager->InitMemoryReporter();
michael@0 69 }
michael@0 70 return gInterfaceInfoManager;
michael@0 71 }
michael@0 72
michael@0 73 void
michael@0 74 XPTInterfaceInfoManager::FreeInterfaceInfoManager()
michael@0 75 {
michael@0 76 gInterfaceInfoManager = nullptr;
michael@0 77 }
michael@0 78
michael@0 79 XPTInterfaceInfoManager::XPTInterfaceInfoManager()
michael@0 80 : mWorkingSet(),
michael@0 81 mResolveLock("XPTInterfaceInfoManager.mResolveLock")
michael@0 82 {
michael@0 83 }
michael@0 84
michael@0 85 XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
michael@0 86 {
michael@0 87 // We only do this on shutdown of the service.
michael@0 88 mWorkingSet.InvalidateInterfaceInfos();
michael@0 89
michael@0 90 UnregisterWeakMemoryReporter(this);
michael@0 91 }
michael@0 92
michael@0 93 void
michael@0 94 XPTInterfaceInfoManager::InitMemoryReporter()
michael@0 95 {
michael@0 96 RegisterWeakMemoryReporter(this);
michael@0 97 }
michael@0 98
michael@0 99 void
michael@0 100 XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
michael@0 101 {
michael@0 102 XPTState *state = XPT_NewXDRState(XPT_DECODE, buf, length);
michael@0 103 if (!state)
michael@0 104 return;
michael@0 105
michael@0 106 XPTCursor cursor;
michael@0 107 if (!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor)) {
michael@0 108 XPT_DestroyXDRState(state);
michael@0 109 return;
michael@0 110 }
michael@0 111
michael@0 112 XPTHeader *header = nullptr;
michael@0 113 if (XPT_DoHeader(gXPTIStructArena, &cursor, &header)) {
michael@0 114 RegisterXPTHeader(header);
michael@0 115 }
michael@0 116
michael@0 117 XPT_DestroyXDRState(state);
michael@0 118 }
michael@0 119
michael@0 120 void
michael@0 121 XPTInterfaceInfoManager::RegisterXPTHeader(XPTHeader* aHeader)
michael@0 122 {
michael@0 123 if (aHeader->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
michael@0 124 NS_ASSERTION(!aHeader->num_interfaces,"bad libxpt");
michael@0 125 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));
michael@0 126 }
michael@0 127
michael@0 128 xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader);
michael@0 129
michael@0 130 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 131 for(uint16_t k = 0; k < aHeader->num_interfaces; k++)
michael@0 132 VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib);
michael@0 133 }
michael@0 134
michael@0 135 void
michael@0 136 XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface,
michael@0 137 uint16_t idx,
michael@0 138 xptiTypelibGuts* typelib)
michael@0 139 {
michael@0 140 if (!iface->interface_descriptor)
michael@0 141 return;
michael@0 142
michael@0 143 // The number of maximum methods is not arbitrary. It is the same value as
michael@0 144 // in xpcom/reflect/xptcall/public/genstubs.pl; do not change this value
michael@0 145 // without changing that one or you WILL see problems.
michael@0 146 if (iface->interface_descriptor->num_methods > 250 &&
michael@0 147 !(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags))) {
michael@0 148 NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
michael@0 149 fprintf(stderr, "ignoring too large interface: %s\n", iface->name);
michael@0 150 return;
michael@0 151 }
michael@0 152
michael@0 153 mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
michael@0 154 xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid);
michael@0 155 if (entry) {
michael@0 156 // XXX validate this info to find possible inconsistencies
michael@0 157 LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
michael@0 158 return;
michael@0 159 }
michael@0 160
michael@0 161 // Build a new xptiInterfaceEntry object and hook it up.
michael@0 162
michael@0 163 entry = xptiInterfaceEntry::Create(iface->name,
michael@0 164 iface->iid,
michael@0 165 iface->interface_descriptor,
michael@0 166 typelib);
michael@0 167 if (!entry)
michael@0 168 return;
michael@0 169
michael@0 170 //XXX We should SetHeader too as part of the validation, no?
michael@0 171 entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
michael@0 172 entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags));
michael@0 173
michael@0 174 mWorkingSet.mIIDTable.Put(entry->IID(), entry);
michael@0 175 mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);
michael@0 176
michael@0 177 typelib->SetEntryAt(idx, entry);
michael@0 178
michael@0 179 LOG_AUTOREG((" added interface: %s\n", iface->name));
michael@0 180 }
michael@0 181
michael@0 182 // this is a private helper
michael@0 183 static nsresult
michael@0 184 EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
michael@0 185 {
michael@0 186 if (!entry) {
michael@0 187 *_retval = nullptr;
michael@0 188 return NS_ERROR_FAILURE;
michael@0 189 }
michael@0 190
michael@0 191 nsRefPtr<xptiInterfaceInfo> info = entry->InterfaceInfo();
michael@0 192 info.forget(_retval);
michael@0 193 return NS_OK;
michael@0 194 }
michael@0 195
michael@0 196 xptiInterfaceEntry*
michael@0 197 XPTInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid)
michael@0 198 {
michael@0 199 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 200 return mWorkingSet.mIIDTable.Get(*iid);
michael@0 201 }
michael@0 202
michael@0 203 /* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */
michael@0 204 NS_IMETHODIMP
michael@0 205 XPTInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
michael@0 206 {
michael@0 207 NS_ASSERTION(iid, "bad param");
michael@0 208 NS_ASSERTION(_retval, "bad param");
michael@0 209
michael@0 210 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 211 xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
michael@0 212 return EntryToInfo(entry, _retval);
michael@0 213 }
michael@0 214
michael@0 215 /* nsIInterfaceInfo getInfoForName (in string name); */
michael@0 216 NS_IMETHODIMP
michael@0 217 XPTInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
michael@0 218 {
michael@0 219 NS_ASSERTION(name, "bad param");
michael@0 220 NS_ASSERTION(_retval, "bad param");
michael@0 221
michael@0 222 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 223 xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
michael@0 224 return EntryToInfo(entry, _retval);
michael@0 225 }
michael@0 226
michael@0 227 /* nsIIDPtr getIIDForName (in string name); */
michael@0 228 NS_IMETHODIMP
michael@0 229 XPTInterfaceInfoManager::GetIIDForName(const char *name, nsIID * *_retval)
michael@0 230 {
michael@0 231 NS_ASSERTION(name, "bad param");
michael@0 232 NS_ASSERTION(_retval, "bad param");
michael@0 233
michael@0 234 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 235 xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
michael@0 236 if (!entry) {
michael@0 237 *_retval = nullptr;
michael@0 238 return NS_ERROR_FAILURE;
michael@0 239 }
michael@0 240
michael@0 241 return entry->GetIID(_retval);
michael@0 242 }
michael@0 243
michael@0 244 /* string getNameForIID (in nsIIDPtr iid); */
michael@0 245 NS_IMETHODIMP
michael@0 246 XPTInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **_retval)
michael@0 247 {
michael@0 248 NS_ASSERTION(iid, "bad param");
michael@0 249 NS_ASSERTION(_retval, "bad param");
michael@0 250
michael@0 251 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 252 xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
michael@0 253 if (!entry) {
michael@0 254 *_retval = nullptr;
michael@0 255 return NS_ERROR_FAILURE;
michael@0 256 }
michael@0 257
michael@0 258 return entry->GetName(_retval);
michael@0 259 }
michael@0 260
michael@0 261 static PLDHashOperator
michael@0 262 xpti_ArrayAppender(const char* name, xptiInterfaceEntry* entry, void* arg)
michael@0 263 {
michael@0 264 nsCOMArray<nsIInterfaceInfo>* array = static_cast<nsCOMArray<nsIInterfaceInfo>*>(arg);
michael@0 265
michael@0 266 if (entry->GetScriptableFlag()) {
michael@0 267 nsCOMPtr<nsIInterfaceInfo> ii = entry->InterfaceInfo();
michael@0 268 array->AppendElement(ii);
michael@0 269 }
michael@0 270 return PL_DHASH_NEXT;
michael@0 271 }
michael@0 272
michael@0 273 /* nsIEnumerator enumerateInterfaces (); */
michael@0 274 void
michael@0 275 XPTInterfaceInfoManager::GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces)
michael@0 276 {
michael@0 277 // I didn't want to incur the size overhead of using nsHashtable just to
michael@0 278 // make building an enumerator easier. So, this code makes a snapshot of
michael@0 279 // the table using an nsISupportsArray and builds an enumerator for that.
michael@0 280 // We can afford this transient cost.
michael@0 281
michael@0 282 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 283 aInterfaces.SetCapacity(mWorkingSet.mNameTable.Count());
michael@0 284 mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayAppender, &aInterfaces);
michael@0 285 }
michael@0 286
michael@0 287 struct ArrayAndPrefix
michael@0 288 {
michael@0 289 nsISupportsArray* array;
michael@0 290 const char* prefix;
michael@0 291 uint32_t length;
michael@0 292 };
michael@0 293
michael@0 294 static PLDHashOperator
michael@0 295 xpti_ArrayPrefixAppender(const char* keyname, xptiInterfaceEntry* entry, void* arg)
michael@0 296 {
michael@0 297 ArrayAndPrefix* args = (ArrayAndPrefix*) arg;
michael@0 298
michael@0 299 const char* name = entry->GetTheName();
michael@0 300 if (name != PL_strnstr(name, args->prefix, args->length))
michael@0 301 return PL_DHASH_NEXT;
michael@0 302
michael@0 303 nsCOMPtr<nsIInterfaceInfo> ii;
michael@0 304 if (NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
michael@0 305 args->array->AppendElement(ii);
michael@0 306 return PL_DHASH_NEXT;
michael@0 307 }
michael@0 308
michael@0 309 /* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */
michael@0 310 NS_IMETHODIMP
michael@0 311 XPTInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval)
michael@0 312 {
michael@0 313 nsCOMPtr<nsISupportsArray> array;
michael@0 314 NS_NewISupportsArray(getter_AddRefs(array));
michael@0 315 if (!array)
michael@0 316 return NS_ERROR_UNEXPECTED;
michael@0 317
michael@0 318 ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
michael@0 319 ArrayAndPrefix args = {array, prefix, static_cast<uint32_t>(strlen(prefix))};
michael@0 320 mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayPrefixAppender, &args);
michael@0 321
michael@0 322 return array->Enumerate(_retval);
michael@0 323 }
michael@0 324
michael@0 325 /* void autoRegisterInterfaces (); */
michael@0 326 NS_IMETHODIMP
michael@0 327 XPTInterfaceInfoManager::AutoRegisterInterfaces()
michael@0 328 {
michael@0 329 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 330 }

mercurial