Backed out 7 changesets (bug 1438688) for android xpcshell failures on builds/worker/workspace/build/tests/bin/components/test_necko.xpt
authorDorel Luca <dluca@mozilla.com>
Tue, 03 Apr 2018 02:30:53 +0300
changeset 411373 70400746eb530da029289760b9bab836558f9824
parent 411372 884742db27967213b57d081b49671d1b8348f60e
child 411374 720ffa73f567809363331c3331bf82b2f1af3c68
push id33753
push userdluca@mozilla.com
push dateTue, 03 Apr 2018 04:03:03 +0000
treeherdermozilla-central@720ffa73f567 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1438688
milestone61.0a1
backs out8786eabb61a41e1b83b69bf8f1f30d135184c404
e05ec1e08b46732b5552a48fe48d32108f9cca4c
4c437ba9d9841597038e36a6244f428b8cf01816
2f243bca1af344ee781aaa616147016b26d74693
4da0e1839353bcfbd378ecf842b102a2641682c6
186f916dcc7aabfea7981702c47c666338fcf869
08b1a5f904e447b46dd1f93551f01f8f10c87239
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
Backed out 7 changesets (bug 1438688) for android xpcshell failures on builds/worker/workspace/build/tests/bin/components/test_necko.xpt Backed out changeset 8786eabb61a4 (bug 1438688) Backed out changeset e05ec1e08b46 (bug 1438688) Backed out changeset 4c437ba9d984 (bug 1438688) Backed out changeset 2f243bca1af3 (bug 1438688) Backed out changeset 4da0e1839353 (bug 1438688) Backed out changeset 186f916dcc7a (bug 1438688) Backed out changeset 08b1a5f904e4 (bug 1438688)
browser/installer/package-manifest.in
browser/moz.build
build/moz.build
build/prebuilt-interfaces.manifest
config/faster/rules.mk
config/makefiles/xpidl/Makefile.in
js/xpconnect/tests/idl/moz.build
mobile/android/installer/package-manifest.in
netwerk/test/httpserver/moz.build
python/mozbuild/mozbuild/artifacts.py
python/mozbuild/mozbuild/backend/common.py
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/context.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
toolkit/mozapps/installer/packager.py
xpcom/components/ManifestParser.cpp
xpcom/components/nsComponentManager.cpp
xpcom/components/nsComponentManager.h
xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
xpcom/reflect/xptinfo/xptinfo.h
xpcom/reflect/xptinfo/xptiprivate.h
xpcom/tests/moz.build
xpcom/typelib/xpt/moz.build
xpcom/typelib/xpt/tools/xpt.py
xpcom/typelib/xpt/xpt_struct.cpp
xpcom/typelib/xpt/xpt_struct.h
xpcom/typelib/xpt/xpt_xdr.cpp
xpcom/typelib/xpt/xpt_xdr.h
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -144,24 +144,200 @@
 #ifdef _AMD64_
 @BINPATH@/@DLL_PREFIX@qipcap64@DLL_SUFFIX@
 #else
 @BINPATH@/@DLL_PREFIX@qipcap@DLL_SUFFIX@
 #endif
 #endif
 
 ; [Components]
+#ifdef MOZ_ARTIFACT_BUILDS
+@RESPATH@/components/prebuilt-interfaces.manifest
+@RESPATH@/components/interfaces.xpt
+@RESPATH@/browser/components/prebuilt-interfaces.manifest
+@RESPATH@/browser/components/interfaces.xpt
+#endif
+@RESPATH@/components/alerts.xpt
 #ifdef ACCESSIBILITY
 #ifdef XP_WIN32
 @BINPATH@/Accessible.tlb
 @BINPATH@/AccessibleHandler.dll
 @BINPATH@/AccessibleMarshal.dll
 @BINPATH@/IA2Marshal.dll
 #endif
+@RESPATH@/components/accessibility.xpt
 #endif
+@RESPATH@/components/appshell.xpt
+@RESPATH@/components/appstartup.xpt
+@RESPATH@/components/autocomplete.xpt
+@RESPATH@/components/autoconfig.xpt
+@RESPATH@/components/browser-element.xpt
+@RESPATH@/browser/components/browsercompsbase.xpt
+@RESPATH@/browser/components/browser-feeds.xpt
+@RESPATH@/components/caps.xpt
+@RESPATH@/components/chrome.xpt
+#ifdef MOZ_CODE_COVERAGE
+@RESPATH@/components/code-coverage.xpt
+#endif
+@RESPATH@/components/commandhandler.xpt
+@RESPATH@/components/commandlines.xpt
+@RESPATH@/components/composer.xpt
+@RESPATH@/components/content_events.xpt
+@RESPATH@/components/content_html.xpt
+@RESPATH@/components/content_geckomediaplugins.xpt
+#ifdef MOZ_WEBRTC
+@RESPATH@/components/content_webrtc.xpt
+#endif
+@RESPATH@/components/content_xslt.xpt
+@RESPATH@/components/directory.xpt
+@RESPATH@/components/docshell.xpt
+@RESPATH@/components/dom.xpt
+@RESPATH@/components/dom_base.xpt
+@RESPATH@/components/dom_bindings.xpt
+#ifdef MOZ_DEBUG
+@RESPATH@/components/dom_bindings_test.xpt
+#endif
+@RESPATH@/components/dom_file.xpt
+@RESPATH@/components/dom_system.xpt
+@RESPATH@/components/dom_core.xpt
+@RESPATH@/components/dom_events.xpt
+@RESPATH@/components/dom_geolocation.xpt
+@RESPATH@/components/dom_media.xpt
+@RESPATH@/components/dom_network.xpt
+@RESPATH@/components/dom_notification.xpt
+@RESPATH@/components/dom_html.xpt
+@RESPATH@/components/dom_offline.xpt
+@RESPATH@/components/dom_payments.xpt
+@RESPATH@/components/dom_power.xpt
+@RESPATH@/components/dom_push.xpt
+@RESPATH@/components/dom_quota.xpt
+@RESPATH@/components/dom_range.xpt
+@RESPATH@/components/dom_security.xpt
+@RESPATH@/components/dom_sidebar.xpt
+@RESPATH@/components/dom_storage.xpt
+@RESPATH@/components/dom_webauthn.xpt
+#ifdef MOZ_WEBSPEECH
+@RESPATH@/components/dom_webspeechrecognition.xpt
+#endif
+@RESPATH@/components/dom_workers.xpt
+@RESPATH@/components/dom_xul.xpt
+@RESPATH@/components/dom_presentation.xpt
+@RESPATH@/components/downloads.xpt
+@RESPATH@/components/editor.xpt
+@RESPATH@/components/enterprisepolicies.xpt
+@RESPATH@/components/extensions.xpt
+@RESPATH@/components/exthandler.xpt
+@RESPATH@/components/fastfind.xpt
+@RESPATH@/components/feeds.xpt
+@RESPATH@/components/gfx.xpt
+@RESPATH@/components/html5.xpt
+@RESPATH@/components/htmlparser.xpt
+@RESPATH@/components/imglib2.xpt
+@RESPATH@/components/inspector.xpt
+@RESPATH@/components/intl.xpt
+@RESPATH@/components/jar.xpt
+@RESPATH@/components/jsdebugger.xpt
+@RESPATH@/browser/components/jsinspector.xpt
+@RESPATH@/components/layout_base.xpt
+#ifdef MOZ_DEBUG
+@RESPATH@/components/layout_debug.xpt
+#endif
+#ifdef NS_PRINTING
+@RESPATH@/components/layout_printing.xpt
+#endif
+@RESPATH@/components/layout_xul_tree.xpt
+@RESPATH@/components/layout_xul.xpt
+@RESPATH@/components/locale.xpt
+@RESPATH@/browser/components/migration.xpt
+@RESPATH@/components/mimetype.xpt
+@RESPATH@/components/mozfind.xpt
+@RESPATH@/components/mozintl.xpt
+@RESPATH@/components/necko_about.xpt
+@RESPATH@/components/necko_cache.xpt
+@RESPATH@/components/necko_cache2.xpt
+@RESPATH@/components/necko_cookie.xpt
+@RESPATH@/components/necko_dns.xpt
+@RESPATH@/components/necko_file.xpt
+@RESPATH@/components/necko_ftp.xpt
+@RESPATH@/components/necko_http.xpt
+@RESPATH@/components/necko_mdns.xpt
+@RESPATH@/components/necko_res.xpt
+@RESPATH@/components/necko_socket.xpt
+@RESPATH@/components/necko_strconv.xpt
+@RESPATH@/components/necko_viewsource.xpt
+@RESPATH@/components/necko_websocket.xpt
+#ifdef NECKO_WIFI
+@RESPATH@/components/necko_wifi.xpt
+#endif
+@RESPATH@/components/necko_wyciwyg.xpt
+@RESPATH@/components/necko.xpt
+@RESPATH@/components/loginmgr.xpt
+@RESPATH@/components/parentalcontrols.xpt
+#ifdef MOZ_WEBRTC
+@RESPATH@/components/peerconnection.xpt
+#endif
+@RESPATH@/components/places.xpt
+@RESPATH@/components/plugin.xpt
+@RESPATH@/components/pref.xpt
+@RESPATH@/components/prefetch.xpt
+#ifdef MOZ_GECKO_PROFILER
+@RESPATH@/components/profiler.xpt
+#endif
+@RESPATH@/components/rdf.xpt
+@RESPATH@/components/reputationservice.xpt
+@RESPATH@/components/satchel.xpt
+@RESPATH@/components/saxparser.xpt
+@RESPATH@/browser/components/sessionstore.xpt
+@RESPATH@/components/services-crypto-component.xpt
+@RESPATH@/components/captivedetect.xpt
+@RESPATH@/browser/components/shellservice.xpt
+@RESPATH@/components/shistory.xpt
+@RESPATH@/components/spellchecker.xpt
+@RESPATH@/components/storage.xpt
+#ifdef ENABLE_MARIONETTE
+@RESPATH@/components/remote.xpt
+#endif
+@RESPATH@/components/toolkit_asyncshutdown.xpt
+@RESPATH@/components/toolkit_filewatcher.xpt
+@RESPATH@/components/toolkit_finalizationwitness.xpt
+@RESPATH@/components/toolkit_osfile.xpt
+@RESPATH@/components/toolkit_securityreporter.xpt
+@RESPATH@/components/toolkit_perfmonitoring.xpt
+@RESPATH@/components/toolkit_xulstore.xpt
+@RESPATH@/components/toolkitprofile.xpt
+#ifdef MOZ_ENABLE_XREMOTE
+@RESPATH@/components/toolkitremote.xpt
+#endif
+@RESPATH@/components/txtsvc.xpt
+@RESPATH@/components/txmgr.xpt
+@RESPATH@/components/uconv.xpt
+@RESPATH@/components/update.xpt
+@RESPATH@/components/uriloader.xpt
+@RESPATH@/components/urlformatter.xpt
+@RESPATH@/components/webBrowser_core.xpt
+@RESPATH@/components/webbrowserpersist.xpt
+@RESPATH@/components/webextensions.xpt
+@RESPATH@/components/widget.xpt
+#ifdef XP_MACOSX
+@RESPATH@/components/widget_cocoa.xpt
+#endif
+@RESPATH@/components/windowcreator.xpt
+@RESPATH@/components/windowwatcher.xpt
+@RESPATH@/components/xpcom_base.xpt
+@RESPATH@/components/xpcom_system.xpt
+@RESPATH@/components/xpcom_components.xpt
+@RESPATH@/components/xpcom_ds.xpt
+@RESPATH@/components/xpcom_io.xpt
+@RESPATH@/components/xpcom_threads.xpt
+@RESPATH@/components/xpcom_xpti.xpt
+@RESPATH@/components/xpconnect.xpt
+@RESPATH@/components/xulapp.xpt
+@RESPATH@/components/xul.xpt
+@RESPATH@/components/zipwriter.xpt
+@RESPATH@/components/telemetry.xpt
 
 ; JavaScript components
 @RESPATH@/components/ConsoleAPI.manifest
 @RESPATH@/components/ConsoleAPIStorage.js
 @RESPATH@/components/BrowserElementParent.manifest
 @RESPATH@/components/BrowserElementParent.js
 @RESPATH@/components/FeedProcessor.manifest
 @RESPATH@/components/FeedProcessor.js
@@ -190,23 +366,25 @@
 @RESPATH@/browser/components/aboutdevtools-registration.js
 @RESPATH@/browser/components/aboutdevtools.manifest
 @RESPATH@/browser/components/aboutdevtoolstoolbox-registration.js
 @RESPATH@/browser/components/aboutdevtoolstoolbox.manifest
 @RESPATH@/browser/components/nsAboutCapabilities.js
 @RESPATH@/browser/components/aboutcapabilities.manifest
 @RESPATH@/browser/components/Experiments.manifest
 @RESPATH@/browser/components/ExperimentsService.js
+@RESPATH@/browser/components/browser-newtab.xpt
 @RESPATH@/browser/components/aboutNewTabService.js
 @RESPATH@/browser/components/NewTabComponents.manifest
 @RESPATH@/browser/components/EnterprisePolicies.js
 @RESPATH@/browser/components/EnterprisePoliciesContent.js
 @RESPATH@/browser/components/EnterprisePolicies.manifest
 @RESPATH@/components/Downloads.manifest
 @RESPATH@/components/DownloadLegacy.js
+@RESPATH@/components/thumbnails.xpt
 @RESPATH@/components/PageThumbsComponents.manifest
 @RESPATH@/components/crashmonitor.manifest
 @RESPATH@/components/nsCrashMonitor.js
 @RESPATH@/components/toolkitsearch.manifest
 @RESPATH@/components/nsSearchService.js
 @RESPATH@/components/nsSearchSuggestions.js
 @RESPATH@/components/nsSidebar.js
 #ifdef NIGHTLY_BUILD
@@ -216,16 +394,17 @@
 @RESPATH@/components/passwordmgr.manifest
 @RESPATH@/components/nsLoginInfo.js
 @RESPATH@/components/nsLoginManager.js
 @RESPATH@/components/nsLoginManagerPrompter.js
 @RESPATH@/components/storage-json.js
 @RESPATH@/components/crypto-SDR.js
 @RESPATH@/components/TooltipTextProvider.js
 @RESPATH@/components/TooltipTextProvider.manifest
+@RESPATH@/components/webvtt.xpt
 @RESPATH@/components/WebVTT.manifest
 @RESPATH@/components/WebVTTParserWrapper.js
 @RESPATH@/components/nsHelperAppDlg.manifest
 @RESPATH@/components/nsHelperAppDlg.js
 @RESPATH@/components/NetworkGeolocationProvider.manifest
 @RESPATH@/components/NetworkGeolocationProvider.js
 @RESPATH@/components/extensions.manifest
 @RESPATH@/components/EditorUtils.manifest
@@ -335,16 +514,20 @@
 @RESPATH@/components/PeerConnection.manifest
 #endif
 
 @RESPATH@/chrome/marionette@JAREXT@
 @RESPATH@/chrome/marionette.manifest
 @RESPATH@/components/marionette.manifest
 @RESPATH@/components/marionette.js
 
+#ifdef MOZ_WEBSPEECH
+@RESPATH@/components/dom_webspeechsynth.xpt
+#endif
+
 @RESPATH@/components/nsAsyncShutdown.manifest
 @RESPATH@/components/nsAsyncShutdown.js
 
 @RESPATH@/components/BuiltinProviders.manifest
 @RESPATH@/components/PresentationControlService.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.manifest
 
@@ -371,18 +554,20 @@
 @RESPATH@/browser/modules/*
 @RESPATH@/modules/*
 
 ; Safe Browsing
 @RESPATH@/components/nsURLClassifier.manifest
 @RESPATH@/components/nsUrlClassifierHashCompleter.js
 @RESPATH@/components/nsUrlClassifierListManager.js
 @RESPATH@/components/nsUrlClassifierLib.js
+@RESPATH@/components/url-classifier.xpt
 
 ; Private Browsing
+@RESPATH@/components/privatebrowsing.xpt
 @RESPATH@/components/PrivateBrowsing.manifest
 @RESPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js
 
 ; Security Reports
 @RESPATH@/components/SecurityReporter.manifest
 @RESPATH@/components/SecurityReporter.js
 
 ; ANGLE GLES-on-D3D rendering library
@@ -528,22 +713,25 @@
 @BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
 #endif
 @BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
 #endif
 @RESPATH@/chrome/pippki@JAREXT@
 @RESPATH@/chrome/pippki.manifest
+@RESPATH@/components/pipnss.xpt
+@RESPATH@/components/pippki.xpt
 
 ; For process sandboxing
 #if defined(MOZ_SANDBOX)
 #if defined(XP_LINUX)
 @BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
 #endif
+@RESPATH@/components/sandbox.xpt
 #endif
 
 ; for Solaris SPARC
 #ifdef SOLARIS
 bin/libfreebl_32fpu_3.so
 bin/libfreebl_32int_3.so
 bin/libfreebl_32int64_3.so
 #endif
@@ -565,16 +753,17 @@ bin/libfreebl_32int64_3.so
 @BINPATH@/maintenanceservice_installer.exe
 #endif
 
 ; [Crash Reporter]
 ;
 #ifdef MOZ_CRASHREPORTER
 @RESPATH@/components/CrashService.manifest
 @RESPATH@/components/CrashService.js
+@RESPATH@/components/toolkit_crashservice.xpt
 #ifdef XP_MACOSX
 @BINPATH@/crashreporter.app/
 #else
 @BINPATH@/crashreporter@BIN_SUFFIX@
 @RESPATH@/crashreporter.ini
 @BINPATH@/minidump-analyzer@BIN_SUFFIX@
 #ifdef XP_UNIX
 @RESPATH@/Throbber-small.gif
@@ -585,16 +774,18 @@ bin/libfreebl_32int64_3.so
 @BINPATH@/breakpadinjector.dll
 #endif
 #endif
 
 ; [ Ping Sender ]
 ;
 @BINPATH@/pingsender@BIN_SUFFIX@
 
+@RESPATH@/components/dom_audiochannel.xpt
+
 ; Shutdown Terminator
 @RESPATH@/components/nsTerminatorTelemetry.js
 @RESPATH@/components/terminator.manifest
 
 #ifdef LLVM_SYMBOLIZER
 @BINPATH@/@LLVM_SYMBOLIZER@
 #endif
 
@@ -620,16 +811,19 @@ bin/libfreebl_32int64_3.so
 #ifdef XP_MACOSX
 @RESPATH@/fix_macosx_stack.py
 #endif
 #ifdef XP_LINUX
 @RESPATH@/fix_linux_stack.py
 #endif
 #endif
 
+; Background Hang Monitor
+@RESPATH@/components/backgroundhangmonitor.xpt
+
 ; NOTE: This must match the config checks in
 ; /toolkit/components/backgroundhangmonitor/moz.build.
 #if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN)
 @RESPATH@/components/BHRTelemetryService.js
 @RESPATH@/components/BHRTelemetryService.manifest
 #endif
 
 #ifdef PKG_LOCALE_MANIFEST
--- a/browser/moz.build
+++ b/browser/moz.build
@@ -31,16 +31,24 @@ if CONFIG['MAKENSISU']:
 
 TEST_DIRS += [
     'tools/mozscreenshots',
 ]
 
 DIST_SUBDIR = 'browser'
 export('DIST_SUBDIR')
 
+if CONFIG['MOZ_ARTIFACT_BUILDS']:
+    # Ensure a pre-built interfaces.xpt installed to the objdir by the artifact
+    # code is included by the top-level chrome.manifest.
+    EXTRA_COMPONENTS += [
+        '../build/prebuilt-interfaces.manifest',
+    ]
+
+
 # These defines are read in firefox.js
 DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 
 for cdm in CONFIG['MOZ_EME_MODULES']:
     DEFINES['MOZ_%s_EME' % cdm.upper()] = True
 
 if CONFIG['MOZ_GPSD']:
     DEFINES['MOZ_GPSD'] = True
--- a/build/moz.build
+++ b/build/moz.build
@@ -112,8 +112,15 @@ OBJDIR_FILES += ['!/dist/bin/.lldbinit']
 OBJDIR_FILES += ['/.ycm_extra_conf.py']
 
 if CONFIG['MOZ_VALGRIND']:
     OBJDIR_FILES._valgrind += [
         'valgrind/cross-architecture.sup',
         'valgrind/i386-pc-linux-gnu.sup',
         'valgrind/x86_64-pc-linux-gnu.sup',
     ]
+
+if CONFIG['MOZ_ARTIFACT_BUILDS']:
+    # Ensure a pre-built interfaces.xpt installed to the objdir by the artifact
+    # code is included by the top-level chrome.manifest.
+    EXTRA_COMPONENTS += [
+        'prebuilt-interfaces.manifest',
+    ]
new file mode 100644
--- /dev/null
+++ b/build/prebuilt-interfaces.manifest
@@ -0,0 +1,1 @@
+interfaces interfaces.xpt
--- a/config/faster/rules.mk
+++ b/config/faster/rules.mk
@@ -99,16 +99,19 @@ ACDEFINES += -DBUILD_FASTER
 
 # The xpidl target in config/makefiles/xpidl requires the install manifest for
 # dist/idl to have been processed. When using the hybrid
 # FasterMake/RecursiveMake backend, this dependency is handled in the top-level
 # Makefile.
 ifndef FASTER_RECURSIVE_MAKE
 $(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
 endif
+# It also requires all the install manifests for dist/bin to have been processed
+# because it adds interfaces.manifest references with buildlist.py.
+$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(addprefix install-,$(filter dist/bin%,$(INSTALL_MANIFESTS)))
 
 $(TOPOBJDIR)/build/application.ini: $(TOPOBJDIR)/buildid.h $(TOPOBJDIR)/source-repo.h
 
 # The manifest of allowed system add-ons should be re-built when using
 # "build faster".
 ifeq ($(MOZ_BUILD_APP),browser/app)
 default: $(TOPOBJDIR)/browser/app/features
 endif
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -25,18 +25,16 @@ include $(topsrcdir)/config/rules.mk
 
 # For dependency files.
 idl_deps_dir := .deps
 
 dist_idl_dir := $(DIST)/idl
 dist_include_dir := $(DIST)/include
 dist_xpcrs_dir := $(DIST)/xpcrs
 process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
-generated_file := $(topobjdir)/xpcom/typelib/xpt/XPTInfo.cpp
-code_gen_py := $(topsrcdir)/xpcom/typelib/xpt/tools/xpt.py
 
 # TODO we should use py_action, but that would require extra directories to be
 # in the virtualenv.
 %.xpt:
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) $(PLY_INCLUDE) -I$(topsrcdir)/xpcom/idl-parser -I$(DEPTH)/xpcom/idl-parser/xpidl \
 		$(process_py) --cache-dir $(DEPTH)/xpcom/idl-parser/xpidl --depsdir $(idl_deps_dir) \
 		$(dist_idl_dir) $(dist_include_dir) $(dist_xpcrs_dir) $(@D) \
@@ -45,37 +43,47 @@ code_gen_py := $(topsrcdir)/xpcom/typeli
 # still is, in the tree, simple dependencies can't detect that the XPT needs
 # to be rebuilt.
 # Add the current value of $($(xpidl_module)_deps) in the depend file, such that
 # we can later check if the value has changed since last build, which will
 # indicate whether IDLs were added or removed.
 # Note that removing previously built files is not covered.
 	@echo $(basename $(notdir $@))_deps_built = $($(basename $(notdir $@))_deps) >> $(idl_deps_dir)/$(basename $(notdir $@)).pp
 
+# Chrome manifests may be written from several Makefiles at various times during
+# the build. The 'buildlist' action adds to the file if it already exists, but
+# if it does exist, make considers it to be up-to-date (as we have no inputs to
+# depend on). We use FORCE to ensure that we always add the interface manifest,
+# whether or not the chrome manifest already exists.
+%/chrome.manifest: FORCE
+	$(call py_action,buildlist,$@ 'manifest components/interfaces.manifest')
+
+chrome_manifests := @chrome_manifests@
+
+%/interfaces.manifest: Makefile
+	$(call py_action,buildlist,$@ $(foreach xpt,$(filter $*/%,$(registered_xpt_files)),'interfaces $(notdir $(xpt))'))
+
+interfaces_manifests := @interfaces_manifests@
+
 xpidl_modules := @xpidl_modules@
-xpt_files := $(addsuffix .xpt,$(xpidl_modules))
+registered_xpt_files := @registered_xpt_files@
+xpt_files := $(registered_xpt_files) @xpt_files@
 
 @xpidl_rules@
 
 depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
 
-GARBAGE += $(xpt_files) $(depends_files) $(generated_file)
+GARBAGE += $(xpt_files) $(depends_files)
 
 ifdef COMPILE_ENVIRONMENT
-xpidl:: $(generated_file)
+xpidl:: $(xpt_files) $(chrome_manifests) $(interfaces_manifests)
 endif
 
 $(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(dist_xpcrs_dir))
 
-$(generated_file): $(xpt_files) $(code_gen_py)
-	$(REPORT_BUILD)
-	$(PYTHON_PATH) $(PLY_INCLUDE) \
-		$(code_gen_py) linkgen \
-		$(generated_file) $(xpt_files)
-
 -include $(depends_files)
 
 define xpt_deps
 $(1): $(call mkdir_deps,$(dir $(1)))
 $(1): $(addsuffix .idl,$(addprefix $(dist_idl_dir)/,$($(basename $(notdir $(1)))_deps)))
 ifneq ($($(basename $(notdir $(1)))_deps),$($(basename $(notdir $(1)))_deps_built))
 $(1): FORCE
 endif
--- a/js/xpconnect/tests/idl/moz.build
+++ b/js/xpconnect/tests/idl/moz.build
@@ -9,8 +9,17 @@ XPIDL_SOURCES += [
     'xpctest_bug809674.idl',
     'xpctest_interfaces.idl',
     'xpctest_params.idl',
     'xpctest_returncode.idl',
     'xpctest_utils.idl',
 ]
 
 XPIDL_MODULE = 'xpctest'
+
+# XXX: This relies on xpctest.xpt being created in dist/bin/components/ during
+# the export tier AND TEST_HARNESS_FILES being processed after that.
+TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.native.components += [
+    '!/dist/bin/components/xpctest.xpt',
+]
+TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.js += [
+    '!/dist/bin/components/xpctest.xpt',
+]
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -84,17 +84,175 @@
 
 [browser]
 ; [Base Browser Files]
 @BINPATH@/application.ini
 @BINPATH@/platform.ini
 @BINPATH@/blocklist.xml
 
 ; [Components]
+#ifdef MOZ_ARTIFACT_BUILDS
+@BINPATH@/components/interfaces.xpt
+@BINPATH@/components/prebuilt-interfaces.manifest
+#endif
 @BINPATH@/components/components.manifest
+@BINPATH@/components/alerts.xpt
+#ifdef ACCESSIBILITY
+@BINPATH@/components/accessibility.xpt
+#endif
+@BINPATH@/components/appshell.xpt
+@BINPATH@/components/appstartup.xpt
+@BINPATH@/components/autocomplete.xpt
+@BINPATH@/components/autoconfig.xpt
+@BINPATH@/components/browser-element.xpt
+@BINPATH@/components/caps.xpt
+@BINPATH@/components/chrome.xpt
+@BINPATH@/components/commandhandler.xpt
+@BINPATH@/components/commandlines.xpt
+@BINPATH@/components/composer.xpt
+@BINPATH@/components/content_events.xpt
+@BINPATH@/components/content_geckomediaplugins.xpt
+@BINPATH@/components/content_html.xpt
+@BINPATH@/components/content_webrtc.xpt
+@BINPATH@/components/content_xslt.xpt
+@BINPATH@/components/directory.xpt
+@BINPATH@/components/docshell.xpt
+@BINPATH@/components/dom.xpt
+@BINPATH@/components/dom_base.xpt
+@BINPATH@/components/dom_bindings.xpt
+#ifdef MOZ_DEBUG
+@BINPATH@/components/dom_bindings_test.xpt
+#endif
+@BINPATH@/components/dom_core.xpt
+@BINPATH@/components/dom_events.xpt
+@BINPATH@/components/dom_file.xpt
+@BINPATH@/components/dom_geolocation.xpt
+@BINPATH@/components/dom_media.xpt
+@BINPATH@/components/dom_network.xpt
+@BINPATH@/components/dom_notification.xpt
+@BINPATH@/components/dom_html.xpt
+@BINPATH@/components/dom_offline.xpt
+@BINPATH@/components/dom_payments.xpt
+@BINPATH@/components/dom_power.xpt
+#ifdef MOZ_ANDROID_GCM
+@BINPATH@/components/dom_push.xpt
+#endif
+@BINPATH@/components/dom_quota.xpt
+@BINPATH@/components/dom_range.xpt
+@BINPATH@/components/dom_security.xpt
+@BINPATH@/components/dom_sidebar.xpt
+@BINPATH@/components/dom_storage.xpt
+@BINPATH@/components/dom_system.xpt
+#ifdef MOZ_WEBSPEECH
+@BINPATH@/components/dom_webspeechrecognition.xpt
+#endif
+@BINPATH@/components/dom_workers.xpt
+@BINPATH@/components/dom_xhr.xpt
+@BINPATH@/components/dom_xul.xpt
+@BINPATH@/components/dom_presentation.xpt
+@BINPATH@/components/downloads.xpt
+@BINPATH@/components/editor.xpt
+@BINPATH@/components/extensions.xpt
+@BINPATH@/components/exthandler.xpt
+@BINPATH@/components/fastfind.xpt
+@BINPATH@/components/feeds.xpt
+@BINPATH@/components/gfx.xpt
+@BINPATH@/components/html5.xpt
+@BINPATH@/components/htmlparser.xpt
+@BINPATH@/components/imglib2.xpt
+@BINPATH@/components/inspector.xpt
+@BINPATH@/components/intl.xpt
+@BINPATH@/components/jar.xpt
+@BINPATH@/components/jsdebugger.xpt
+@BINPATH@/components/jsinspector.xpt
+@BINPATH@/components/layout_base.xpt
+#ifdef NS_PRINTING
+@BINPATH@/components/layout_printing.xpt
+#endif
+@BINPATH@/components/layout_xul_tree.xpt
+@BINPATH@/components/layout_xul.xpt
+@BINPATH@/components/locale.xpt
+@BINPATH@/components/mimetype.xpt
+@BINPATH@/components/mozfind.xpt
+@BINPATH@/components/mozintl.xpt
+@BINPATH@/components/necko_about.xpt
+@BINPATH@/components/necko_cache.xpt
+@BINPATH@/components/necko_cache2.xpt
+@BINPATH@/components/necko_cookie.xpt
+@BINPATH@/components/necko_dns.xpt
+@BINPATH@/components/necko_file.xpt
+@BINPATH@/components/necko_ftp.xpt
+@BINPATH@/components/necko_http.xpt
+@BINPATH@/components/necko_mdns.xpt
+@BINPATH@/components/necko_res.xpt
+@BINPATH@/components/necko_socket.xpt
+@BINPATH@/components/necko_strconv.xpt
+@BINPATH@/components/necko_viewsource.xpt
+@BINPATH@/components/necko_websocket.xpt
+#ifdef NECKO_WIFI
+@BINPATH@/components/necko_wifi.xpt
+#endif
+@BINPATH@/components/necko_wyciwyg.xpt
+@BINPATH@/components/necko.xpt
+@BINPATH@/components/loginmgr.xpt
+@BINPATH@/components/parentalcontrols.xpt
+#ifdef MOZ_WEBRTC
+@BINPATH@/components/peerconnection.xpt
+#endif
+@BINPATH@/components/plugin.xpt
+@BINPATH@/components/pref.xpt
+@BINPATH@/components/prefetch.xpt
+#ifdef MOZ_GECKO_PROFILER
+@BINPATH@/components/profiler.xpt
+#endif
+@BINPATH@/components/rdf.xpt
+@BINPATH@/components/reputationservice.xpt
+@BINPATH@/components/satchel.xpt
+@BINPATH@/components/saxparser.xpt
+@BINPATH@/components/services-crypto-component.xpt
+@BINPATH@/components/captivedetect.xpt
+@BINPATH@/components/shistory.xpt
+@BINPATH@/components/spellchecker.xpt
+@BINPATH@/components/storage.xpt
+@BINPATH@/components/telemetry.xpt
+@BINPATH@/components/toolkit_asyncshutdown.xpt
+@BINPATH@/components/toolkit_filewatcher.xpt
+@BINPATH@/components/toolkit_finalizationwitness.xpt
+@BINPATH@/components/toolkit_osfile.xpt
+@BINPATH@/components/toolkit_securityreporter.xpt
+@BINPATH@/components/toolkit_perfmonitoring.xpt
+@BINPATH@/components/toolkit_xulstore.xpt
+@BINPATH@/components/toolkitprofile.xpt
+#ifdef MOZ_ENABLE_XREMOTE
+@BINPATH@/components/toolkitremote.xpt
+#endif
+@BINPATH@/components/txtsvc.xpt
+@BINPATH@/components/txmgr.xpt
+@BINPATH@/components/uconv.xpt
+@BINPATH@/components/update.xpt
+@BINPATH@/components/uriloader.xpt
+@BINPATH@/components/urlformatter.xpt
+@BINPATH@/components/webBrowser_core.xpt
+@BINPATH@/components/webbrowserpersist.xpt
+@BINPATH@/components/webextensions.xpt
+@BINPATH@/components/widget.xpt
+@BINPATH@/components/widget_android.xpt
+@BINPATH@/components/windowcreator.xpt
+@BINPATH@/components/windowwatcher.xpt
+@BINPATH@/components/xpcom_base.xpt
+@BINPATH@/components/xpcom_system.xpt
+@BINPATH@/components/xpcom_components.xpt
+@BINPATH@/components/xpcom_ds.xpt
+@BINPATH@/components/xpcom_io.xpt
+@BINPATH@/components/xpcom_threads.xpt
+@BINPATH@/components/xpcom_xpti.xpt
+@BINPATH@/components/xpconnect.xpt
+@BINPATH@/components/xulapp.xpt
+@BINPATH@/components/xul.xpt
+@BINPATH@/components/zipwriter.xpt
 
 ; JavaScript components
 @BINPATH@/components/ConsoleAPI.manifest
 @BINPATH@/components/ConsoleAPIStorage.js
 @BINPATH@/components/NotificationStorage.js
 @BINPATH@/components/NotificationStorage.manifest
 #ifdef MOZ_ANDROID_GCM
 @BINPATH@/components/Push.js
@@ -141,16 +299,17 @@
 @BINPATH@/components/amContentHandler.js
 @BINPATH@/components/amWebAPI.js
 @BINPATH@/components/amInstallTrigger.js
 #ifndef RELEASE_OR_BETA
 @BINPATH@/components/TabSource.js
 #endif
 #endif
 
+@BINPATH@/components/webvtt.xpt
 @BINPATH@/components/WebVTT.manifest
 @BINPATH@/components/WebVTTParserWrapper.js
 
 #ifndef MOZ_GECKOVIEW_JAR
 #ifdef MOZ_UPDATER
 @BINPATH@/components/nsUpdateService.manifest
 @BINPATH@/components/nsUpdateService.js
 @BINPATH@/components/nsUpdateServiceStub.js
@@ -202,16 +361,20 @@
 #ifdef MOZ_WEBRTC
 @BINPATH@/components/PeerConnection.js
 @BINPATH@/components/PeerConnection.manifest
 #endif
 
 @BINPATH@/components/CaptivePortalDetectComponents.manifest
 @BINPATH@/components/captivedetect.js
 
+#ifdef MOZ_WEBSPEECH
+@BINPATH@/components/dom_webspeechsynth.xpt
+#endif
+
 #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
 @BINPATH@/components/TestInterfaceJS.js
 @BINPATH@/components/TestInterfaceJS.manifest
 @BINPATH@/components/TestInterfaceJSMaplike.js
 #endif
 
 @BINPATH@/components/nsAsyncShutdown.manifest
 @BINPATH@/components/nsAsyncShutdown.js
@@ -236,18 +399,20 @@
 ; Modules
 @BINPATH@/modules/*
 
 ; Safe Browsing
 @BINPATH@/components/nsURLClassifier.manifest
 @BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
 @BINPATH@/components/nsUrlClassifierLib.js
+@BINPATH@/components/url-classifier.xpt
 
 ; Private Browsing
+@BINPATH@/components/privatebrowsing.xpt
 @BINPATH@/components/PrivateBrowsing.manifest
 @BINPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js
 
 ; Security Reports
 @BINPATH@/components/SecurityReporter.manifest
 @BINPATH@/components/SecurityReporter.js
 
 ; [Browser Chrome Files]
@@ -312,29 +477,35 @@
 #endif
 
 ; Content-accessible resources.
 @BINPATH@/contentaccessible/*
 
 ; svg
 @BINPATH@/res/svg.css
 
+; [Personal Security Manager]
+;
+@BINPATH@/components/pipnss.xpt
+
 ; For process sandboxing
 #if defined(MOZ_SANDBOX)
 @BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@
 #endif
 
 ; [Crash Reporter]
 ; CrashService is not used on Android but the ini files are required for L10N
 ; strings, see bug 1191351.
 #ifdef MOZ_CRASHREPORTER
 @BINPATH@/crashreporter.ini
 @BINPATH@/crashreporter-override.ini
 #endif
 
+@BINPATH@/components/dom_audiochannel.xpt
+
 @BINPATH@/components/RemoteWebNavigation.js
 @BINPATH@/components/remotebrowserutils.manifest
 
 [mobile]
 @BINPATH@/chrome/geckoview@JAREXT@
 @BINPATH@/chrome/geckoview.manifest
 
 #ifdef MOZ_GECKOVIEW_JAR
@@ -355,16 +526,17 @@
 @BINPATH@/components/ContentPermissionPrompt.js
 @BINPATH@/components/ImageBlockingPolicy.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/FilePicker.js
 @BINPATH@/components/FxAccountsPush.js
 @BINPATH@/components/HelperAppDialog.js
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
+@BINPATH@/components/MobileComponents.xpt
 @BINPATH@/components/NSSDialogService.js
 @BINPATH@/components/PersistentNotificationHandler.js
 @BINPATH@/components/PresentationDevicePrompt.js
 @BINPATH@/components/PresentationRequestUIGlue.js
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/Snippets.js
 @BINPATH@/components/XPIDialogService.js
@@ -376,14 +548,17 @@
 @BINPATH@/components/marionette.manifest
 @BINPATH@/components/marionette.js
 #endif
 
 #ifdef PKG_LOCALE_MANIFEST
 #include @PKG_LOCALE_MANIFEST@
 #endif
 
+; Background Hang Monitor
+@BINPATH@/components/backgroundhangmonitor.xpt
+
 ; NOTE: This must match the config checks in
 ; /toolkit/components/backgroundhangmonitor/moz.build.
 #if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN)
 @BINPATH@/components/BHRTelemetryService.js
 @BINPATH@/components/BHRTelemetryService.manifest
 #endif
--- a/netwerk/test/httpserver/moz.build
+++ b/netwerk/test/httpserver/moz.build
@@ -5,16 +5,19 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIHttpServer.idl',
 ]
 
 XPIDL_MODULE = 'test_necko'
 
+# Don't add our test-only .xpt files to the normal manifests
+XPIDL_NO_MANIFEST = True
+
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 EXTRA_COMPONENTS += [
     'httpd.js',
     'httpd.manifest',
 ]
 
 TESTING_JS_MODULES += [
--- a/python/mozbuild/mozbuild/artifacts.py
+++ b/python/mozbuild/mozbuild/artifacts.py
@@ -240,16 +240,17 @@ class ArtifactJob(object):
 class AndroidArtifactJob(ArtifactJob):
 
     product = 'mobile'
 
     package_artifact_patterns = {
         'application.ini',
         'platform.ini',
         '**/*.so',
+        '**/interfaces.xpt',
     }
 
     def process_package_artifact(self, filename, processed_filename):
         # Extract all .so files into the root, which will get copied into dist/bin.
         with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer:
             for p, f in UnpackFinder(JarFinder(filename, JarReader(filename))):
                 if not any(mozpath.match(p, pat) for pat in self.package_artifact_patterns):
                     continue
@@ -277,16 +278,17 @@ class LinuxArtifactJob(ArtifactJob):
         'firefox/firefox',
         'firefox/firefox-bin',
         'firefox/minidump-analyzer',
         'firefox/pingsender',
         'firefox/platform.ini',
         'firefox/plugin-container',
         'firefox/updater',
         'firefox/**/*.so',
+        'firefox/**/interfaces.xpt',
     }
 
     def process_package_artifact(self, filename, processed_filename):
         added_entry = False
 
         with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer:
             with tarfile.open(filename) as reader:
                 for p, f in UnpackFinder(TarFinder(filename, reader)):
@@ -375,16 +377,17 @@ class MacArtifactJob(ArtifactJob):
                 ]),
                 ('Contents/Resources', [
                     'browser/components/libbrowsercomps.dylib',
                     'dependentlibs.list',
                     # 'firefox',
                     'gmp-clearkey/0.1/libclearkey.dylib',
                     # 'gmp-fake/1.0/libfake.dylib',
                     # 'gmp-fakeopenh264/1.0/libfakeopenh264.dylib',
+                    '**/interfaces.xpt',
                 ]),
             ]
 
             with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer:
                 root, paths = paths_no_keep_path
                 finder = UnpackFinder(mozpath.join(source, root))
                 for path in paths:
                     for p, f in finder.find(path):
@@ -417,16 +420,17 @@ class MacArtifactJob(ArtifactJob):
 
 class WinArtifactJob(ArtifactJob):
     package_artifact_patterns = {
         'firefox/dependentlibs.list',
         'firefox/platform.ini',
         'firefox/application.ini',
         'firefox/**/*.dll',
         'firefox/*.exe',
+        'firefox/**/interfaces.xpt',
         'firefox/*.tlb',
     }
 
     product = 'firefox'
 
     # These are a subset of TEST_HARNESS_BINS in testing/mochitest/Makefile.in.
     test_artifact_patterns = {
         ('bin/BadCertServer.exe', ('bin', 'bin')),
--- a/python/mozbuild/mozbuild/backend/common.py
+++ b/python/mozbuild/mozbuild/backend/common.py
@@ -53,40 +53,50 @@ class XPIDLManager(object):
     """Helps manage XPCOM IDLs in the context of the build system."""
     def __init__(self, config):
         self.config = config
         self.topsrcdir = config.topsrcdir
         self.topobjdir = config.topobjdir
 
         self.idls = {}
         self.modules = {}
+        self.interface_manifests = {}
+        self.chrome_manifests = set()
 
     def register_idl(self, idl, allow_existing=False):
         """Registers an IDL file with this instance.
 
         The IDL file will be built, installed, etc.
         """
         basename = mozpath.basename(idl.source_path)
         root = mozpath.splitext(basename)[0]
         xpt = '%s.xpt' % idl.module
+        manifest = mozpath.join(idl.install_target, 'components', 'interfaces.manifest')
+        chrome_manifest = mozpath.join(idl.install_target, 'chrome.manifest')
 
         entry = {
             'source': idl.source_path,
             'module': idl.module,
             'basename': basename,
             'root': root,
+            'manifest': manifest,
         }
 
         if not allow_existing and entry['basename'] in self.idls:
             raise Exception('IDL already registered: %s' % entry['basename'])
 
         self.idls[entry['basename']] = entry
         t = self.modules.setdefault(entry['module'], (idl.install_target, set()))
         t[1].add(entry['root'])
 
+        if idl.add_to_manifest:
+            self.interface_manifests.setdefault(manifest, set()).add(xpt)
+            self.chrome_manifests.add(chrome_manifest)
+
+
 class BinariesCollection(object):
     """Tracks state of binaries produced by the build."""
 
     def __init__(self):
         self.shared_libraries = []
         self.programs = []
 
 class CommonBackend(BuildBackend):
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1058,16 +1058,18 @@ class RecursiveMakeBackend(CommonBackend
                 % idl['root'])
 
         for module in manager.modules:
             build_files.add_optional_exists(mozpath.join('.deps',
                 '%s.pp' % module))
 
         modules = manager.modules
         xpt_modules = sorted(modules.keys())
+        xpt_files = set()
+        registered_xpt_files = set()
 
         mk = Makefile()
 
         for module in xpt_modules:
             install_target, sources = modules[module]
             deps = sorted(sources)
 
             # It may seem strange to have the .idl files listed as
@@ -1075,39 +1077,67 @@ class RecursiveMakeBackend(CommonBackend
             # It is necessary to list them here to handle the case where a
             # new .idl is added to an xpt. If we add a new .idl and nothing
             # else has changed, the new .idl won't be referenced anywhere
             # except in the command invocation. Therefore, the .xpt won't
             # be rebuilt because the dependencies say it is up to date. By
             # listing the .idls here, we ensure the make file has a
             # reference to the new .idl. Since the new .idl presumably has
             # an mtime newer than the .xpt, it will trigger xpt generation.
+            xpt_path = '$(DEPTH)/%s/components/%s.xpt' % (install_target, module)
+            xpt_files.add(xpt_path)
             mk.add_statement('%s_deps = %s' % (module, ' '.join(deps)))
 
-            build_files.add_optional_exists('%s.xpt' % module)
+            if install_target.startswith('dist/'):
+                path = mozpath.relpath(xpt_path, '$(DEPTH)/dist')
+                prefix, subpath = path.split('/', 1)
+                key = 'dist_%s' % prefix
+
+                self._install_manifests[key].add_optional_exists(subpath)
 
         rules = StringIO()
         mk.dump(rules, removal_guard=False)
 
+        interfaces_manifests = []
+        dist_dir = mozpath.join(self.environment.topobjdir, 'dist')
+        for manifest, entries in manager.interface_manifests.items():
+            interfaces_manifests.append(mozpath.join('$(DEPTH)', manifest))
+            for xpt in sorted(entries):
+                registered_xpt_files.add(mozpath.join(
+                    '$(DEPTH)', mozpath.dirname(manifest), xpt))
+
+            if install_target.startswith('dist/'):
+                path = mozpath.join(self.environment.topobjdir, manifest)
+                path = mozpath.relpath(path, dist_dir)
+                prefix, subpath = path.split('/', 1)
+                key = 'dist_%s' % prefix
+                self._install_manifests[key].add_optional_exists(subpath)
+
+        chrome_manifests = [mozpath.join('$(DEPTH)', m) for m in sorted(manager.chrome_manifests)]
+
         # Create dependency for output header so we force regeneration if the
         # header was deleted. This ideally should not be necessary. However,
         # some processes (such as PGO at the time this was implemented) wipe
         # out dist/include without regard to our install manifests.
 
         obj = self.Substitution()
         obj.output_path = mozpath.join(self.environment.topobjdir, 'config',
             'makefiles', 'xpidl', 'Makefile')
         obj.input_path = mozpath.join(self.environment.topsrcdir, 'config',
             'makefiles', 'xpidl', 'Makefile.in')
         obj.topsrcdir = self.environment.topsrcdir
         obj.topobjdir = self.environment.topobjdir
         obj.config = self.environment
         self._create_makefile(obj, extra=dict(
+            chrome_manifests = ' '.join(chrome_manifests),
+            interfaces_manifests = ' '.join(interfaces_manifests),
             xpidl_rules=rules.getvalue(),
             xpidl_modules=' '.join(xpt_modules),
+            xpt_files=' '.join(sorted(xpt_files - registered_xpt_files)),
+            registered_xpt_files=' '.join(sorted(registered_xpt_files)),
         ))
 
     def _process_program(self, obj, backend_file):
         backend_file.write('PROGRAM = %s\n' % self._pretty_path(obj.output_path, backend_file))
         if not obj.cxx_link and not self.environment.bin_suffix:
             backend_file.write('PROG_IS_C_ONLY_%s := 1\n' % obj.program)
 
     def _process_host_program(self, program, backend_file):
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1774,16 +1774,24 @@ VARIABLES = {
     'XPIDL_MODULE': (unicode, unicode,
         """XPCOM Interface Definition Module Name.
 
         This is the name of the ``.xpt`` file that is created by linking
         ``XPIDL_SOURCES`` together. If unspecified, it defaults to be the same
         as ``MODULE``.
         """),
 
+    'XPIDL_NO_MANIFEST': (bool, bool,
+        """Indicate that the XPIDL module should not be added to a manifest.
+
+        This flag exists primarily to prevent test-only XPIDL modules from being
+        added to the application's chrome manifest. Most XPIDL modules should
+        not use this flag.
+        """),
+
     'PREPROCESSED_IPDL_SOURCES': (StrictOrderingOnAppendList, list,
         """Preprocessed IPDL source files.
 
         These files will be preprocessed, then parsed and converted to
         ``.cpp`` files.
         """),
 
     'IPDL_SOURCES': (StrictOrderingOnAppendList, list,
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -191,24 +191,26 @@ class ComputedFlags(ContextDerived):
 
 class XPIDLFile(ContextDerived):
     """Describes an XPIDL file to be compiled."""
 
     __slots__ = (
         'source_path',
         'basename',
         'module',
+        'add_to_manifest',
     )
 
-    def __init__(self, context, source, module):
+    def __init__(self, context, source, module, add_to_manifest):
         ContextDerived.__init__(self, context)
 
         self.source_path = source
         self.basename = mozpath.basename(source)
         self.module = module
+        self.add_to_manifest = add_to_manifest
 
 class BaseDefines(ContextDerived):
     """Context derived container object for DEFINES/HOST_DEFINES,
     which are OrderedDicts.
     """
     __slots__ = ('defines')
 
     def __init__(self, context, defines):
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -1339,17 +1339,17 @@ class TreeMetadataEmitter(LoggingMixin):
 
         if context['XPIDL_SOURCES'] and context['DIST_INSTALL'] is False:
             self.log(logging.WARN, 'mozbuild_warning', dict(
                 path=context.main_path),
                 '{path}: DIST_INSTALL = False has no effect on XPIDL_SOURCES.')
 
         for idl in context['XPIDL_SOURCES']:
             yield XPIDLFile(context, mozpath.join(context.srcdir, idl),
-                xpidl_module)
+                xpidl_module, add_to_manifest=not context['XPIDL_NO_MANIFEST'])
 
     def _process_generated_files(self, context):
         for path in context['CONFIGURE_DEFINE_FILES']:
             script = mozpath.join(mozpath.dirname(mozpath.dirname(__file__)),
                                   'action', 'process_define_files.py')
             yield GeneratedFile(context, script, 'process_define_file',
                                 unicode(path),
                                 [Path(context, path + '.in')])
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -682,18 +682,19 @@ class TestRecursiveMakeBackend(BackendTe
         m = InstallManifest(path=mozpath.join(install_dir, 'dist_idl'))
         self.assertEqual(len(m), 2)
         self.assertIn('bar.idl', m)
         self.assertIn('foo.idl', m)
 
         m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
         self.assertIn('.deps/my_module.pp', m)
 
-        m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
-        self.assertIn('my_module.xpt', m)
+        m = InstallManifest(path=os.path.join(install_dir, 'dist_bin'))
+        self.assertIn('components/my_module.xpt', m)
+        self.assertIn('components/interfaces.manifest', m)
 
         m = InstallManifest(path=mozpath.join(install_dir, 'dist_include'))
         self.assertIn('foo.h', m)
 
         p = mozpath.join(env.topobjdir, 'config/makefiles/xpidl')
         self.assertTrue(os.path.isdir(p))
 
         self.assertTrue(os.path.isfile(mozpath.join(p, 'Makefile')))
--- a/toolkit/mozapps/installer/packager.py
+++ b/toolkit/mozapps/installer/packager.py
@@ -180,16 +180,19 @@ class NoPkgFilesRemover(object):
         if not any(mozpath.match(path, spec) for spec in self._files):
             self._formatter.add(path, content)
         else:
             self._error(self._msg % path)
 
     def add_manifest(self, entry):
         self._formatter.add_manifest(entry)
 
+    def add_interfaces(self, path, content):
+        self._formatter.add_interfaces(path, content)
+
     def contains(self, path):
         return self._formatter.contains(path)
 
 
 def main():
     parser = ArgumentParser()
     parser.add_argument('-D', dest='defines', action='append',
                         metavar="VAR[=VAL]", help='Define a variable')
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -75,16 +75,20 @@ static const ManifestDirective kParsingT
     "manifest",         1, false, false, true, true, false,
     &nsComponentManagerImpl::ManifestManifest, nullptr,
   },
   {
     "binary-component", 1, true, true, false, false, false,
     &nsComponentManagerImpl::ManifestBinaryComponent, nullptr,
   },
   {
+    "interfaces",       1, false, true, false, false, false,
+    &nsComponentManagerImpl::ManifestXPT, nullptr,
+  },
+  {
     "component",        2, false, true, false, false, false,
     &nsComponentManagerImpl::ManifestComponent, nullptr,
   },
   {
     "contract",         2, false, true, false, false, false,
     &nsComponentManagerImpl::ManifestContract, nullptr,
   },
   {
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -12,29 +12,32 @@
 
 #include "nsCategoryManager.h"
 #include "nsCOMPtr.h"
 #include "nsComponentManager.h"
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsCategoryManager.h"
 #include "nsCategoryManagerUtils.h"
+#include "xptiprivate.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/XPTInterfaceInfoManager.h"
 #include "nsIConsoleService.h"
 #include "nsIObserverService.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIStringEnumerator.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMPrivate.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIClassInfo.h"
 #include "nsLocalFile.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "prcmon.h"
+#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
 #include "nsThreadUtils.h"
 #include "prthread.h"
 #include "private/pprthred.h"
 #include "nsTArray.h"
 #include "prio.h"
 #include "ManifestParser.h"
 #include "nsNetUtil.h"
 #include "mozilla/Services.h"
@@ -567,16 +570,47 @@ void
 nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& aCx,
                                                 int aLineNo,
                                                 char* const* aArgv)
 {
   LogMessageWithContext(aCx.mFile, aLineNo,
                         "Binary XPCOM components are no longer supported.");
 }
 
+static void
+DoRegisterXPT(FileLocation& aFile)
+{
+  uint32_t len;
+  FileLocation::Data data;
+  UniquePtr<char[]> buf;
+  nsresult rv = aFile.GetData(data);
+  if (NS_SUCCEEDED(rv)) {
+    rv = data.GetSize(&len);
+  }
+  if (NS_SUCCEEDED(rv)) {
+    buf = MakeUnique<char[]>(len);
+    rv = data.Copy(buf.get(), len);
+  }
+  if (NS_SUCCEEDED(rv)) {
+    XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf.get(), len);
+  } else {
+    nsCString uri;
+    aFile.GetURIString(uri);
+    LogMessage("Could not read '%s'.", uri.get());
+  }
+}
+
+void
+nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& aCx,
+                                    int aLineNo, char* const* aArgv)
+{
+  FileLocation f(aCx.mFile, aArgv[0]);
+  DoRegisterXPT(f);
+}
+
 void
 nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& aCx,
                                           int aLineNo, char* const* aArgv)
 {
   mLock.AssertNotCurrentThreadOwns();
 
   char* id = aArgv[0];
   char* file = aArgv[1];
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -285,16 +285,18 @@ public:
     mozilla::FileLocation mFile;
     bool mChromeOnly;
   };
 
   void ManifestManifest(ManifestProcessingContext& aCx, int aLineNo,
                         char* const* aArgv);
   void ManifestBinaryComponent(ManifestProcessingContext& aCx, int aLineNo,
                                char* const* aArgv);
+  void ManifestXPT(ManifestProcessingContext& aCx, int aLineNo,
+                   char* const* aArgv);
   void ManifestComponent(ManifestProcessingContext& aCx, int aLineNo,
                          char* const* aArgv);
   void ManifestContract(ManifestProcessingContext& aCx, int aLineNo,
                         char* const* aArgv);
   void ManifestCategory(ManifestProcessingContext& aCx, int aLineNo,
                         char* const* aArgv);
 
   void RereadChromeManifests(bool aChromeOnly = true);
--- a/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
+++ b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
@@ -12,17 +12,18 @@
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsDataHashtable.h"
 
 template<typename T> class nsCOMArray;
 class nsIMemoryReporter;
-struct XPTInterfaceDescriptor;
+struct XPTHeader;
+struct XPTInterfaceDirectoryEntry;
 class xptiInterfaceEntry;
 class xptiInterfaceInfo;
 class xptiTypelibGuts;
 
 namespace mozilla {
 
 class XPTInterfaceInfoManager final
     : public nsIInterfaceInfoManager
@@ -34,33 +35,37 @@ class XPTInterfaceInfoManager final
 
 public:
     // GetSingleton() is infallible
     static XPTInterfaceInfoManager* GetSingleton();
     static void FreeInterfaceInfoManager();
 
     void GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces);
 
+    void RegisterBuffer(char *buf, uint32_t length);
+
     static Mutex& GetResolveLock()
     {
         return GetSingleton()->mResolveLock;
     }
 
     xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 private:
     XPTInterfaceInfoManager();
     ~XPTInterfaceInfoManager();
 
     void InitMemoryReporter();
 
+    void RegisterXPTHeader(const XPTHeader* aHeader);
+
     // idx is the index of this interface in the XPTHeader
-    void VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
+    void VerifyAndAddEntryIfNew(const XPTInterfaceDirectoryEntry* iface,
                                 uint16_t idx,
                                 xptiTypelibGuts* typelib);
 
 private:
 
     class xptiWorkingSet
     {
     public:
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
@@ -11,42 +11,42 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "mozilla/PodOperations.h"
 #include "jsapi.h"
 
 using namespace mozilla;
 
 /* static */ xptiInterfaceEntry*
-xptiInterfaceEntry::Create(const XPTInterfaceDescriptor* aIface,
+xptiInterfaceEntry::Create(const XPTInterfaceDirectoryEntry* aEntry,
                            xptiTypelibGuts* aTypelib)
 {
     void* place = XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry));
     if (!place) {
         return nullptr;
     }
-    return new (place) xptiInterfaceEntry(aIface, aTypelib);
+    return new (place) xptiInterfaceEntry(aEntry, aTypelib);
 }
 
-xptiInterfaceEntry::xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
+xptiInterfaceEntry::xptiInterfaceEntry(const XPTInterfaceDirectoryEntry* aEntry,
                                        xptiTypelibGuts* aTypelib)
-    : mIID(aIface->mIID)
-    , mDescriptor(aIface)
+    : mIID(aEntry->mIID)
+    , mDescriptor(aEntry->mInterfaceDescriptor)
     , mTypelib(aTypelib)
     , mParent(nullptr)
     , mInfo(nullptr)
     , mMethodBaseIndex(0)
     , mConstantBaseIndex(0)
     , mFlags(0)
-    , mName(aIface->Name())
+    , mName(aEntry->mName)
 {
     SetResolvedState(PARTIALLY_RESOLVED);
-    SetScriptableFlag(aIface->IsScriptable());
-    SetBuiltinClassFlag(aIface->IsBuiltinClass());
-    SetMainProcessScriptableOnlyFlag(aIface->IsMainProcessScriptableOnly());
+    SetScriptableFlag(mDescriptor->IsScriptable());
+    SetBuiltinClassFlag(mDescriptor->IsBuiltinClass());
+    SetMainProcessScriptableOnlyFlag(mDescriptor->IsMainProcessScriptableOnly());
 }
 
 bool
 xptiInterfaceEntry::Resolve()
 {
     MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock());
     return ResolveLocked();
 }
@@ -80,17 +80,17 @@ xptiInterfaceEntry::ResolveLocked()
         }
 
         mParent = parent;
         if (parent->GetHasNotXPCOMFlag()) {
             SetHasNotXPCOMFlag();
         } else {
             for (uint16_t idx = 0; idx < mDescriptor->mNumMethods; ++idx) {
                 const nsXPTMethodInfo* method = static_cast<const nsXPTMethodInfo*>(
-                    &mDescriptor->Method(idx));
+                    mDescriptor->mMethodDescriptors + idx);
                 if (method->IsNotXPCOM()) {
                     SetHasNotXPCOMFlag();
                     break;
                 }
             }
         }
 
 
@@ -184,32 +184,32 @@ xptiInterfaceEntry::GetMethodInfo(uint16
     {
         NS_ERROR("bad param");
         *info = nullptr;
         return NS_ERROR_INVALID_ARG;
     }
 
     // else...
     *info = static_cast<const nsXPTMethodInfo*>
-        (&mDescriptor->Method(index - mMethodBaseIndex));
+        (&mDescriptor->mMethodDescriptors[index - mMethodBaseIndex]);
     return NS_OK;
 }
 
 nsresult
 xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index,
                                          const nsXPTMethodInfo** result)
 {
     if(!EnsureResolved())
         return NS_ERROR_UNEXPECTED;
 
     // This is a slow algorithm, but this is not expected to be called much.
     for(uint16_t i = 0; i < mDescriptor->mNumMethods; ++i)
     {
         const nsXPTMethodInfo* info;
-        info = static_cast<const nsXPTMethodInfo*>(&mDescriptor->Method(i));
+        info = static_cast<const nsXPTMethodInfo*>(&mDescriptor->mMethodDescriptors[i]);
         if (PL_strcmp(methodName, info->GetName()) == 0) {
             *index = i + mMethodBaseIndex;
             *result = info;
             return NS_OK;
         }
     }
 
     if(mParent)
@@ -234,17 +234,17 @@ xptiInterfaceEntry::GetConstant(uint16_t
 
     if(index >= mConstantBaseIndex +
                 mDescriptor->mNumConstants)
     {
         NS_PRECONDITION(0, "bad param");
         return NS_ERROR_INVALID_ARG;
     }
 
-    const auto& c = mDescriptor->Const(index - mConstantBaseIndex);
+    const auto& c = mDescriptor->mConstDescriptors[index - mConstantBaseIndex];
     AutoJSContext cx;
     JS::Rooted<JS::Value> v(cx);
     v.setUndefined();
 
     switch (c.mType.mPrefix.mFlags) {
       case nsXPTType::T_I16:
       {
         v.setInt32(c.mValue.i16);
@@ -267,17 +267,17 @@ xptiInterfaceEntry::GetConstant(uint16_t
       }
       default:
       {
         MOZ_ASSERT(false, "Invalid constant type found in interface");
       }
     }
 
     constant.set(v);
-    *name = ToNewCString(nsDependentCString(c.Name()));
+    *name = ToNewCString(nsDependentCString(c.mName));
 
     return NS_OK;
 }
 
 // this is a private helper
 
 nsresult
 xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex,
@@ -296,17 +296,17 @@ xptiInterfaceEntry::GetInterfaceIndexFor
     {
         NS_ERROR("bad param");
         return NS_ERROR_INVALID_ARG;
     }
 
     const XPTTypeDescriptor *td = &param->mType;
 
     while (td->Tag() == TD_ARRAY) {
-        td = td->ArrayElementType();
+        td = td->ArrayElementType(mDescriptor);
     }
 
     if (td->Tag() != TD_INTERFACE_TYPE) {
         NS_ERROR("not an interface");
         return NS_ERROR_INVALID_ARG;
     }
     *interfaceIndex = td->InterfaceIndex();
     return NS_OK;
@@ -436,17 +436,17 @@ xptiInterfaceEntry::GetTypeInArray(const
 
     const XPTTypeDescriptor *td = &param->mType;
 
     for (uint16_t i = 0; i < dimension; i++) {
         if (td->Tag() != TD_ARRAY) {
             NS_ERROR("bad dimension");
             return NS_ERROR_INVALID_ARG;
         }
-        td = td->ArrayElementType();
+        td = td->ArrayElementType(mDescriptor);
     }
 
     *type = td;
     return NS_OK;
 }
 
 nsresult
 xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
@@ -544,17 +544,17 @@ xptiInterfaceEntry::GetInterfaceIsArgNum
     {
         NS_ERROR("bad index");
         return NS_ERROR_INVALID_ARG;
     }
 
     const XPTTypeDescriptor *td = &param->mType;
 
     while (td->Tag() == TD_ARRAY) {
-        td = td->ArrayElementType();
+        td = td->ArrayElementType(mDescriptor);
     }
 
     if (td->Tag() != TD_INTERFACE_IS_TYPE) {
         NS_ERROR("not an iid_is");
         return NS_ERROR_INVALID_ARG;
     }
 
     *argnum = td->ArgNum();
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
@@ -76,22 +76,16 @@ XPTInterfaceInfoManager::FreeInterfaceIn
 {
     gInterfaceInfoManager = nullptr;
 }
 
 XPTInterfaceInfoManager::XPTInterfaceInfoManager()
     :   mWorkingSet(),
         mResolveLock("XPTInterfaceInfoManager.mResolveLock")
 {
-    xptiTypelibGuts* typelib = xptiTypelibGuts::Create();
-
-    ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
-    for (uint16_t k = 0; k < XPTHeader::kNumInterfaces; k++) {
-        VerifyAndAddEntryIfNew(XPTHeader::kInterfaces + k, k, typelib);
-    }
 }
 
 XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
 {
     // We only do this on shutdown of the service.
     mWorkingSet.InvalidateInterfaceInfos();
 
     UnregisterWeakMemoryReporter(this);
@@ -99,33 +93,62 @@ XPTInterfaceInfoManager::~XPTInterfaceIn
 
 void
 XPTInterfaceInfoManager::InitMemoryReporter()
 {
     RegisterWeakMemoryReporter(this);
 }
 
 void
-XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
+XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
+{
+    XPTState state;
+    XPT_InitXDRState(&state, buf, length);
+
+    XPTCursor curs;
+    NotNull<XPTCursor*> cursor = WrapNotNull(&curs);
+    if (!XPT_MakeCursor(&state, XPT_HEADER, 0, cursor)) {
+        return;
+    }
+
+    XPTHeader *header = nullptr;
+    if (XPT_DoHeader(gXPTIStructArena, cursor, &header)) {
+        RegisterXPTHeader(header);
+    }
+}
+
+void
+XPTInterfaceInfoManager::RegisterXPTHeader(const XPTHeader* aHeader)
+{
+    if (aHeader->mMajorVersion >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
+        MOZ_ASSERT(!aHeader->mNumInterfaces, "bad libxpt");
+    }
+
+    xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader);
+
+    ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+    for(uint16_t k = 0; k < aHeader->mNumInterfaces; k++)
+        VerifyAndAddEntryIfNew(aHeader->mInterfaceDirectory + k, k, typelib);
+}
+
+void
+XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(const XPTInterfaceDirectoryEntry* iface,
                                                 uint16_t idx,
                                                 xptiTypelibGuts* typelib)
 {
-    static const nsID zeroIID =
-        { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
-
-    if (iface->mIID.Equals(zeroIID)) {
+    if (!iface->mInterfaceDescriptor)
         return;
-    }
 
     // The number of maximum methods is not arbitrary. It is the same value as
     // in xpcom/reflect/xptcall/genstubs.pl; do not change this value
     // without changing that one or you WILL see problems.
-    if (iface->mNumMethods > 250 && !iface->IsBuiltinClass()) {
+    if (iface->mInterfaceDescriptor->mNumMethods > 250 &&
+            !iface->mInterfaceDescriptor->IsBuiltinClass()) {
         NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
-        fprintf(stderr, "ignoring too large interface: %s\n", iface->Name());
+        fprintf(stderr, "ignoring too large interface: %s\n", iface->mName);
         return;
     }
 
     mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
     xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->mIID);
     if (entry) {
         // XXX validate this info to find possible inconsistencies
         return;
--- a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
+++ b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
@@ -15,58 +15,61 @@ using namespace mozilla;
 template <class T>
 class MOZ_NEEDS_NO_VTABLE_TYPE CheckNoVTable
 {
 };
 CheckNoVTable<xptiTypelibGuts> gChecker;
 
 // static
 xptiTypelibGuts*
-xptiTypelibGuts::Create()
+xptiTypelibGuts::Create(const XPTHeader* aHeader)
 {
+    NS_ASSERTION(aHeader, "bad param");
     size_t n = sizeof(xptiTypelibGuts) +
-               sizeof(xptiInterfaceEntry*) * (XPTHeader::kNumInterfaces - 1);
+               sizeof(xptiInterfaceEntry*) * (aHeader->mNumInterfaces - 1);
     void* place = XPT_CALLOC8(gXPTIStructArena, n);
     if (!place)
         return nullptr;
-    return new(place) xptiTypelibGuts();
+    return new(place) xptiTypelibGuts(aHeader);
 }
 
 xptiInterfaceEntry*
 xptiTypelibGuts::GetEntryAt(uint16_t i)
 {
     static const nsID zeroIID =
         { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
 
+    NS_ASSERTION(mHeader, "bad state");
     NS_ASSERTION(i < GetEntryCount(), "bad index");
 
     xptiInterfaceEntry* r = mEntryArray[i];
     if (r)
         return r;
 
-    const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
+    const XPTInterfaceDirectoryEntry* iface = mHeader->mInterfaceDirectory + i;
 
     XPTInterfaceInfoManager::xptiWorkingSet& set =
         XPTInterfaceInfoManager::GetSingleton()->mWorkingSet;
 
     {
         ReentrantMonitorAutoEnter monitor(set.mTableReentrantMonitor);
         if (iface->mIID.Equals(zeroIID))
-            r = set.mNameTable.Get(iface->Name());
+            r = set.mNameTable.Get(iface->mName);
         else
             r = set.mIIDTable.Get(iface->mIID);
     }
 
     if (r)
         SetEntryAt(i, r);
 
     return r;
 }
 
 const char*
 xptiTypelibGuts::GetEntryNameAt(uint16_t i)
 {
+    NS_ASSERTION(mHeader, "bad state");
     NS_ASSERTION(i < GetEntryCount(), "bad index");
 
-    const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
+    const XPTInterfaceDirectoryEntry* iface = mHeader->mInterfaceDirectory + i;
 
-    return iface->Name();
+    return iface->mName;
 }
--- a/xpcom/reflect/xptinfo/xptinfo.h
+++ b/xpcom/reflect/xptinfo/xptinfo.h
@@ -189,21 +189,21 @@ public:
         {*(XPTMethodDescriptor*)this = desc;}
 
     bool IsGetter() const { return !!(mFlags & kGetterMask); }
     bool IsSetter() const { return !!(mFlags & kSetterMask); }
     bool IsNotXPCOM() const { return !!(mFlags & kNotXPCOMMask); }
     bool IsHidden() const { return !!(mFlags & kHiddenMask); }
     bool WantsOptArgc() const { return !!(mFlags & kOptArgcMask); }
     bool WantsContext() const { return !!(mFlags & kContextMask); }
-    const char* GetName() const { return Name(); }
+    const char* GetName() const { return mName; }
     uint8_t GetParamCount() const { return mNumArgs; }
     const nsXPTParamInfo GetParam(uint8_t idx) const {
         MOZ_ASSERT(idx < GetParamCount(), "bad arg");
-        return Param(idx);
+        return mParams[idx];
     }
 
 private:
     static const uint8_t kGetterMask =   0x80;
     static const uint8_t kSetterMask =   0x40;
     static const uint8_t kNotXPCOMMask = 0x20;
     static const uint8_t kHiddenMask =   0x08;
     static const uint8_t kOptArgcMask =  0x04;
--- a/xpcom/reflect/xptinfo/xptiprivate.h
+++ b/xpcom/reflect/xptinfo/xptiprivate.h
@@ -10,16 +10,17 @@
 
 #include "nscore.h"
 #include <new>
 #include "nsISupports.h"
 
 // this after nsISupports, to pick up IID
 // so that xpt stuff doesn't try to define it itself...
 #include "xpt_struct.h"
+#include "xpt_xdr.h"
 
 #include "nsIInterfaceInfo.h"
 #include "nsIInterfaceInfoManager.h"
 #include "xptinfo.h"
 #include "ShimInterfaceInfo.h"
 
 #include "nsIServiceManager.h"
 #include "nsIFile.h"
@@ -56,48 +57,51 @@
 #include <stdarg.h>
 
 /***************************************************************************/
 
 class xptiInterfaceInfo;
 class xptiInterfaceEntry;
 class xptiTypelibGuts;
 
-struct XPTArena;
 extern XPTArena* gXPTIStructArena;
 
 /***************************************************************************/
 
 /***************************************************************************/
 
 // No virtuals.
 // These are always constructed in the struct arena using placement new.
 // dtor need not be called.
 
 class xptiTypelibGuts
 {
 public:
-    static xptiTypelibGuts* Create();
+    static xptiTypelibGuts* Create(const XPTHeader* aHeader);
 
-    uint16_t GetEntryCount() const { return XPTHeader::kNumInterfaces; }
+    uint16_t GetEntryCount() const {return mHeader->mNumInterfaces;}
 
     void                SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
     {
+        NS_ASSERTION(mHeader,"bad state!");
         NS_ASSERTION(i < GetEntryCount(),"bad param!");
         mEntryArray[i] = ptr;
     }
 
     xptiInterfaceEntry* GetEntryAt(uint16_t i);
     const char* GetEntryNameAt(uint16_t i);
 
 private:
-    xptiTypelibGuts() = default;
+    explicit xptiTypelibGuts(const XPTHeader* aHeader)
+        : mHeader(aHeader)
+    { }
     ~xptiTypelibGuts();
 
 private:
+    const XPTHeader*     mHeader;        // hold pointer into arena
     xptiInterfaceEntry*  mEntryArray[1]; // Always last. Sized to fit.
 };
 
 /***************************************************************************/
 
 /***************************************************************************/
 
 // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
@@ -142,17 +146,17 @@ private:
 
 // No virtual methods.
 // We always create in the struct arena and construct using "placement new".
 // No members need dtor calls.
 
 class xptiInterfaceEntry
 {
 public:
-    static xptiInterfaceEntry* Create(const XPTInterfaceDescriptor* aIface,
+    static xptiInterfaceEntry* Create(const XPTInterfaceDirectoryEntry* aEntry,
                                       xptiTypelibGuts* aTypelib);
 
     enum {
         PARTIALLY_RESOLVED    = 1,
         FULLY_RESOLVED        = 2,
         RESOLVE_FAILED        = 3
     };
 
@@ -238,17 +242,17 @@ public:
     nsresult IsIID(const nsIID * IID, bool *_retval);
     nsresult GetNameShared(const char **name);
     nsresult GetIIDShared(const nsIID * *iid);
     nsresult IsFunction(bool *_retval);
     nsresult HasAncestor(const nsIID * iid, bool *_retval);
     nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
 
 private:
-    xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
+    xptiInterfaceEntry(const XPTInterfaceDirectoryEntry* aDescriptor,
                        xptiTypelibGuts* aTypelib);
     ~xptiInterfaceEntry();
 
     void SetResolvedState(int state)
         {mFlags.SetState(uint8_t(state));}
 
     bool Resolve();
 
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -25,23 +25,29 @@ test_progs = [
 SimplePrograms(test_progs)
 
 USE_LIBS += ['mfbt']
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
 if CONFIG['COMPILE_ENVIRONMENT']:
     TEST_HARNESS_FILES.xpcshell.xpcom.tests.unit += [
+        '!/dist/bin/components/xpcomtest.xpt',
+    ]
+    TEST_HARNESS_FILES.xpcshell.xpcom.tests.unit += [
         '!%s%s' % (f, CONFIG['BIN_SUFFIX']) for f in test_progs
     ]
 
 XPIDL_MODULE = 'xpcomtest'
 XPIDL_SOURCES += [
     'NotXPCOMTest.idl',
 ]
 
+# Don't add our test-only .xpt files to the normal manifests
+XPIDL_NO_MANIFEST = True
+
 LOCAL_INCLUDES += [
     '../ds',
 ]
 
 RESOURCE_FILES += [
     'test.properties',
 ]
--- a/xpcom/typelib/xpt/moz.build
+++ b/xpcom/typelib/xpt/moz.build
@@ -5,25 +5,24 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 Library('xpt')
 
 DIRS += ['tools']
 
 UNIFIED_SOURCES += [
     'xpt_arena.cpp',
-]
-
-SOURCES += [
-    '!XPTInfo.cpp',
+    'xpt_struct.cpp',
+    'xpt_xdr.cpp',
 ]
 
 EXPORTS += [
     'xpt_arena.h',
     'xpt_struct.h',
+    'xpt_xdr.h',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '!/xpcom/base',
     '/xpcom/base',
 ]
--- a/xpcom/typelib/xpt/tools/xpt.py
+++ b/xpcom/typelib/xpt/tools/xpt.py
@@ -29,19 +29,19 @@
 # are those of the authors and should not be interpreted as representing
 # official policies, either expressed or implied, of the Mozilla
 # Foundation.
 
 """
 A module for working with XPCOM Type Libraries.
 
 The XPCOM Type Library File Format is described at:
-  https://www-archive.mozilla.org/scriptable/typelib_file.html
-It is used to provide type information for calling methods on XPCOM
-objects from scripting languages such as JavaScript.
+http://www.mozilla.org/scriptable/typelib_file.html . It is used
+to provide type information for calling methods on XPCOM objects
+from scripting languages such as JavaScript.
 
 This module provides a set of classes representing the parts of
 a typelib in a high-level manner, as well as methods for reading
 and writing them from files.
 
 The usable public interfaces are currently:
 Typelib.read(input_file) - read a typelib from a file on disk or file-like
                            object, return a Typelib object.
@@ -129,133 +129,16 @@ class IndexedList(object):
 
     def __getitem__(self, index):
         return self._list[index]
 
     def __len__(self):
         return len(self._list)
 
 
-class CodeGenData(object):
-    """
-    This stores the top-level data needed to generate XPT information in C++.
-    |methods| and |constants| are the top-level declarations in the module.
-    These contain names, and so are not likely to benefit from deduplication.
-    |params| are the lists of parameters for |methods|, stored concatenated.
-    These are deduplicated if there are only a few. |types| and |strings| are
-    side data stores for the other things, and are deduplicated.
-
-    """
-
-    def __init__(self):
-        self.interfaces = []
-
-        self.types = []
-        self.type_indexes = {}
-
-        self.params = []
-        self.params_indexes = {}
-
-        self.methods = []
-
-        self.constants = []
-
-        self.strings = []
-        self.string_indexes = {}
-        self.curr_string_index = 0
-
-    @staticmethod
-    def write_array_body(fd, iterator):
-        fd.write("{\n")
-        for s in iterator:
-            fd.write("  %s,\n" % s)
-        fd.write("};\n\n")
-
-    def finish(self, fd):
-        fd.write("const uint16_t XPTHeader::kNumInterfaces = %s;\n\n" % len(self.interfaces))
-
-        fd.write("const XPTInterfaceDescriptor XPTHeader::kInterfaces[] = ")
-        CodeGenData.write_array_body(fd, self.interfaces)
-
-        fd.write("const XPTTypeDescriptor XPTHeader::kTypes[] = ")
-        CodeGenData.write_array_body(fd, self.types)
-
-        fd.write("const XPTParamDescriptor XPTHeader::kParams[] = ")
-        CodeGenData.write_array_body(fd, self.params)
-
-        fd.write("const XPTMethodDescriptor XPTHeader::kMethods[] = ")
-        CodeGenData.write_array_body(fd, self.methods)
-
-        fd.write("const XPTConstDescriptor XPTHeader::kConsts[] = ")
-        CodeGenData.write_array_body(fd, self.constants)
-
-        fd.write("const char XPTHeader::kStrings[] = {\n")
-        if self.strings:
-            for s in self.strings:
-                # Store each string as individual characters to work around
-                # MSVC's limit of 65k characters for a single string literal
-                # (error C1091).
-                s_index = self.string_indexes[s]
-                fd.write("    '%s', '\\0', // %s %d\n" % ("', '".join(list(s)), s, s_index))
-        else:
-            fd.write('""')
-        fd.write('};\n\n')
-
-    def add_interface(self, new_interface):
-        assert new_interface
-        self.interfaces.append(new_interface)
-
-    def add_type(self, new_type):
-        assert isinstance(new_type, basestring)
-        if new_type in self.type_indexes:
-            return self.type_indexes[new_type]
-        index = len(self.types)
-        self.types.append(new_type)
-        self.type_indexes[new_type] = index
-        return index
-
-    def add_params(self, new_params):
-        # Always represent empty parameter lists as being at 0, for no
-        # particular reason beside it being nicer.
-        if len(new_params) == 0:
-            return 0
-
-        index = len(self.params)
-        # The limit of 4 here is fairly arbitrary. The idea is to not
-        # spend time adding large things to the cache that have little
-        # chance of getting used again.
-        if len(new_params) <= 4:
-            params_key = "".join(new_params)
-            if params_key in self.params_indexes:
-                return self.params_indexes[params_key]
-            else:
-                self.params_indexes[params_key] = index
-        self.params += new_params
-        return index
-
-    def add_methods(self, new_methods):
-        index = len(self.methods)
-        self.methods += new_methods
-        return index
-
-    def add_constants(self, new_constants):
-        index = len(self.constants)
-        self.constants += new_constants
-        return index
-
-    def add_string(self, new_string):
-        if new_string in self.string_indexes:
-            return self.string_indexes[new_string]
-        index = self.curr_string_index
-        self.strings.append(new_string)
-        self.string_indexes[new_string] = index
-        self.curr_string_index += len(new_string) + 1
-        return index
-
-
 # Descriptor types as described in the spec
 class Type(object):
     """
     Data type of a method parameter or return value. Do not instantiate
     this class directly. Rather, use one of its subclasses.
 
     """
     _prefixdescriptor = struct.Struct(">B")
@@ -375,23 +258,16 @@ class Type(object):
         Write a TypeDescriptor to |file|, which is assumed
         to be seeked to the proper position. For types other than
         SimpleType, this is not sufficient for writing the TypeDescriptor,
         and the subclass method must be called.
 
         """
         file.write(Type._prefixdescriptor.pack(self.encodeflags() | self.tag))
 
-    def typeDescriptorPrefixString(self):
-        """
-        Return a string for the C++ code to represent the XPTTypeDescriptorPrefix.
-
-        """
-        return "{0x%x}" % (self.encodeflags() | self.tag)
-
 
 class SimpleType(Type):
     """
     A simple data type. (SimpleTypeDescriptor from the typelib specification.)
 
     """
     _cache = {}
 
@@ -430,19 +306,16 @@ class SimpleType(Type):
 
         if self.pointer:
             if self.reference:
                 s += " &"
             else:
                 s += " *"
         return s
 
-    def code_gen(self, typelib, cd):
-        return "{%s, 0, 0}" % self.typeDescriptorPrefixString()
-
 
 class InterfaceType(Type):
     """
     A type representing a pointer to an IDL-defined interface.
     (InterfaceTypeDescriptor from the typelib specification.)
 
     """
     _descriptor = struct.Struct(">H")
@@ -488,22 +361,16 @@ class InterfaceType(Type):
         Write an InterfaceTypeDescriptor to |file|, which is assumed
         to be seeked to the proper position.
 
         """
         Type.write(self, typelib, file)
         # write out the interface index (1-based)
         file.write(InterfaceType._descriptor.pack(typelib.interfaces.index(self.iface) + 1))
 
-    def code_gen(self, typelib, cd):
-        index = typelib.interfaces.index(self.iface) + 1
-        hi = int(index / 256)
-        lo = index - (hi * 256)
-        return "{%s, %d, %d}" % (self.typeDescriptorPrefixString(), hi, lo)
-
     def __str__(self):
         if self.iface:
             return self.iface.name
         return "unknown interface"
 
 
 class InterfaceIsType(Type):
     """
@@ -553,20 +420,16 @@ class InterfaceIsType(Type):
         """
         Write an InterfaceIsTypeDescriptor to |file|, which is assumed
         to be seeked to the proper position.
 
         """
         Type.write(self, typelib, file)
         file.write(InterfaceIsType._descriptor.pack(self.param_index))
 
-    def code_gen(self, typelib, cd):
-        return "{%s, %d, 0}" % (self.typeDescriptorPrefixString(),
-                                self.param_index)
-
     def __str__(self):
         return "InterfaceIs *"
 
 
 class ArrayType(Type):
     """
     A type representing an Array of elements of another type, whose
     size and length are passed as separate parameters to a method.
@@ -617,22 +480,16 @@ class ArrayType(Type):
         to be seeked to the proper position.
 
         """
         Type.write(self, typelib, file)
         file.write(ArrayType._descriptor.pack(self.size_is_arg_num,
                                               self.length_is_arg_num))
         self.element_type.write(typelib, file)
 
-    def code_gen(self, typelib, cd):
-        element_type_index = cd.add_type(self.element_type.code_gen(typelib, cd))
-        return "{%s, %d, %d}" % (self.typeDescriptorPrefixString(),
-                                 self.size_is_arg_num,
-                                 element_type_index)
-
     def __str__(self):
         return "%s []" % str(self.element_type)
 
 
 class StringWithSizeType(Type):
     """
     A type representing a UTF-8 encoded string whose size and length
     are passed as separate arguments to a method. (StringWithSizeTypeDescriptor
@@ -679,20 +536,16 @@ class StringWithSizeType(Type):
         Write a StringWithSizeTypeDescriptor to |file|, which is assumed
         to be seeked to the proper position.
 
         """
         Type.write(self, typelib, file)
         file.write(StringWithSizeType._descriptor.pack(self.size_is_arg_num,
                                                        self.length_is_arg_num))
 
-    def code_gen(self, typelib, cd):
-        return "{%s, %d, 0}" % (self.typeDescriptorPrefixString(),
-                                self.size_is_arg_num)
-
     def __str__(self):
         return "string_s"
 
 
 class WideStringWithSizeType(Type):
     """
     A type representing a UTF-16 encoded string whose size and length
     are passed as separate arguments to a method.
@@ -739,20 +592,16 @@ class WideStringWithSizeType(Type):
         Write a WideStringWithSizeTypeDescriptor to |file|, which is assumed
         to be seeked to the proper position.
 
         """
         Type.write(self, typelib, file)
         file.write(WideStringWithSizeType._descriptor.pack(self.size_is_arg_num,
                                                            self.length_is_arg_num))
 
-    def code_gen(self, typelib, cd):
-        return "{%s, %d, 0}" % (self.typeDescriptorPrefixString(),
-                                self.size_is_arg_num)
-
     def __str__(self):
         return "wstring_s"
 
 
 class CachedStringWriter(object):
     """
     A cache that sits in front of a file to avoid adding the same
     string multiple times.
@@ -871,19 +720,16 @@ class Param(object):
         """
         Write a ParamDescriptor to |file|, which is assumed to be seeked
         to the correct position.
 
         """
         file.write(Param._descriptorstart.pack(self.encodeflags()))
         self.type.write(typelib, file)
 
-    def code_gen(self, typelib, cd):
-        return "{0x%x, %s}" % (self.encodeflags(), self.type.code_gen(typelib, cd))
-
     def prefix(self):
         """
         Return a human-readable string representing the flags set
         on this Param.
 
         """
         s = ""
         if self.out:
@@ -1054,48 +900,29 @@ class Method(object):
         """
         Write this method's name to |string_writer|'s file.
         Assumes that this file is currently seeked to an unused
         portion of the data pool.
 
         """
         self._name_offset = string_writer.write(self.name)
 
-    def code_gen(self, typelib, cd):
-        # Don't store any extra info for methods that can't be called from JS.
-        if self.notxpcom or self.hidden:
-            string_index = 0
-            param_index = 0
-            num_params = 0
-        else:
-            string_index = cd.add_string(self.name)
-            param_index = cd.add_params([p.code_gen(typelib, cd) for p in self.params])
-            num_params = len(self.params)
-
-        return "{%d, %d, 0x%x, %d}" % (string_index,
-                                       param_index,
-                                       self.encodeflags(),
-                                       num_params)
 
 class Constant(object):
     """
     A constant value of a specific type defined on an interface.
     (ConstantDescriptor from the typelib specification.)
 
     """
     _descriptorstart = struct.Struct(">I")
     # Actual value is restricted to this set of types
     typemap = {Type.Tags.int16: '>h',
                Type.Tags.uint16: '>H',
                Type.Tags.int32: '>i',
                Type.Tags.uint32: '>I'}
-    memberTypeMap = {Type.Tags.int16: 'int16_t',
-                     Type.Tags.uint16: 'uint16_t',
-                     Type.Tags.int32: 'int32_t',
-                     Type.Tags.uint32: 'uint32_t'}
 
     def __init__(self, name, type, value):
         self.name = name
         self._name_offset = 0
         self.type = type
         self.value = value
 
     def __cmp__(self, other):
@@ -1144,25 +971,16 @@ class Constant(object):
         """
         Write this constants's name to |string_writer|'s file.
         Assumes that this file is currently seeked to an unused
         portion of the data pool.
 
         """
         self._name_offset = string_writer.write(self.name)
 
-    def code_gen(self, typelib, cd):
-        string_index = cd.add_string(self.name)
-
-        # The static cast is needed for disambiguation.
-        return "{%d, %s, XPTConstValue(static_cast<%s>(%d))}" % (string_index,
-                                                                 self.type.code_gen(typelib, cd),
-                                                                 Constant.memberTypeMap[self.type.tag],
-                                                                 self.value)
-
     def __repr__(self):
         return "Constant(%s, %s, %d)" % (self.name, str(self.type), self.value)
 
 
 class Interface(object):
     """
     An Interface represents an object, with its associated methods
     and constant values.
@@ -1348,45 +1166,16 @@ class Interface(object):
         """
         self._name_offset = string_writer.write(self.name)
         self._namespace_offset = string_writer.write(self.namespace)
         for m in self.methods:
             m.write_name(string_writer)
         for c in self.constants:
             c.write_name(string_writer)
 
-    def code_gen_interface(self, typelib, cd):
-        iid = Typelib.code_gen_iid(self.iid)
-        string_index = cd.add_string(self.name)
-
-        parent_idx = 0
-        if self.resolved:
-            methods_index = cd.add_methods([m.code_gen(typelib, cd) for m in self.methods])
-            constants_index = cd.add_constants([c.code_gen(typelib, cd) for c in self.constants])
-            if self.parent:
-                parent_idx = typelib.interfaces.index(self.parent) + 1
-        else:
-            # Unresolved interfaces only have their name and IID set to non-zero values.
-            methods_index = 0
-            constants_index = 0
-            assert len(self.methods) == 0
-            assert len(self.constants) == 0
-            assert self.encodeflags() == 0
-
-        return "{%s, %s, %d, %d, %d, %d, %d, 0x%x} /* %s */" % (
-            iid,
-            string_index,
-            methods_index,
-            constants_index,
-            parent_idx,
-            len(self.methods),
-            len(self.constants),
-            self.encodeflags(),
-            self.name)
-
 
 class Typelib(object):
     """
     A typelib represents one entire typelib file and all the interfaces
     referenced within, whether defined entirely within the typelib or
     merely referenced by name or IID.
 
     Typelib objects may be instantiated directly and populated with data,
@@ -1494,26 +1283,16 @@ class Typelib(object):
             iface = Interface(name, iid, namespace)
             iface._descriptor_offset = ide[3]
             iface.xpt_filename = xpt.filename
             xpt.interfaces.append(iface)
         for iface in xpt.interfaces:
             iface.read_descriptor(xpt, data, data_pool_offset)
         return xpt
 
-    @staticmethod
-    def code_gen_iid(iid):
-        chunks = iid.split('-')
-        return "{0x%s, 0x%s, 0x%s, {0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}" % (
-            chunks[0], chunks[1], chunks[2],
-            int(chunks[3][0:2], 16), int(chunks[3][2:4], 16),
-            int(chunks[4][0:2], 16), int(chunks[4][2:4], 16),
-            int(chunks[4][4:6], 16), int(chunks[4][6:8], 16),
-            int(chunks[4][8:10], 16), int(chunks[4][10:12], 16))
-
     def __repr__(self):
         return "<Typelib with %d interfaces>" % len(self.interfaces)
 
     def _sanityCheck(self):
         """
         Check certain assumptions about data contained in this typelib.
         Sort the interfaces array by IID, check that all interfaces
         referenced by methods exist in the array.
@@ -1578,49 +1357,16 @@ class Typelib(object):
         """
         self._sanityCheck()
         if isinstance(output_file, basestring):
             with open(output_file, "wb") as f:
                 self.writefd(f)
         else:
             self.writefd(output_file)
 
-    def code_gen_writefd(self, fd):
-        cd = CodeGenData()
-
-        for i in self.interfaces:
-            cd.add_interface(i.code_gen_interface(self, cd))
-
-        fd.write("""/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. */
-
-#include "xpt_struct.h"
-
-""")
-        cd.finish(fd)
-
-    def code_gen_write(self, output_file):
-        """
-        Write the contents of this typelib to |output_file|,
-        which can be either a filename or a file-like object.
-
-        """
-        self._sanityCheck()
-
-        if isinstance(output_file, basestring):
-            with open(output_file, "wb") as f:
-                self.code_gen_writefd(f)
-        else:
-            self.code_gen_writefd(output_file)
-
     def dump(self, out):
         """
         Print a human-readable listing of the contents of this typelib
         to |out|, in the format of xpt_dump.
 
         """
         out.write("""Header:
    Major version:         %d
@@ -1828,16 +1574,14 @@ def xpt_link(inputs):
     interfaces = list(required_interfaces)
 
     # Re-sort interfaces (by IID)
     interfaces.sort()
     return Typelib(interfaces=interfaces)
 
 if __name__ == '__main__':
     if len(sys.argv) < 3:
-        print >>sys.stderr, "xpt <dump|link|linkgen> <files>"
+        print >>sys.stderr, "xpt <dump|link> <files>"
         sys.exit(1)
     if sys.argv[1] == 'dump':
         xpt_dump(sys.argv[2])
     elif sys.argv[1] == 'link':
         xpt_link(sys.argv[3:]).write(sys.argv[2])
-    elif sys.argv[1] == 'linkgen':
-        xpt_link(sys.argv[3:]).code_gen_write(sys.argv[2])
new file mode 100644
--- /dev/null
+++ b/xpcom/typelib/xpt/xpt_struct.cpp
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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/. */
+
+/* Implementation of XDR routines for typelib structures. */
+
+#include "xpt_xdr.h"
+#include "xpt_struct.h"
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+using mozilla::WrapNotNull;
+
+#define XPT_MAGIC "XPCOM\nTypeLib\r\n\032"
+#define XPT_MAGIC_STRING "XPCOM\\nTypeLib\\r\\n\\032"
+
+/*
+ * Annotation records are variable-size records used to store secondary
+ * information about the typelib, e.g. such as the name of the tool that
+ * generated the typelib file, the date it was generated, etc.  The
+ * information is stored with very loose format requirements so as to
+ * allow virtually any private data to be stored in the typelib.
+ *
+ * There are two types of Annotations:
+ *
+ * EmptyAnnotation
+ * PrivateAnnotation
+ *
+ * The tag field of the prefix discriminates among the variant record
+ * types for Annotation's.  If the tag is 0, this record is an
+ * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to
+ * indicate an array of Annotation's that's completely empty.  If the tag
+ * is 1, the record is a PrivateAnnotation.
+ *
+ * We don't actually store annotations; we just skip over them if they are
+ * present.
+ */
+
+#define XPT_ANN_LAST    0x80
+#define XPT_ANN_PRIVATE 0x40
+
+#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
+#define XPT_ANN_IS_PRIVATE(flags)(flags & XPT_ANN_PRIVATE)
+
+
+/***************************************************************************/
+/* Forward declarations. */
+
+static bool
+DoInterfaceDirectoryEntry(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                          XPTInterfaceDirectoryEntry *ide);
+
+static bool
+DoConstDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                  XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
+
+static bool
+DoMethodDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                   XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
+
+static bool
+SkipAnnotation(NotNull<XPTCursor*> cursor, bool *isLast);
+
+static bool
+DoInterfaceDescriptor(XPTArena *arena, NotNull<XPTCursor*> outer,
+                      const XPTInterfaceDescriptor **idp);
+
+static bool
+DoTypeDescriptorPrefix(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                       XPTTypeDescriptorPrefix *tdp);
+
+static bool
+DoTypeDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                 XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
+
+static bool
+DoParamDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                  XPTParamDescriptor *pd, XPTInterfaceDescriptor *id);
+
+/***************************************************************************/
+
+bool
+XPT_DoHeader(XPTArena *arena, NotNull<XPTCursor*> cursor, XPTHeader **headerp)
+{
+    unsigned int i;
+    uint32_t file_length = 0;
+    uint32_t ide_offset;
+
+    XPTHeader* header = XPT_NEWZAP(arena, XPTHeader);
+    if (!header)
+        return false;
+    *headerp = header;
+
+    uint8_t magic[16];
+    for (i = 0; i < sizeof(magic); i++) {
+        if (!XPT_Do8(cursor, &magic[i]))
+            return false;
+    }
+
+    if (strncmp((const char*)magic, XPT_MAGIC, 16) != 0) {
+        /* Require that the header contain the proper magic */
+        fprintf(stderr,
+                "libxpt: bad magic header in input file; "
+                "found '%s', expected '%s'\n",
+                magic, XPT_MAGIC_STRING);
+        return false;
+    }
+
+    uint8_t minor_version;
+    if (!XPT_Do8(cursor, &header->mMajorVersion) ||
+        !XPT_Do8(cursor, &minor_version)) {
+        return false;
+    }
+
+    if (header->mMajorVersion >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
+        /* This file is newer than we are and set to an incompatible version
+         * number. We must set the header state thusly and return.
+         */
+        header->mNumInterfaces = 0;
+        return true;
+    }
+
+    if (!XPT_Do16(cursor, &header->mNumInterfaces) ||
+        !XPT_Do32(cursor, &file_length) ||
+        !XPT_Do32(cursor, &ide_offset)) {
+        return false;
+    }
+
+    /*
+     * Make sure the file length reported in the header is the same size as
+     * as our buffer unless it is zero (not set)
+     */
+    if (file_length != 0 &&
+        cursor->state->pool_allocated < file_length) {
+        fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
+            stderr);
+        return false;
+    }
+
+    uint32_t data_pool;
+    if (!XPT_Do32(cursor, &data_pool))
+        return false;
+
+    XPT_SetDataOffset(cursor->state, data_pool);
+
+    XPTInterfaceDirectoryEntry* interface_directory = nullptr;
+
+    if (header->mNumInterfaces) {
+        size_t n = header->mNumInterfaces * sizeof(XPTInterfaceDirectoryEntry);
+        interface_directory =
+            static_cast<XPTInterfaceDirectoryEntry*>(XPT_CALLOC8(arena, n));
+        if (!interface_directory)
+            return false;
+    }
+
+    /*
+     * Iterate through the annotations rather than recurring, to avoid blowing
+     * the stack on large xpt files. We don't actually store annotations, we
+     * just skip over them.
+     */
+    bool isLast;
+    do {
+        if (!SkipAnnotation(cursor, &isLast))
+            return false;
+    } while (!isLast);
+
+    /* shouldn't be necessary now, but maybe later */
+    XPT_SeekTo(cursor, ide_offset);
+
+    for (i = 0; i < header->mNumInterfaces; i++) {
+        if (!DoInterfaceDirectoryEntry(arena, cursor,
+                                       &interface_directory[i]))
+            return false;
+    }
+
+    header->mInterfaceDirectory = interface_directory;
+
+    return true;
+}
+
+/* InterfaceDirectoryEntry records go in the header */
+bool
+DoInterfaceDirectoryEntry(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                          XPTInterfaceDirectoryEntry *ide)
+{
+    const char* dummy_name_space;
+
+    /* write the IID in our cursor space */
+    if (!XPT_DoIID(cursor, &(ide->mIID)) ||
+
+        /* write the name string in the data pool, and the offset in our
+           cursor space */
+        !XPT_DoCString(arena, cursor, &(ide->mName)) ||
+
+        /* don't write the name_space string in the data pool, because we don't
+         * need it. Do write the offset in our cursor space */
+        !XPT_DoCString(arena, cursor, &dummy_name_space, /* ignore = */ true) ||
+
+        /* do InterfaceDescriptors */
+        !DoInterfaceDescriptor(arena, cursor, &ide->mInterfaceDescriptor)) {
+        return false;
+    }
+
+    return true;
+}
+
+static bool
+InterfaceDescriptorAddType(XPTArena *arena,
+                           XPTInterfaceDescriptor *id,
+                           XPTTypeDescriptor *td)
+{
+    const XPTTypeDescriptor *old = id->mAdditionalTypes;
+    XPTTypeDescriptor *new_;
+    size_t old_size = id->mNumAdditionalTypes * sizeof(XPTTypeDescriptor);
+    size_t new_size = old_size + sizeof(XPTTypeDescriptor);
+
+    /* XXX should grow in chunks to minimize alloc overhead */
+    new_ = static_cast<XPTTypeDescriptor*>(XPT_CALLOC8(arena, new_size));
+    if (!new_)
+        return false;
+    if (old) {
+        memcpy(new_, old, old_size);
+    }
+
+    new_[id->mNumAdditionalTypes] = *td;
+    id->mAdditionalTypes = new_;
+
+    if (id->mNumAdditionalTypes == UINT8_MAX)
+        return false;
+
+    id->mNumAdditionalTypes += 1;
+    return true;
+}
+
+bool
+DoInterfaceDescriptor(XPTArena *arena, NotNull<XPTCursor*> outer,
+                      const XPTInterfaceDescriptor **idp)
+{
+    XPTInterfaceDescriptor *id;
+    XPTCursor curs;
+    NotNull<XPTCursor*> cursor = WrapNotNull(&curs);
+    uint32_t i, id_sz = 0;
+
+    id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
+    if (!id)
+        return false;
+    *idp = id;
+
+    if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
+        return false;
+
+    if (!XPT_Do32(outer, &cursor->offset))
+        return false;
+    if (!cursor->offset) {
+        *idp = NULL;
+        return true;
+    }
+    if(!XPT_Do16(cursor, &id->mParentInterface) ||
+       !XPT_Do16(cursor, &id->mNumMethods)) {
+        return false;
+    }
+
+    XPTMethodDescriptor* method_descriptors = nullptr;
+
+    if (id->mNumMethods) {
+        size_t n = id->mNumMethods * sizeof(XPTMethodDescriptor);
+        method_descriptors =
+            static_cast<XPTMethodDescriptor*>(XPT_CALLOC8(arena, n));
+        if (!method_descriptors)
+            return false;
+    }
+
+    for (i = 0; i < id->mNumMethods; i++) {
+        if (!DoMethodDescriptor(arena, cursor, &method_descriptors[i], id))
+            return false;
+    }
+
+    id->mMethodDescriptors = method_descriptors;
+
+    if (!XPT_Do16(cursor, &id->mNumConstants)) {
+        return false;
+    }
+
+    XPTConstDescriptor* const_descriptors = nullptr;
+
+    if (id->mNumConstants) {
+        size_t n = id->mNumConstants * sizeof(XPTConstDescriptor);
+        const_descriptors =
+            static_cast<XPTConstDescriptor*>(XPT_CALLOC8(arena, n));
+        if (!const_descriptors)
+            return false;
+    }
+
+    for (i = 0; i < id->mNumConstants; i++) {
+        if (!DoConstDescriptor(arena, cursor, &const_descriptors[i], id)) {
+            return false;
+        }
+    }
+
+    id->mConstDescriptors = const_descriptors;
+
+    if (!XPT_Do8(cursor, &id->mFlags)) {
+        return false;
+    }
+
+    return true;
+}
+
+bool
+DoConstDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                  XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
+{
+    bool ok = false;
+
+    if (!XPT_DoCString(arena, cursor, &cd->mName) ||
+        !DoTypeDescriptor(arena, cursor, &cd->mType, id)) {
+
+        return false;
+    }
+
+    switch (cd->mType.Tag()) {
+      case TD_INT16:
+        ok = XPT_Do16(cursor, (uint16_t*) &cd->mValue.i16);
+        break;
+      case TD_INT32:
+        ok = XPT_Do32(cursor, (uint32_t*) &cd->mValue.i32);
+        break;
+      case TD_UINT16:
+        ok = XPT_Do16(cursor, &cd->mValue.ui16);
+        break;
+      case TD_UINT32:
+        ok = XPT_Do32(cursor, &cd->mValue.ui32);
+        break;
+      default:
+        MOZ_ASSERT(false, "illegal type");
+        break;
+    }
+
+    return ok;
+}
+
+bool
+DoMethodDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                   XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
+{
+    int i;
+
+    if (!XPT_Do8(cursor, &md->mFlags) ||
+        !XPT_DoCString(arena, cursor, &md->mName) ||
+        !XPT_Do8(cursor, &md->mNumArgs))
+        return false;
+
+    XPTParamDescriptor* params = nullptr;
+
+    if (md->mNumArgs) {
+        size_t n = md->mNumArgs * sizeof(XPTParamDescriptor);
+        params = static_cast<XPTParamDescriptor*>(XPT_CALLOC8(arena, n));
+        if (!params)
+            return false;
+    }
+
+    for(i = 0; i < md->mNumArgs; i++) {
+        if (!DoParamDescriptor(arena, cursor, &params[i], id))
+            return false;
+    }
+
+    md->mParams = params;
+
+    // |result| appears in the on-disk format but it isn't used,
+    // because a method is either notxpcom, in which case it can't be
+    // called from script so the XPT information is irrelevant, or the
+    // result type is nsresult.
+    XPTParamDescriptor result;
+    if (!DoParamDescriptor(arena, cursor, &result, id))
+        return false;
+
+    return true;
+}
+
+bool
+DoParamDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                  XPTParamDescriptor *pd, XPTInterfaceDescriptor *id)
+{
+    if (!XPT_Do8(cursor, &pd->mFlags) ||
+        !DoTypeDescriptor(arena, cursor, &pd->mType, id))
+        return false;
+
+    return true;
+}
+
+bool
+DoTypeDescriptorPrefix(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                       XPTTypeDescriptorPrefix *tdp)
+{
+    return XPT_Do8(cursor, &tdp->mFlags);
+}
+
+bool
+DoTypeDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
+                 XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
+{
+    if (!DoTypeDescriptorPrefix(arena, cursor, &td->mPrefix)) {
+        return false;
+    }
+
+    switch (td->Tag()) {
+      case TD_INTERFACE_TYPE:
+        uint16_t iface;
+        if (!XPT_Do16(cursor, &iface))
+            return false;
+        td->mData1 = (iface >> 8) & 0xff;
+        td->mData2 = iface & 0xff;
+        break;
+      case TD_INTERFACE_IS_TYPE:
+        if (!XPT_Do8(cursor, &td->mData1))
+            return false;
+        break;
+      case TD_ARRAY: {
+        // argnum2 appears in the on-disk format but it isn't used.
+        uint8_t argnum2 = 0;
+        if (!XPT_Do8(cursor, &td->mData1) ||
+            !XPT_Do8(cursor, &argnum2))
+            return false;
+
+        XPTTypeDescriptor elementTypeDescriptor;
+        if (!DoTypeDescriptor(arena, cursor, &elementTypeDescriptor, id))
+            return false;
+        if (!InterfaceDescriptorAddType(arena, id, &elementTypeDescriptor))
+            return false;
+        td->mData2 = id->mNumAdditionalTypes - 1;
+
+        break;
+      }
+      case TD_PSTRING_SIZE_IS:
+      case TD_PWSTRING_SIZE_IS: {
+        // argnum2 appears in the on-disk format but it isn't used.
+        uint8_t argnum2 = 0;
+        if (!XPT_Do8(cursor, &td->mData1) ||
+            !XPT_Do8(cursor, &argnum2))
+            return false;
+        break;
+      }
+      default:
+        /* nothing special */
+        break;
+    }
+    return true;
+}
+
+bool
+SkipAnnotation(NotNull<XPTCursor*> cursor, bool *isLast)
+{
+    uint8_t flags;
+    if (!XPT_Do8(cursor, &flags))
+        return false;
+
+    *isLast = XPT_ANN_IS_LAST(flags);
+
+    if (XPT_ANN_IS_PRIVATE(flags)) {
+        if (!XPT_SkipStringInline(cursor) ||
+            !XPT_SkipStringInline(cursor))
+            return false;
+    }
+
+    return true;
+}
+
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -1,44 +1,90 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 https://mozilla.org/MPL/2.0/. */
 
 /*
- * Structures for representing typelib structures in memory.
+ * Structures matching the in-memory representation of typelib structures.
  * http://www.mozilla.org/scriptable/typelib_file.html
  */
 
 #ifndef xpt_struct_h
 #define xpt_struct_h
 
 #include "nsID.h"
 #include <stdint.h>
 #include "mozilla/Assertions.h"
 
+/*
+ * Originally, I was going to have structures that exactly matched the on-disk
+ * representation, but that proved difficult: different compilers can pack
+ * their structs differently, and that makes overlaying them atop a
+ * read-from-disk byte buffer troublesome.  So now I just have some structures
+ * that are used in memory, and we're going to write a nice XDR library to
+ * write them to disk and stuff.  It is pure joy. -- shaver
+ */
+
+/* Structures for the typelib components */
+
+struct XPTHeader;
+struct XPTInterfaceDirectoryEntry;
 struct XPTInterfaceDescriptor;
 struct XPTConstDescriptor;
 struct XPTMethodDescriptor;
 struct XPTParamDescriptor;
 struct XPTTypeDescriptor;
 struct XPTTypeDescriptorPrefix;
 
+/*
+ * Every XPCOM typelib file begins with a header.
+ */
 struct XPTHeader {
-  static const uint16_t kNumInterfaces;
-  static const XPTInterfaceDescriptor kInterfaces[];
-  static const XPTTypeDescriptor kTypes[];
-  static const XPTParamDescriptor kParams[];
-  static const XPTMethodDescriptor kMethods[];
-  static const XPTConstDescriptor kConsts[];
+  // Some of these fields exists in the on-disk format but don't need to be
+  // stored in memory (other than very briefly, which can be done with local
+  // variables).
+
+  //uint8_t mMagic[16];
+  uint8_t mMajorVersion;
+  //uint8_t mMinorVersion;
+  uint16_t mNumInterfaces;
+  //uint32_t mFileLength;
+  const XPTInterfaceDirectoryEntry* mInterfaceDirectory;
+  //uint32_t mDataPool;
+};
 
-  // All of the strings for this header, including their null
-  // terminators, concatenated into a single string.
-  static const char kStrings[];
+/*
+ * Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION
+ * or higher is to be considered incompatible by this version of xpt and
+ * we will refuse to read it. We will return a header with magic, major and
+ * minor versions set from the file. num_interfaces will be set to zero to
+ * confirm our inability to read the file; i.e. even if some client of this
+ * library gets out of sync with us regarding the agreed upon value for
+ * XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces is zero we *know*
+ * that this library refused to read the file due to version incompatibility.
+ */
+#define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02
+
+/*
+ * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at
+ * the byte offset identified by the mInterfaceDirectory field in the file
+ * header.  The array is used to quickly locate an interface description
+ * using its IID.  No interface should appear more than once in the array.
+ */
+struct XPTInterfaceDirectoryEntry {
+  nsID mIID;
+  const char* mName;
+
+  // This field exists in the on-disk format. But it isn't used so we don't
+  // allocate space for it in memory.
+  //const char* mNameSpace;
+
+  const XPTInterfaceDescriptor* mInterfaceDescriptor;
 };
 
 /*
  * An InterfaceDescriptor describes a single XPCOM interface, including all of
  * its methods.
  */
 struct XPTInterfaceDescriptor {
   static const uint8_t kScriptableMask =                0x80;
@@ -46,47 +92,63 @@ struct XPTInterfaceDescriptor {
   static const uint8_t kBuiltinClassMask =              0x20;
   static const uint8_t kMainProcessScriptableOnlyMask = 0x10;
 
   bool IsScriptable() const { return !!(mFlags & kScriptableMask); }
   bool IsFunction() const { return !!(mFlags & kFunctionMask); }
   bool IsBuiltinClass() const { return !!(mFlags & kBuiltinClassMask); }
   bool IsMainProcessScriptableOnly() const { return !!(mFlags & kMainProcessScriptableOnlyMask); }
 
-  inline const char* Name() const;
-  inline const XPTMethodDescriptor& Method(size_t aIndex) const;
-  inline const XPTConstDescriptor& Const(size_t aIndex) const;
-
   /*
    * This field ordering minimizes the size of this struct.
+   * The fields are serialized on disk in a different order.
+   * See DoInterfaceDescriptor().
    */
-  nsID mIID;
-  uint32_t mName; // Index into XPTHeader::mStrings.
-  uint16_t mMethodDescriptors; // Index into XPTHeader::mMethods.
-  uint16_t mConstDescriptors; // Index into XPTHeader::mConsts.
+  const XPTMethodDescriptor* mMethodDescriptors;
+  const XPTConstDescriptor* mConstDescriptors;
+  const XPTTypeDescriptor* mAdditionalTypes;
   uint16_t mParentInterface;
   uint16_t mNumMethods;
   uint16_t mNumConstants;
   uint8_t mFlags;
+
+  /*
+   * mAdditionalTypes are used for arrays where we may need multiple
+   * XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still
+   * want to have a simple array of XPTMethodDescriptor (each with a single
+   * embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference
+   * to an 'additional_type'. That reference is an index in this
+   * "mAdditionalTypes" array. So a given XPTMethodDescriptor might have
+   * a whole chain of these XPTTypeDescriptors to represent, say, a multi
+   * dimensional array.
+   *
+   * Note that in the typelib file these additional types are stored 'inline'
+   * in the MethodDescriptor. But, in the typelib MethodDescriptors can be
+   * of varying sizes, where in XPT's in memory mapping of the data we want
+   * them to be of fixed size. This mAdditionalTypes scheme is here to allow
+   * for that.
+   */
+  uint8_t mNumAdditionalTypes;
 };
 
 /*
- * A TypeDescriptor is a union used to identify the type of a method
- * argument or return value.
+ * A TypeDescriptor is a variable-size record used to identify the type of a
+ * method argument or return value.
  *
  * There are three types of TypeDescriptors:
  *
  * SimpleTypeDescriptor
  * InterfaceTypeDescriptor
  * InterfaceIsTypeDescriptor
  *
  * The tag field in the prefix indicates which of the variant TypeDescriptor
- * records is being used, and hence which union members are valid. Values from 0
- * to 17 refer to SimpleTypeDescriptors. The value 18 designates an
- * InterfaceTypeDescriptor, while 19 represents an InterfaceIsTypeDescriptor.
+ * records is being used, and hence the way any remaining fields should be
+ * parsed. Values from 0 to 17 refer to SimpleTypeDescriptors. The value 18
+ * designates an InterfaceTypeDescriptor, while 19 represents an
+ * InterfaceIsTypeDescriptor.
  */
 
 /* why bother with a struct?  - other code relies on this being a struct */
 struct XPTTypeDescriptorPrefix {
   uint8_t TagPart() const {
     static const uint8_t kFlagMask = 0xe0;
     return (uint8_t) (mFlags & ~kFlagMask);
   }
@@ -136,19 +198,19 @@ struct XPTTypeDescriptor {
   uint8_t ArgNum() const {
     MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE ||
                Tag() == TD_PSTRING_SIZE_IS ||
                Tag() == TD_PWSTRING_SIZE_IS ||
                Tag() == TD_ARRAY);
     return mData1;
   }
 
-  const XPTTypeDescriptor* ArrayElementType() const {
+  const XPTTypeDescriptor* ArrayElementType(const XPTInterfaceDescriptor* aDescriptor) const {
     MOZ_ASSERT(Tag() == TD_ARRAY);
-    return &XPTHeader::kTypes[mData2];
+    return &aDescriptor->mAdditionalTypes[mData2];
   }
 
   // We store the 16-bit iface value as two 8-bit values in order to
   // avoid 16-bit alignment requirements for XPTTypeDescriptor, which
   // reduces its size and also the size of XPTParamDescriptor.
   uint16_t InterfaceIndex() const {
     MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE);
     return (mData1 << 8) | mData2;
@@ -161,83 +223,52 @@ struct XPTTypeDescriptor {
   // assert if the tag is invalid. The memory layout here doesn't exactly match
   // the on-disk format. This is to save memory. Some fields for some cases are
   // smaller than they are on disk or omitted entirely.
   uint8_t mData1;
   uint8_t mData2;
 };
 
 /*
- * A ConstDescriptor records the name and value of a scoped interface constant.
- * This is allowed only for a subset of types.
+ * A ConstDescriptor is a variable-size record that records the name and
+ * value of a scoped interface constant. This is allowed only for a subset
+ * of types.
  *
- * The type of the value record is determined by the contents of the associated
- * TypeDescriptor record. For instance, if type corresponds to int16_t, then
- * value is a 16-bit signed integer.
+ * The type (and thus the size) of the value record is determined by the
+ * contents of the associated TypeDescriptor record. For instance, if type
+ * corresponds to int16_t, then value is a two-byte record consisting of a
+ * 16-bit signed integer.
  */
 union XPTConstValue {
   int16_t i16;
   uint16_t ui16;
   int32_t i32;
   uint32_t ui32;
-
-  // These constructors are needed to statically initialize different cases of
-  // the union because MSVC does not support the use of designated initializers
-  // in C++ code. They need to be constexpr to ensure that no initialization code
-  // is run at startup, to enable sharing of this memory between Firefox processes.
-  explicit constexpr XPTConstValue(int16_t aInt) : i16(aInt) {}
-  explicit constexpr XPTConstValue(uint16_t aInt) : ui16(aInt) {}
-  explicit constexpr XPTConstValue(int32_t aInt) : i32(aInt) {}
-  explicit constexpr XPTConstValue(uint32_t aInt) : ui32(aInt) {}
-};
+}; /* varies according to type */
 
 struct XPTConstDescriptor {
-  const char* Name() const {
-    return &XPTHeader::kStrings[mName];
-  }
-
-  uint32_t mName; // Index into XPTHeader::mStrings.
+  const char* mName;
   XPTTypeDescriptor mType;
-  XPTConstValue mValue;
+  union XPTConstValue mValue;
 };
 
 /*
- * A ParamDescriptor is used to describe either a single argument to a method or
- * a method's result.
+ * A ParamDescriptor is a variable-size record used to describe either a
+ * single argument to a method or a method's result.
  */
 struct XPTParamDescriptor {
   uint8_t mFlags;
   XPTTypeDescriptor mType;
 };
 
 /*
- * A MethodDescriptor is used to describe a single interface method.
+ * A MethodDescriptor is a variable-size record used to describe a single
+ * interface method.
  */
 struct XPTMethodDescriptor {
-  const char* Name() const {
-    return &XPTHeader::kStrings[mName];
-  }
-  const XPTParamDescriptor& Param(uint8_t aIndex) const {
-    return XPTHeader::kParams[mParams + aIndex];
-  }
-
-  uint32_t mName; // Index into XPTHeader::mStrings.
-  uint32_t mParams; // Index into XPTHeader::mParams.
+  const char* mName;
+  const XPTParamDescriptor* mParams;
+  //XPTParamDescriptor mResult; // Present on disk, omitted here.
   uint8_t mFlags;
   uint8_t mNumArgs;
 };
 
-const char*
-XPTInterfaceDescriptor::Name() const {
-  return &XPTHeader::kStrings[mName];
-}
-
-const XPTMethodDescriptor&
-XPTInterfaceDescriptor::Method(size_t aIndex) const {
-  return XPTHeader::kMethods[mMethodDescriptors + aIndex];
-}
-
-const XPTConstDescriptor&
-XPTInterfaceDescriptor::Const(size_t aIndex) const {
-  return XPTHeader::kConsts[mConstDescriptors + aIndex];
-}
-
 #endif /* xpt_struct_h */
new file mode 100644
--- /dev/null
+++ b/xpcom/typelib/xpt/xpt_xdr.cpp
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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/. */
+
+/* Implementation of XDR primitives. */
+
+#include "xpt_xdr.h"
+#include "nscore.h"
+#include <string.h>             /* strchr */
+#include "mozilla/Assertions.h"
+#include "mozilla/EndianUtils.h"
+
+static size_t
+CursPoolOffsetRaw(NotNull<XPTCursor*> cursor)
+{
+    if (cursor->pool == XPT_HEADER) {
+        return cursor->offset;
+    }
+    MOZ_ASSERT(cursor->state->data_offset);
+    return cursor->offset + cursor->state->data_offset;
+}
+
+static size_t
+CursPoolOffset(NotNull<XPTCursor*> cursor)
+{
+    return CursPoolOffsetRaw(cursor) - 1;
+}
+
+static char*
+CursPoint(NotNull<XPTCursor*> cursor)
+{
+    return &cursor->state->pool_data[CursPoolOffset(cursor)];
+}
+
+static bool
+CheckCount(NotNull<XPTCursor*> cursor, uint32_t space)
+{
+    // Fail if we're in the data area and about to exceed the allocation.
+    // XXX Also fail if we're in the data area and !state->data_offset
+    if (cursor->pool == XPT_DATA &&
+        (CursPoolOffset(cursor) + space > cursor->state->pool_allocated)) {
+        MOZ_ASSERT(false);
+        fprintf(stderr, "FATAL: no room for %u in cursor\n", space);
+        return false;
+    }
+
+    return true;
+}
+
+void
+XPT_InitXDRState(XPTState* state, char *data, uint32_t len)
+{
+    state->next_cursor[0] = state->next_cursor[1] = 1;
+    state->pool_data = data;
+    state->pool_allocated = len;
+}
+
+/* All offsets are 1-based */
+void
+XPT_SetDataOffset(XPTState *state, uint32_t data_offset)
+{
+   state->data_offset = data_offset;
+}
+
+bool
+XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len,
+               NotNull<XPTCursor*> cursor)
+{
+    cursor->state = state;
+    cursor->pool = pool;
+    cursor->bits = 0;
+    cursor->offset = state->next_cursor[pool];
+
+    if (!(CheckCount(cursor, len)))
+        return false;
+
+    /* this check should be in CHECK_CURSOR */
+    if (pool == XPT_DATA && !state->data_offset) {
+        fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
+        return false;
+    }
+
+    state->next_cursor[pool] += len;
+
+    return true;
+}
+
+bool
+XPT_SeekTo(NotNull<XPTCursor*> cursor, uint32_t offset)
+{
+    /* XXX do some real checking and update len and stuff */
+    cursor->offset = offset;
+    return true;
+}
+
+bool
+XPT_SkipStringInline(NotNull<XPTCursor*> cursor)
+{
+    uint16_t length;
+    if (!XPT_Do16(cursor, &length))
+        return false;
+
+    uint8_t byte;
+    for (uint16_t i = 0; i < length; i++)
+        if (!XPT_Do8(cursor, &byte))
+            return false;
+
+    return true;
+}
+
+bool
+XPT_DoCString(XPTArena *arena, NotNull<XPTCursor*> cursor, const char **identp,
+              bool ignore)
+{
+    uint32_t offset = 0;
+    if (!XPT_Do32(cursor, &offset))
+        return false;
+
+    if (!offset) {
+        *identp = NULL;
+        return true;
+    }
+
+    XPTCursor my_cursor;
+    my_cursor.pool = XPT_DATA;
+    my_cursor.offset = offset;
+    my_cursor.state = cursor->state;
+    char* start = CursPoint(WrapNotNull(&my_cursor));
+
+    char* end = strchr(start, 0); /* find the end of the string */
+    if (!end) {
+        fprintf(stderr, "didn't find end of string on decode!\n");
+        return false;
+    }
+    int len = end - start;
+    MOZ_ASSERT(len > 0);
+
+    if (!ignore) {
+        char *ident = (char*)XPT_CALLOC1(arena, len + 1u);
+        if (!ident)
+            return false;
+
+        memcpy(ident, start, (size_t)len);
+        ident[len] = 0;
+        *identp = ident;
+    }
+
+    return true;
+}
+
+/*
+ * IIDs are written in struct order, in the usual big-endian way.  From the
+ * typelib file spec:
+ *
+ *   "For example, this IID:
+ *     {00112233-4455-6677-8899-aabbccddeeff}
+ *   is converted to the 128-bit value
+ *     0x00112233445566778899aabbccddeeff
+ *   Note that the byte storage order corresponds to the layout of the nsIID
+ *   C-struct on a big-endian architecture."
+ *
+ * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
+ */
+bool
+XPT_DoIID(NotNull<XPTCursor*> cursor, nsID *iidp)
+{
+    int i;
+
+    if (!XPT_Do32(cursor, &iidp->m0) ||
+        !XPT_Do16(cursor, &iidp->m1) ||
+        !XPT_Do16(cursor, &iidp->m2))
+        return false;
+
+    for (i = 0; i < 8; i++)
+        if (!XPT_Do8(cursor, (uint8_t *)&iidp->m3[i]))
+            return false;
+
+    return true;
+}
+
+// MSVC apparently cannot handle functions as template parameters very well,
+// so we need to use a macro approach here.
+
+#define XPT_DOINT(T, func, valuep)                \
+    do {                                          \
+        const size_t sz = sizeof(T);              \
+                                                  \
+        if (!CheckCount(cursor, sz)) {            \
+            return false;                         \
+        }                                         \
+                                                  \
+        *valuep = func(CursPoint(cursor));        \
+        cursor->offset += sz;                     \
+        return true;                              \
+    } while(0)
+
+bool
+XPT_Do64(NotNull<XPTCursor*> cursor, int64_t *u64p)
+{
+    XPT_DOINT(int64_t, mozilla::BigEndian::readInt64, u64p);
+}
+
+/*
+ * When we're handling 32- or 16-bit quantities, we handle a byte at a time to
+ * avoid alignment issues.  Someone could come and optimize this to detect
+ * well-aligned cases and do a single store, if they cared.  I might care
+ * later.
+ */
+bool
+XPT_Do32(NotNull<XPTCursor*> cursor, uint32_t *u32p)
+{
+    XPT_DOINT(uint32_t, mozilla::BigEndian::readUint32, u32p);
+}
+
+bool
+XPT_Do16(NotNull<XPTCursor*> cursor, uint16_t *u16p)
+{
+    XPT_DOINT(uint16_t, mozilla::BigEndian::readUint16, u16p);
+}
+
+#undef XPT_DOINT
+
+bool
+XPT_Do8(NotNull<XPTCursor*> cursor, uint8_t *u8p)
+{
+    if (!CheckCount(cursor, 1))
+        return false;
+
+    *u8p = *CursPoint(cursor);
+
+    cursor->offset++;
+
+    return true;
+}
+
+
new file mode 100644
--- /dev/null
+++ b/xpcom/typelib/xpt/xpt_xdr.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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/. */
+
+/*
+ * Basic APIs for streaming typelib structures from disk.
+ */
+
+#ifndef __xpt_xdr_h__
+#define __xpt_xdr_h__
+
+#include "xpt_struct.h"
+#include "mozilla/NotNull.h"
+
+using mozilla::NotNull;
+
+struct XPTArena;
+struct XPTCursor;
+struct XPTState;
+
+bool
+XPT_SkipStringInline(NotNull<XPTCursor*> cursor);
+
+bool
+XPT_DoCString(XPTArena *arena, NotNull<XPTCursor*> cursor, const char **strp,
+              bool ignore = false);
+
+bool
+XPT_DoIID(NotNull<XPTCursor*> cursor, nsID *iidp);
+
+bool
+XPT_Do64(NotNull<XPTCursor*> cursor, int64_t *u64p);
+
+bool
+XPT_Do32(NotNull<XPTCursor*> cursor, uint32_t *u32p);
+
+bool
+XPT_Do16(NotNull<XPTCursor*> cursor, uint16_t *u16p);
+
+bool
+XPT_Do8(NotNull<XPTCursor*> cursor, uint8_t *u8p);
+
+bool
+XPT_DoHeader(XPTArena *arena, NotNull<XPTCursor*> cursor, XPTHeader **headerp);
+
+enum XPTPool {
+    XPT_HEADER = 0,
+    XPT_DATA = 1
+};
+
+struct XPTState {
+    uint32_t         data_offset;
+    uint32_t         next_cursor[2];
+    char             *pool_data;
+    uint32_t         pool_allocated;
+};
+
+struct XPTCursor {
+    XPTState    *state;
+    XPTPool     pool;
+    uint32_t    offset;
+    uint8_t     bits;
+};
+
+void
+XPT_InitXDRState(XPTState* state, char* data, uint32_t len);
+
+bool
+XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len,
+               NotNull<XPTCursor*> cursor);
+
+bool
+XPT_SeekTo(NotNull<XPTCursor*> cursor, uint32_t offset);
+
+void
+XPT_SetDataOffset(XPTState *state, uint32_t data_offset);
+
+#endif /* __xpt_xdr_h__ */