From eeee2498f73dd4daaf4c79dd421c2c57b0b557cf Mon Sep 17 00:00:00 2001 From: roytam1 Date: Wed, 31 Jan 2024 13:43:16 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1153978 - Part 1: Separate buildIdOp from AsmJSCacheOps. r=jandem,bz (3e2b2c2754) - Bug 1190032 - Sandbox failure in nsPluginHost::GetPluginTempDir. r=areinald (5698ee5709) - Bug 1190032 - Sandbox failure in nsPluginHost::GetPluginTempDir, tighten earlier patch. r=areinald (81fad0767b) - Bug 1201935 - Allow reading from TmpD in OS X content processes. r=smichaud (d67de1d8da) - Bug 1237847 - [e10s] Null deref crash when running test_pluginstream_newstream.html; r=bobowen (c61e5fa268) - Add a helper function for iterating indirect layer trees. (bug 1245765 part 1, r=mattwoodrow) (9fcc19e731) - Propagate D3D9 device resets to remote layers. (bug 1245765 part 2, r=mattwoodrow) (15ab24ebd6) - Don't propagate simulated device resets to child processes. (bug 1245765 part 3, r=mattwoodrow) (fe0986532c) - Fix async drawing when we lose the D3D11 device. (bug 1245765 part 4, r=mattwoodrow) (fcf9e1a009) - Factor compositor initialization out of LayerManagerComposite. (bug 1245765 part 6, r=mattwoodrow) (7af570b6fc) - Bug 1232042: Execute an additional present for D3D11 on the compositor thread when a WM_PAINT event has returned. r=jrmuizel (ac14c78377) - Handle device resets by recreating the compositor, rather than the compositor IPDL stack. (bug 1245765 part 7, r=mattwoodrow) (87292d6e2b) - Ensure that content processes recreate rendering devices. (bug 1245765 part 8, r=mattwoodrow) (8c4e712c6e) - Invalidate layers when starting a transaction on a stale device. (bug 1245765 part 9, r=mattwoodrow) (330efa7199) - Bug 1041599 - Maintain a single volume control session between browser, content, and plugins on Windows. r=aklotz (bdab2a3b35) - align more tests (c6445e1646) - Bug 1241646 - remove unused token arguments from nsIX509CertDB r=keeler (13e50d449c) - Bug 1064402 - Part 1: Remove Import button in Servers tab of the Certificate Manager. r=keeler (181a5a0be2) - Bug 1064402 - Part 2: Remove nsIX509CertDB.importServerCertificate() and nsIX509Cert::SERVER_CERT support in importCertsFromFile(). r=keeler (a4ee6e83f4) - Bug 1130418 - Remove broken e-mail cert trust editing UI. r=emk (d8dca873c1) - Bug 1243182 - Enable eslint "space-infix-ops" rule for PSM. r=keeler (9f5110213f) - Bug 1244245 - Enable eslint "curly" rule for PSM. r=keeler (09b4d913ab) - Bug 1246365 - Enable eslint "comma-spacing" and "semi" rules for PSM. r=keeler (e85d033547) - bug 1246765 - remove unnecessary resource://app/ registration from getHSTSPreloadList.js r=Cykesiopka DONTBUILD NPOTB (e4eb6d1a1e) - Bug 1249595 - Enable 11 more ESLint rules for PSM. r=keeler (7daa42685a) - Bug 1224968 - Support public key input to unbreak periodic HPKP updates. r=keeler (a14415f3c3) - Bug 1229284 - Remove support for SHA-1 hashes in genHPKPStaticPins.js. r=keeler (2e54ef3566) - Bug 1197607, Automated hsts & hpkp updates are failing on mozilla-central, mozilla-aurora, mozilla-esr38, r=cykesiopka (8754cce3ba) - Bug 1224481 - Comment out CA certs removed in NSS 3.21 in PreloadedHPKPins.json to keep periodic Static HPKP updates working. r=dkeeler (6680c85a1b) - bug 1232766 - update the preloaded pinset for Google domains r=rbarnes (83697d274b) - Bug 1250254 - Enable ESLint "no-throw-literal" rule for PSM. r=dkeeler (300ef6f5b8) - Bug 1256088 - Merge mock app-info implementation into AppInfo.jsm. r=gps (e38ae85b3d) - Bug 1153978 - Part 0: Separate nsIPlatformInfo from nsIXULAppInfo. r=jst,gps (2f4eef64c1) - Bug 1153978 - Part 2: Clear pending exception thrown from XDR related APIs when ignoring ReadCachedScript failure. r=bz (09f06d4c74) - Bug 1153978 - Part 3: Use the build id instead of the XDR_BYTECODE_VERSION constant. r=jandem (2e8e01f534) - bug 1241317 - gather telemetry on prevalence of FIPS r=jcj r=vladan (905485c911) - Bug 1220237 - Remove uses of nsIEnumerator from PSM. r=keeler (6b17abd967) - bug 1239455 - rework telemetry for SHA-1 certificates to reflect possible policy states r=Cykesiopka,mgoodwin,rbarnes (95fb0f63ab) - Bug 1247847 - Use smart pointers in nsNSSCertHelper.cpp to manage NSS resources. r=keeler (56140f95c4) - Bug 1248874 - Replace Scoped.h templates used only by PSM in ScopedNSSTypes.h with UniquePtr equivalents. r=dkeeler (1cedc01ab9) - Bug 1016555 - Disable OCSP checking for certificates covered by OneCRL r=keeler (3dc16a87d6) - Bug 1227970 - Perform preference checks to allow OCSP Bypass for OneCRL via Kinto r=keeler (58136eb9e5) - Bug 1219482: Replace PRLogModuleInfo with LazyLogModule in security subdirectory.r=nfroyd (896838cc5d) - Bug 1226928 - remove Wshadow warning in ScopedNSSTypes, r=keeler (52ccbac1bc) - Bug 1226928 - signature verification for content-signing, r=keeler,mayhemer (5f589bf0e0) - Bug 1250256 - Partially clean up nsSDR.cpp. r=keeler (665c582a90) - bug 1241650 - remove nsIX509CertDB.findCertNicknames r=mgoodwin (bf0c26772b) - Bug 1250258 - Partially clean up nsNSSCertificateDB.cpp import methods. r=keeler (693e213484) - Bug 1204202 - Package Universal CRT DLLs for VS2015. r=glandium,ehsan (9b9e1e4057) - bug 496234 - add test vectors from RFC 1320 for md4 implementation r=mayhemer (6526e81ec7) - bug 1228175 - fix IsCertBuiltInRoot r=Cykesiopka,mgoodwin (13bdaf7bb3) - bug 1240118 - add functionality to treat a test certificate as a built-in root r=mgoodwin (bf31c4365b) - Bug 1245649: Turn on valid-typeof, no-invalid-regexp, no-empty-pattern and no-empty-character-class. r=felipe (f637f26dc7) - Bug 1245916: Add additional default globals. r=felipe (229e39bbbe) - Bug 1251011 - Enable ESLint "no-undef" rule for PSM. r=keeler r=mossop (a6e17d09aa) - Bug 1243636. Switch to gfx::CriticalSection (a4d6172870) - Bug 1137561 part.1 Implement WinTextEventDispatcherListener as a singleton class for using TextEventDispatcher at handling native keyboard and IME events r=m_kato (f4582070b0) - Bug 1137572 part.1 TextEventDispatcher should manage its input transaction type r=smaug (ccafc27024) - Bug 1137572 part.2 Add nsIWidget::GetNativeTextEventDispatcherListener() for TextEventDispatcher::NotifyIME() r=smaug, sr=smaug (21571501e8) - Bug 1137572 part.3 Use pseudo IME context when TextEventDispatcher has input transaction which is not for native event handler r=smaug (40be7193b1) - Bug 1137572 part.4 TextEventDispatcher::DispatchInputEvent() should decide if dispatches events with nsIWidget::DispatchInputEvent() with input transaction type r=smaug (ae71f47af2) - Bug 1137572 part.5 Implement TextEventDispatcher::SetPendingComposition() for some platforms whose clause information may overlap each other or the order may not be from start to the end r=smaug (fd046de0fc) - Bug 1137572 part.6 TextEventDispatcher::DispatchKeyboardEventInternal() should copy mNativeKeyEvent when it's in native text input transaction r=smaug (eb17ab1738) - Bug 1137572 part.7 Add TextEventDispatcherListener::WillDispatchKeyboardEvent() for easier to maintain r=smaug (e66759a731) - Bug 1137572 part.8 Callers of methods to dispatch composition events of TextEventDispatcher should be able to specify specific time/timeStamp r=smaug (2cdfd2f3d4) - Bug 1137572 part.9 TextEventDispatcher should not allow WillDispatchKeyboardEvent() modifies unexpected members of WidgetKeyboardEvent r=smaug (94f97ff72d) - Bug 1137561 part.2 Make TSFTextStore use TextEventDispatcher r=m_kato (5b0d92117d) - Bug 1137561 part.3 Make IMMHandler use TextEventDispatcher r=m_kato (2b5ef42de7) - Bug 1137561 part.4 Make NativeKey use TextEventDispatcher r=m_kato (e98eb8b72f) - Bug 1137561 part.5 TextEventDispatcher should decide if keypress events should be fired for specific keys r=m_kato (b5ad4d702c) --- b2g/installer/Makefile.in | 5 +- b2g/installer/package-manifest.in | 4 + browser/installer/Makefile.in | 5 +- browser/installer/package-manifest.in | 5 +- build/win32/Makefile.in | 24 +- chrome/test/unit/test_abi.js | 37 +- chrome/test/unit/test_bug380398.js | 34 +- chrome/test/unit/test_bug397073.js | 32 +- chrome/test/unit/test_bug399707.js | 32 +- chrome/test/unit/test_bug401153.js | 32 +- .../test/unit/test_no_remote_registration.js | 26 +- config/external/nss/nss.def | 2 + configure.in | 7 + dom/asmjscache/AsmJSCache.cpp | 25 +- dom/asmjscache/AsmJSCache.h | 3 - dom/base/TextInputProcessor.cpp | 43 +- dom/base/TextInputProcessor.h | 7 +- dom/base/nsJSEnvironment.cpp | 3 +- dom/ipc/ContentChild.cpp | 52 +- dom/ipc/ContentChild.h | 6 +- dom/ipc/ContentParent.cpp | 14 + dom/ipc/ContentProcess.cpp | 56 +- dom/ipc/PContent.ipdl | 13 +- dom/ipc/TabChild.cpp | 26 + dom/ipc/TabChild.h | 2 + dom/plugins/ipc/PluginModuleParent.cpp | 4 +- .../test/unit/test_nice_plugin_name.js | 58 +- dom/security/ContentVerifier.cpp | 375 +++++++++ dom/security/ContentVerifier.h | 98 +++ dom/security/moz.build | 2 + dom/workers/RuntimeService.cpp | 3 +- gfx/layers/Compositor.h | 8 +- gfx/layers/client/ClientLayerManager.cpp | 17 + gfx/layers/client/ClientLayerManager.h | 4 + gfx/layers/client/TextureClient.cpp | 3 +- .../composite/ContainerLayerComposite.cpp | 7 + .../composite/LayerManagerComposite.cpp | 21 +- gfx/layers/composite/LayerManagerComposite.h | 18 +- gfx/layers/d3d11/CompositorD3D11.h | 2 + gfx/layers/d3d9/CompositorD3D9.cpp | 13 +- gfx/layers/d3d9/CompositorD3D9.h | 2 +- gfx/layers/ipc/CompositableForwarder.h | 3 + gfx/layers/ipc/CompositorChild.cpp | 22 +- gfx/layers/ipc/CompositorChild.h | 6 +- gfx/layers/ipc/CompositorParent.cpp | 186 ++++- gfx/layers/ipc/CompositorParent.h | 36 + gfx/layers/ipc/PCompositor.ipdl | 15 +- gfx/tests/gtest/TestCompositor.cpp | 4 +- gfx/thebes/gfxPlatform.cpp | 7 + gfx/thebes/gfxPlatform.h | 29 +- gfx/thebes/gfxWindowsPlatform.cpp | 30 +- gfx/thebes/gfxWindowsPlatform.h | 5 +- js/src/asmjs/WasmSerialize.h | 4 +- js/src/frontend/SourceNotes.h | 3 - js/src/js.msg | 3 +- js/src/jsapi-tests/testXDR.cpp | 9 + js/src/jsapi.cpp | 6 + js/src/jsapi.h | 4 +- js/src/jscntxt.h | 1 + js/src/jsfriendapi.h | 3 - js/src/shell/js.cpp | 4 +- js/src/vm/Runtime.cpp | 1 + js/src/vm/Runtime.h | 2 + js/src/vm/Xdr.cpp | 44 +- js/src/vm/Xdr.h | 26 - js/src/vm/make_opcode_doc.py | 36 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 3 + js/xpconnect/loader/mozJSSubScriptLoader.cpp | 7 +- js/xpconnect/tests/unit/test_xpcomutils.js | 17 +- layout/base/UnitTransforms.h | 1 + layout/base/nsRefreshDriver.cpp | 2 +- modules/libpref/init/all.js | 7 + security/apps/AppSignatureVerification.cpp | 2 +- security/apps/AppTrustDomain.cpp | 2 +- security/certverifier/CertVerifier.cpp | 305 ++++--- security/certverifier/CertVerifier.h | 37 +- security/certverifier/ExtendedValidation.cpp | 2 +- .../certverifier/NSSCertDBTrustDomain.cpp | 49 +- security/certverifier/NSSCertDBTrustDomain.h | 15 +- security/certverifier/OCSPCache.cpp | 2 +- security/certverifier/OCSPRequestor.cpp | 2 +- .../manager/{.eslintrc => .eslintrc.json} | 72 +- .../en-US/chrome/pippki/certManager.dtd | 6 - .../en-US/chrome/pippki/pippki.properties | 8 +- .../pki/resources/content/OthersOverlay.xul | 6 +- .../pki/resources/content/WebSitesOverlay.xul | 4 - .../pki/resources/content/certManager.js | 169 ++-- .../pki/resources/content/certpicker.js | 20 +- .../pki/resources/content/choosetoken.js | 37 +- .../pki/resources/content/clientauthask.js | 25 +- .../pki/resources/content/createCertInfo.js | 5 +- .../pki/resources/content/deletecert.js | 72 +- .../pki/resources/content/device_manager.js | 78 +- .../pki/resources/content/downloadcert.js | 30 +- .../pki/resources/content/editcerts.js | 89 +- .../pki/resources/content/editemailcert.xul | 38 - .../pki/resources/content/exceptionDialog.js | 22 +- .../manager/pki/resources/content/password.js | 13 +- .../manager/pki/resources/content/pippki.js | 28 +- .../pki/resources/content/protectedAuth.js | 8 +- .../pki/resources/content/resetpassword.js | 4 +- .../pki/resources/content/viewCertDetails.js | 151 ++-- security/manager/pki/resources/jar.mn | 1 - security/manager/ssl/CertBlocklist.cpp | 32 +- security/manager/ssl/CertBlocklist.h | 1 + security/manager/ssl/PSMContentListener.cpp | 2 +- .../manager/ssl/PublicKeyPinningService.cpp | 3 +- .../ssl/RootCertificateTelemetryUtils.cpp | 3 +- .../manager/ssl/SSLServerCertVerification.cpp | 28 +- security/manager/ssl/ScopedNSSTypes.h | 175 ++-- security/manager/ssl/moz.build | 1 + security/manager/ssl/nsCertPicker.cpp | 3 +- security/manager/ssl/nsCertTree.cpp | 2 +- security/manager/ssl/nsCrypto.cpp | 4 +- .../manager/ssl/nsDataSignatureVerifier.cpp | 6 +- security/manager/ssl/nsIPK11TokenDB.idl | 6 +- security/manager/ssl/nsIPKCS11Module.idl | 7 +- security/manager/ssl/nsIPKCS11ModuleDB.idl | 5 +- security/manager/ssl/nsIX509Cert.idl | 5 + security/manager/ssl/nsIX509CertDB.idl | 63 +- security/manager/ssl/nsNSSCallbacks.cpp | 2 +- security/manager/ssl/nsNSSCertHelper.cpp | 360 ++++---- security/manager/ssl/nsNSSCertTrust.cpp | 14 - security/manager/ssl/nsNSSCertTrust.h | 2 - security/manager/ssl/nsNSSCertificate.cpp | 60 +- security/manager/ssl/nsNSSCertificateDB.cpp | 789 +++++++----------- security/manager/ssl/nsNSSCertificateDB.h | 31 +- .../ssl/nsNSSCertificateFakeTransport.cpp | 7 + security/manager/ssl/nsNSSComponent.cpp | 50 +- security/manager/ssl/nsNSSComponent.h | 12 + security/manager/ssl/nsNSSIOLayer.cpp | 12 +- security/manager/ssl/nsNSSShutDown.cpp | 2 +- security/manager/ssl/nsNTLMAuthModule.cpp | 14 +- security/manager/ssl/nsPK11TokenDB.cpp | 58 +- security/manager/ssl/nsPKCS11Slot.cpp | 97 +-- security/manager/ssl/nsPKCS11Slot.h | 33 +- security/manager/ssl/nsPKCS12Blob.cpp | 3 +- security/manager/ssl/nsSDR.cpp | 181 ++-- .../manager/ssl/nsSecureBrowserUIImpl.cpp | 5 +- .../manager/ssl/nsSecurityHeaderParser.cpp | 12 +- .../manager/ssl/nsSiteSecurityService.cpp | 20 +- security/manager/ssl/nsUsageArrayHelper.cpp | 6 +- .../manager/ssl/tests/compiled/TestCertDB.cpp | 5 +- .../tests/compiled/TestIsCertBuiltInRoot.cpp | 263 ++++++ .../manager/ssl/tests/compiled/TestMD4.cpp | 70 ++ security/manager/ssl/tests/compiled/moz.build | 10 + .../tests/mochitest/browser/.eslintrc.json | 3 + .../browser/browser_bug627234_perwindowpb.js | 4 +- .../mochitest/mixedcontent/.eslintrc.json | 3 + .../mochitest/mixedcontent/backward.html | 4 +- .../tests/mochitest/mixedcontent/bug329869.js | 1 + .../mixedcontent/bug383369step3.html | 1 + .../mixedcontent/mixedContentTest.js | 129 ++- .../mixedcontent/test_bug329869.html | 1 + .../mixedcontent/test_bug383369.html | 1 + .../mixedcontent/test_bug455367.html | 1 + .../mixedcontent/test_bug472986.html | 5 +- .../mixedcontent/test_bug477118.html | 1 + .../mixedcontent/test_bug521461.html | 3 +- .../mixedcontent/test_cssBefore1.html | 1 + .../mixedcontent/test_cssContent1.html | 1 + .../mixedcontent/test_cssContent2.html | 1 + .../mixedcontent/test_documentWrite1.html | 1 + .../mixedcontent/test_documentWrite2.html | 1 + .../test_dynDelayedUnsecurePicture.html | 1 + .../test_dynDelayedUnsecureXHR.html | 11 +- .../test_dynUnsecureBackground.html | 1 + .../test_dynUnsecureIframeRedirect.html | 1 + .../mixedcontent/test_dynUnsecurePicture.html | 1 + .../test_dynUnsecurePicturePreload.html | 1 + .../test_dynUnsecureRedirect.html | 1 + .../test_innerHtmlDelayedUnsecurePicture.html | 1 + .../test_innerHtmlUnsecurePicture.html | 1 + .../mixedcontent/test_javascriptPicture.html | 1 + .../mixedcontent/test_secureAll.html | 3 +- .../mixedcontent/test_securePicture.html | 1 + .../mixedcontent/test_unsecureBackground.html | 1 + .../mixedcontent/test_unsecureCSS.html | 5 +- .../mixedcontent/test_unsecureIframe.html | 1 + .../mixedcontent/test_unsecureIframe2.html | 1 + .../test_unsecureIframeMetaRedirect.html | 1 + .../test_unsecureIframeRedirect.html | 1 + .../mixedcontent/test_unsecurePicture.html | 1 + .../mixedcontent/test_unsecurePictureDup.html | 3 +- .../test_unsecurePictureInIframe.html | 1 + .../mixedcontent/test_unsecureRedirect.html | 1 + .../mixedcontent/unsecurePictureDup.html | 3 +- .../stricttransportsecurity/.eslintrc.json | 7 + .../nosts_bootstrap.html | 7 +- .../plain_bootstrap.html | 7 +- .../subdom_bootstrap.html | 7 +- .../test_stricttransportsecurity.html | 5 +- .../test_sts_privatebrowsing_perwindowpb.html | 15 +- .../manager/ssl/tests/unit/.eslintrc.json | 3 + security/manager/ssl/tests/unit/head_psm.js | 103 +-- security/manager/ssl/tests/unit/moz.build | 8 +- .../tests/unit/sss_readstate_child_worker.js | 2 + .../tests/unit/test_add_preexisting_cert.js | 2 +- .../ssl/tests/unit/test_certDB_import.js | 118 +++ .../tests/unit/test_certDB_import/emailEE.pem | 17 + .../test_certDB_import/emailEE.pem.certspec | 2 + .../unit/test_certDB_import/importedCA.pem | 17 + .../importedCA.pem.certspec | 3 + .../tests/unit/test_certDB_import/moz.build | 14 + .../ssl/tests/unit/test_cert_blocklist.js | 73 +- .../manager/ssl/tests/unit/test_cert_dbKey.js | 10 +- .../ssl/tests/unit/test_cert_isBuiltInRoot.js | 71 ++ .../ssl/tests/unit/test_cert_keyUsage.js | 2 +- .../ssl/tests/unit/test_cert_overrides.js | 59 +- .../manager/ssl/tests/unit/test_cert_sha1.js | 44 +- .../manager/ssl/tests/unit/test_cert_trust.js | 6 +- .../unit/test_constructX509FromBase64.js | 6 +- .../manager/ssl/tests/unit/test_ev_certs.js | 56 +- .../manager/ssl/tests/unit/test_getchain.js | 4 +- .../ssl/tests/unit/test_hash_algorithms.js | 31 +- .../moz.build | 2 +- .../ssl/tests/unit/test_name_constraints.js | 2 +- .../ssl/tests/unit/test_ocsp_caching.js | 2 +- .../ssl/tests/unit/test_ocsp_stapling.js | 22 + .../tests/unit/test_ocsp_stapling_expired.js | 13 + .../manager/ssl/tests/unit/test_pinning.js | 42 + .../ssl/tests/unit/test_pinning_dynamic.js | 2 +- .../tests/unit/test_pinning_header_parsing.js | 12 +- .../tests/unit/test_pkcs11_insert_remove.js | 22 + .../ssl/tests/unit/test_pkcs11_list.js | 94 +++ .../ssl/tests/unit/test_pkcs11_safe_mode.js | 4 +- security/manager/ssl/tests/unit/test_sdr.js | 80 ++ .../ssl/tests/unit/test_signed_apps.js | 27 +- .../manager/ssl/tests/unit/test_signed_dir.js | 16 +- .../ssl/tests/unit/test_sss_eviction.js | 77 +- .../ssl/tests/unit/test_sss_readstate.js | 79 +- .../tests/unit/test_sss_readstate_empty.js | 42 +- .../tests/unit/test_sss_readstate_garbage.js | 53 +- .../ssl/tests/unit/test_sss_readstate_huge.js | 57 +- .../ssl/tests/unit/test_sss_savestate.js | 110 ++- .../ssl/tests/unit/test_sts_ipv4_ipv6.js | 2 +- .../unit/test_sts_preloadlist_perwindowpb.js | 3 +- .../unit/test_toolkit_securityreporter.js | 3 +- .../ssl/tests/unit/tlsserver/cmd/moz.build | 1 - .../ssl/tests/unit/xpcshell-smartcards.ini | 3 + security/manager/ssl/tests/unit/xpcshell.ini | 196 +++-- security/manager/tools/.eslintrc.json | 7 + security/manager/tools/PreloadedHPKPins.json | 45 +- security/manager/tools/dumpGoogleRoots.js | 90 ++ security/manager/tools/genHPKPStaticPins.js | 174 ++-- security/manager/tools/genRootCAHashes.js | 24 +- security/manager/tools/getHSTSPreloadList.js | 76 +- security/manager/tools/makeCNNICHashes.js | 6 +- security/sandbox/mac/Sandbox.h | 1 + security/sandbox/mac/Sandbox.mm | 26 +- services/common/kinto-updater.js | 80 ++ services/common/moz.build | 1 + services/common/tests/unit/head_global.js | 28 +- .../common/tests/unit/test_kinto_updater.js | 110 +++ services/common/tests/unit/xpcshell.ini | 1 + services/crypto/tests/unit/head_helpers.js | 26 +- services/mobileid/tests/xpcshell/head.js | 50 +- services/sync/tests/unit/head_appinfo.js | 27 +- testing/cppunittest.ini | 3 + testing/modules/AppInfo.jsm | 109 ++- testing/profiles/prefs_general.js | 2 + testing/xpcshell/xpcshell.eslintrc | 11 + toolkit/.eslintrc | 18 +- .../search/tests/xpcshell/head_search.js | 34 +- .../search/tests/xpcshell/test_json_cache.js | 1 + .../components/social/test/xpcshell/head.js | 51 +- .../startup/tests/unit/head_startup.js | 41 +- toolkit/components/telemetry/Histograms.json | 12 +- .../components/telemetry/docs/common-ping.rst | 1 + .../tests/unit/test_TelemetrySession.js | 2 +- .../tests/unit/test_TelemetryTimestamps.js | 14 +- .../tests/unit/head_urlformatter.js | 35 +- .../tests/unit/test_urlformatter.js | 4 +- .../devtools/security/LocalCertService.cpp | 2 +- .../modules/tests/xpcshell/test_Services.js | 26 +- toolkit/xre/nsAppRunner.cpp | 94 ++- widget/BasicEvents.h | 57 +- widget/EventForwards.h | 2 + widget/TextEventDispatcher.cpp | 270 ++++-- widget/TextEventDispatcher.h | 187 ++++- widget/TextEventDispatcherListener.h | 42 + widget/cocoa/nsChildView.mm | 4 + widget/cocoa/nsCocoaWindow.mm | 4 + widget/gonk/nsWindow.cpp | 7 +- widget/gtk/nsWindow.cpp | 13 +- widget/nsBaseWidget.cpp | 107 ++- widget/nsBaseWidget.h | 13 + widget/nsIWidget.h | 11 + widget/qt/nsWindow.cpp | 7 +- widget/uikit/nsWindow.mm | 4 + widget/windows/AudioSession.cpp | 50 +- widget/windows/IMMHandler.cpp | 226 +++-- widget/windows/IMMHandler.h | 5 +- widget/windows/KeyboardLayout.cpp | 160 ++-- widget/windows/KeyboardLayout.h | 17 +- widget/windows/TSFTextStore.cpp | 152 ++-- widget/windows/TSFTextStore.h | 3 + widget/windows/WinIMEHandler.cpp | 9 + widget/windows/WinIMEHandler.h | 5 + .../WinTextEventDispatcherListener.cpp | 75 ++ .../windows/WinTextEventDispatcherListener.h | 50 ++ widget/windows/moz.build | 1 + widget/windows/nsAppShell.cpp | 13 +- widget/windows/nsWindow.cpp | 68 +- widget/windows/nsWindow.h | 13 +- widget/windows/nsWindowBase.h | 8 + widget/windows/nsWindowGfx.cpp | 21 +- xpcom/base/CycleCollectedJSRuntime.cpp | 25 + xpcom/base/CycleCollectedJSRuntime.h | 3 + xpcom/base/ErrorList.h | 4 + xpcom/system/moz.build | 1 + xpcom/system/nsIPlatformInfo.idl | 19 + xpcom/system/nsIXULAppInfo.idl | 16 +- 313 files changed, 6504 insertions(+), 3692 deletions(-) create mode 100644 dom/security/ContentVerifier.cpp create mode 100644 dom/security/ContentVerifier.h rename security/manager/{.eslintrc => .eslintrc.json} (62%) delete mode 100644 security/manager/pki/resources/content/editemailcert.xul create mode 100644 security/manager/ssl/tests/compiled/TestIsCertBuiltInRoot.cpp create mode 100644 security/manager/ssl/tests/compiled/TestMD4.cpp create mode 100644 security/manager/ssl/tests/mochitest/browser/.eslintrc.json create mode 100644 security/manager/ssl/tests/mochitest/mixedcontent/.eslintrc.json create mode 100644 security/manager/ssl/tests/mochitest/stricttransportsecurity/.eslintrc.json create mode 100644 security/manager/ssl/tests/unit/.eslintrc.json create mode 100644 security/manager/ssl/tests/unit/test_certDB_import.js create mode 100644 security/manager/ssl/tests/unit/test_certDB_import/emailEE.pem create mode 100644 security/manager/ssl/tests/unit/test_certDB_import/emailEE.pem.certspec create mode 100644 security/manager/ssl/tests/unit/test_certDB_import/importedCA.pem create mode 100644 security/manager/ssl/tests/unit/test_certDB_import/importedCA.pem.certspec create mode 100644 security/manager/ssl/tests/unit/test_certDB_import/moz.build create mode 100644 security/manager/ssl/tests/unit/test_cert_isBuiltInRoot.js create mode 100644 security/manager/ssl/tests/unit/test_pkcs11_list.js create mode 100644 security/manager/ssl/tests/unit/test_sdr.js create mode 100644 security/manager/tools/.eslintrc.json create mode 100644 security/manager/tools/dumpGoogleRoots.js create mode 100644 services/common/kinto-updater.js create mode 100644 services/common/tests/unit/test_kinto_updater.js create mode 100644 widget/windows/WinTextEventDispatcherListener.cpp create mode 100644 widget/windows/WinTextEventDispatcherListener.h create mode 100644 xpcom/system/nsIPlatformInfo.idl diff --git a/b2g/installer/Makefile.in b/b2g/installer/Makefile.in index 0def2c8e2c..d0a99f6acb 100644 --- a/b2g/installer/Makefile.in +++ b/b2g/installer/Makefile.in @@ -20,12 +20,15 @@ DEFINES += -DJAREXT= DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME) # Set MSVC dlls version to package, if any. -ifdef WIN32_REDIST_DIR ifdef MOZ_NO_DEBUG_RTL +ifdef WIN32_REDIST_DIR DEFINES += -DMOZ_PACKAGE_MSVC_DLLS=1 DEFINES += -DMSVC_C_RUNTIME_DLL=$(MSVC_C_RUNTIME_DLL) DEFINES += -DMSVC_CXX_RUNTIME_DLL=$(MSVC_CXX_RUNTIME_DLL) endif +ifdef WIN_UCRT_REDIST_DIR +DEFINES += -DMOZ_PACKAGE_WIN_UCRT_DLLS=1 +endif endif ifdef MOZ_DEBUG diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index ed1eed0c38..41e774abe7 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -88,6 +88,10 @@ @BINPATH@/@MSVC_C_RUNTIME_DLL@ @BINPATH@/@MSVC_CXX_RUNTIME_DLL@ #endif +#if MOZ_PACKAGE_WIN_UCRT_DLLS +@BINPATH@/api-ms-win-*.dll +@BINPATH@/ucrtbase.dll +#endif #endif #ifndef MOZ_NATIVE_ICU #ifdef MOZ_SHARED_ICU diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in index b1c739dac8..77a06ec23b 100644 --- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -60,13 +60,16 @@ endif DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME) # Set MSVC dlls version to package, if any. -ifdef WIN32_REDIST_DIR ifdef MOZ_NO_DEBUG_RTL +ifdef WIN32_REDIST_DIR DEFINES += -DMOZ_PACKAGE_MSVC_DLLS=1 DEFINES += -DMSVC_C_RUNTIME_DLL=$(MSVC_C_RUNTIME_DLL) DEFINES += -DMSVC_CXX_RUNTIME_DLL=$(MSVC_CXX_RUNTIME_DLL) DEFINES += -DMSVC_OPENMP_DLL=$(MSVC_OPENMP_DLL) endif +ifdef WIN_UCRT_REDIST_DIR +DEFINES += -DMOZ_PACKAGE_WIN_UCRT_DLLS=1 +endif endif ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET))) diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index b5f4028e30..8ac4adb255 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -101,7 +101,10 @@ #ifdef MOZ_PACKAGE_MSVC_DLLS @BINPATH@/@MSVC_C_RUNTIME_DLL@ @BINPATH@/@MSVC_CXX_RUNTIME_DLL@ -@BINPATH@/@MSVC_OPENMP_DLL@ +#endif +#if MOZ_PACKAGE_WIN_UCRT_DLLS +@BINPATH@/api-ms-win-*.dll +@BINPATH@/ucrtbase.dll #endif #endif #ifndef MOZ_NATIVE_ICU diff --git a/build/win32/Makefile.in b/build/win32/Makefile.in index 5f151fc9ab..75949f2ff0 100644 --- a/build/win32/Makefile.in +++ b/build/win32/Makefile.in @@ -4,22 +4,26 @@ include $(topsrcdir)/config/rules.mk +REDIST_FILES = + ifdef WIN32_REDIST_DIR +REDIST_FILES += '$(WIN32_REDIST_DIR)'/$(MSVC_C_RUNTIME_DLL) +REDIST_FILES += '$(WIN32_REDIST_DIR)'/$(MSVC_CXX_RUNTIME_DLL) +endif -REDIST_FILES = \ - $(MSVC_REDIST_CRT_DIR)/$(MSVC_C_RUNTIME_DLL) \ - $(MSVC_REDIST_CRT_DIR)/$(MSVC_CXX_RUNTIME_DLL) \ - $(MSVC_REDIST_OPENMP_DIR)/$(MSVC_OPENMP_DLL) \ - $(NULL) +ifdef WIN_UCRT_REDIST_DIR +REDIST_FILES += $(wildcard $(WIN_UCRT_REDIST_DIR)/api-ms-win-*.dll) +REDIST_FILES += '$(WIN_UCRT_REDIST_DIR)'/ucrtbase.dll +endif +ifdef REDIST_FILES libs-preqs = \ - $(call mkdir_deps,$(FINAL_TARGET)) \ - $(NULL) + $(call mkdir_deps,$(FINAL_TARGET)) \ + $(NULL) libs:: $(libs-preqs) - install --preserve-timestamps $(foreach f,$(REDIST_FILES),'$(WIN32_REDIST_DIR)'/$(f)) $(FINAL_TARGET) - -endif # WIN32_REDIST_DIR + install --preserve-timestamps $(REDIST_FILES) $(FINAL_TARGET) +endif # run the binscope tool to make sure the binary and all libraries # are using all available Windows OS-level security mechanisms diff --git a/chrome/test/unit/test_abi.js b/chrome/test/unit/test_abi.js index 69ff31ea39..076fd3215f 100644 --- a/chrome/test/unit/test_abi.js +++ b/chrome/test/unit/test_abi.js @@ -1,41 +1,10 @@ -const XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +updateAppInfo({ name: "XPCShell", ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) - || iid.equals(Ci.nsIXULRuntime) - || iid.equals(Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - -const XULAppInfoFactory = { - // These two are used when we register all our factories (and unregister) - CID: XULAPPINFO_CID, - scheme: "XULAppInfo", - contractID: XULAPPINFO_CONTRACTID, - createInstance: function (outer, iid) { - if (outer != null) - throw Cr.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; - -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +}); registerManifests([do_get_file("data/test_abi.manifest")]); diff --git a/chrome/test/unit/test_bug380398.js b/chrome/test/unit/test_bug380398.js index 1791da10a0..ce0b6233ec 100644 --- a/chrome/test/unit/test_bug380398.js +++ b/chrome/test/unit/test_bug380398.js @@ -10,39 +10,13 @@ var MANIFESTS = [ registerManifests(MANIFESTS); -var XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +updateAppInfo({ name: "XPCShell", - ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", + id: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) - || iid.equals(Ci.nsIXULRuntime) - || iid.equals(Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +}); var gIOS = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); diff --git a/chrome/test/unit/test_bug397073.js b/chrome/test/unit/test_bug397073.js index 6c153fe4f2..fb9c6c0953 100644 --- a/chrome/test/unit/test_bug397073.js +++ b/chrome/test/unit/test_bug397073.js @@ -10,39 +10,13 @@ var MANIFESTS = [ registerManifests(MANIFESTS); -var XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +updateAppInfo({ name: "XPCShell", ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) - || iid.equals(Ci.nsIXULRuntime) - || iid.equals(Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +}); var gIOS = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); diff --git a/chrome/test/unit/test_bug399707.js b/chrome/test/unit/test_bug399707.js index 1a61741db6..05273550c3 100644 --- a/chrome/test/unit/test_bug399707.js +++ b/chrome/test/unit/test_bug399707.js @@ -9,39 +9,13 @@ var MANIFESTS = [ registerManifests(MANIFESTS); -var XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +updateAppInfo({ name: "XPCShell", ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) - || iid.equals(Ci.nsIXULRuntime) - || iid.equals(Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +}); var gIOS = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); diff --git a/chrome/test/unit/test_bug401153.js b/chrome/test/unit/test_bug401153.js index 50870aabeb..3317d8b1e3 100644 --- a/chrome/test/unit/test_bug401153.js +++ b/chrome/test/unit/test_bug401153.js @@ -9,39 +9,13 @@ var MANIFESTS = [ registerManifests(MANIFESTS); -var XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +updateAppInfo({ name: "XPCShell", ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) - || iid.equals(Ci.nsIXULRuntime) - || iid.equals(Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +}); var gIOS = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); diff --git a/chrome/test/unit/test_no_remote_registration.js b/chrome/test/unit/test_no_remote_registration.js index c3abf2685c..ac4f5745d7 100644 --- a/chrome/test/unit/test_no_remote_registration.js +++ b/chrome/test/unit/test_no_remote_registration.js @@ -4,36 +4,26 @@ * 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/. */ -let manifests = [ +var manifests = [ do_get_file("data/test_no_remote_registration.manifest"), ]; registerManifests(manifests); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -let XULAppInfo = { - vendor: "Mozilla", +Components.utils.import("resource://testing-common/AppInfo.jsm", this); +var XULAppInfo = newAppInfo({ name: "XPCShell", ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}", version: "5", - appBuildID: "2007010101", platformVersion: "1.9", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIXULAppInfo, - Ci.nsIXULRuntime, - ]) -}; +}); -let XULAppInfoFactory = { +var XULAppInfoFactory = { // These two are used when we register all our factories (and unregister) - CID: XULAPPINFO_CID, + CID: Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"), scheme: "XULAppInfo", - contractID: XULAPPINFO_CONTRACTID, + contractID: "@mozilla.org/xre/app-info;1", createInstance: function (outer, iid) { if (outer != null) throw Cr.NS_ERROR_NO_AGGREGATION; @@ -69,7 +59,7 @@ ProtocolHandler.prototype = ]) }; -let testProtocols = [ +var testProtocols = [ // It doesn't matter if it has this flag - the only flag we accept is // URI_IS_LOCAL_RESOURCE. {scheme: "moz-protocol-ui-resource", diff --git a/config/external/nss/nss.def b/config/external/nss/nss.def index 825be113ff..523beb96fb 100644 --- a/config/external/nss/nss.def +++ b/config/external/nss/nss.def @@ -326,6 +326,7 @@ PK11_ExportDERPrivateKeyInfo PK11_ExportEncryptedPrivKeyInfo PK11_ExtractKeyValue PK11_FindCertFromNickname +PK11_FindCertInSlot PK11_FindCertsFromEmailAddress PK11_FindCertsFromNickname PK11_FindKeyByAnyCert @@ -547,6 +548,7 @@ SECMOD_DeleteInternalModule SECMOD_DeleteModule SECMOD_DestroyModule SECMOD_FindModule +SECMOD_FindSlot SECMOD_GetDeadModuleList SECMOD_GetDefaultModuleList SECMOD_GetDefaultModuleListLock diff --git a/configure.in b/configure.in index 03d78b5e46..ffd65649f0 100644 --- a/configure.in +++ b/configure.in @@ -557,6 +557,13 @@ case "$target" in # C4091: 'typedef ': ignored on left of '' when no variable is declared CFLAGS="$CFLAGS -wd4091" CXXFLAGS="$CXXFLAGS -wd4091" + + if test -n "$WIN_UCRT_REDIST_DIR"; then + if test ! -d "$WIN_UCRT_REDIST_DIR"; then + AC_MSG_ERROR([Invalid Windows UCRT Redist directory: ${WIN_UCRT_REDIST_DIR}]) + fi + WIN_UCRT_REDIST_DIR=`cd "$WIN_UCRT_REDIST_DIR" && pwd` + fi else AC_MSG_ERROR([This version (${_CC_MAJOR_VERSION}.${_CC_MINOR_VERSION}.${_CC_BUILD_VERSION}) of the MSVC compiler is unsupported. You must install Visual C++ 2013 Update 3 or newer in order to build. diff --git a/dom/asmjscache/AsmJSCache.cpp b/dom/asmjscache/AsmJSCache.cpp index 70bcc116a4..372f4dcc78 100644 --- a/dom/asmjscache/AsmJSCache.cpp +++ b/dom/asmjscache/AsmJSCache.cpp @@ -12,6 +12,7 @@ #include "jsfriendapi.h" #include "mozilla/Assertions.h" #include "mozilla/CondVar.h" +#include "mozilla/CycleCollectedJSRuntime.h" #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h" #include "mozilla/dom/asmjscache/PAsmJSCacheEntryParent.h" #include "mozilla/dom/ContentChild.h" @@ -34,7 +35,6 @@ #include "nsIRunnable.h" #include "nsISimpleEnumerator.h" #include "nsIThread.h" -#include "nsIXULAppInfo.h" #include "nsJSPrincipals.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" @@ -1706,29 +1706,6 @@ CloseEntryForWrite(size_t aSize, } } -bool -GetBuildId(JS::BuildIdCharVector* aBuildID) -{ - nsCOMPtr info = do_GetService("@mozilla.org/xre/app-info;1"); - if (!info) { - return false; - } - - nsCString buildID; - nsresult rv = info->GetPlatformBuildID(buildID); - NS_ENSURE_SUCCESS(rv, false); - - if (!aBuildID->resize(buildID.Length())) { - return false; - } - - for (size_t i = 0; i < buildID.Length(); i++) { - (*aBuildID)[i] = buildID[i]; - } - - return true; -} - class Client : public quota::Client { ~Client() {} diff --git a/dom/asmjscache/AsmJSCache.h b/dom/asmjscache/AsmJSCache.h index 2a3bec80c9..adca4e45b6 100644 --- a/dom/asmjscache/AsmJSCache.h +++ b/dom/asmjscache/AsmJSCache.h @@ -132,9 +132,6 @@ CloseEntryForWrite(size_t aSize, uint8_t* aMemory, intptr_t aHandle); -bool -GetBuildId(JS::BuildIdCharVector* aBuildId); - // Called from QuotaManager.cpp: quota::Client* diff --git a/dom/base/TextInputProcessor.cpp b/dom/base/TextInputProcessor.cpp index 44f00ccde1..6970add527 100644 --- a/dom/base/TextInputProcessor.cpp +++ b/dom/base/TextInputProcessor.cpp @@ -197,7 +197,8 @@ TextInputProcessor::BeginInputTransactionInternal( } if (aForTests) { - rv = dispatcher->BeginInputTransactionForTests(this); + bool isAPZAware = gfxPrefs::TestEventsAsyncEnabled(); + rv = dispatcher->BeginTestInputTransaction(this, isAPZAware); } else { rv = dispatcher->BeginInputTransaction(this); } @@ -631,8 +632,11 @@ TextInputProcessor::NotifyIME(TextEventDispatcher* aTextEventDispatcher, const IMENotification& aNotification) { // If This is called while this is being initialized, ignore the call. + // In such case, this method should return NS_ERROR_NOT_IMPLEMENTED because + // we can say, TextInputProcessor doesn't implement any handlers of the + // requests and notifications. if (!mDispatcher) { - return NS_ERROR_NOT_AVAILABLE; + return NS_ERROR_NOT_IMPLEMENTED; } MOZ_ASSERT(aTextEventDispatcher == mDispatcher, "Wrong TextEventDispatcher notifies this"); @@ -701,6 +705,16 @@ TextInputProcessor::OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) UnlinkFromTextEventDispatcher(); } +NS_IMETHODIMP_(void) +TextInputProcessor::WillDispatchKeyboardEvent( + TextEventDispatcher* aTextEventDispatcher, + WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aIndexOfKeypress, + void* aData) +{ + // TextInputProcessor doesn't set alternative char code. +} + nsresult TextInputProcessor::PrepareKeyboardEventToDispatch( WidgetKeyboardEvent& aKeyboardEvent, @@ -776,23 +790,6 @@ TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent, return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags); } -TextEventDispatcher::DispatchTo -TextInputProcessor::GetDispatchTo() const -{ - // Support asynchronous tests. - if (mForTests) { - return gfxPrefs::TestEventsAsyncEnabled() ? - TextEventDispatcher::eDispatchToParentProcess : - TextEventDispatcher::eDispatchToCurrentProcess; - } - - // Otherwise, TextInputProcessor supports only keyboard apps on B2G. - // Keyboard apps on B2G doesn't want to dispatch keyboard events to - // chrome process. Therefore, this should dispatch key events only in - // the current process. - return TextEventDispatcher::eDispatchToCurrentProcess; -} - nsresult TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent, uint32_t aKeyFlags, @@ -838,8 +835,7 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent, nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault : nsEventStatus_eIgnore; - if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status, - GetDispatchTo())) { + if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status)) { // If keydown event isn't dispatched, we don't need to dispatch keypress // events. return NS_OK; @@ -850,8 +846,7 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent, KEYEVENT_NOT_CONSUMED; if (aAllowToDispatchKeypress && - mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status, - GetDispatchTo())) { + mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status)) { aConsumedFlags |= (status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED : KEYEVENT_NOT_CONSUMED; @@ -920,7 +915,7 @@ TextInputProcessor::KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent, nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore : nsEventStatus_eConsumeNoDefault; - mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status, GetDispatchTo()); + mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status); aDoDefault = (status != nsEventStatus_eConsumeNoDefault); return NS_OK; } diff --git a/dom/base/TextInputProcessor.h b/dom/base/TextInputProcessor.h index c6bc157906..bbd33efbe5 100644 --- a/dom/base/TextInputProcessor.h +++ b/dom/base/TextInputProcessor.h @@ -36,6 +36,12 @@ public: NS_IMETHOD_(void) OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override; + NS_IMETHOD_(void) WillDispatchKeyboardEvent( + TextEventDispatcher* aTextEventDispatcher, + WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aIndexOfKeypress, + void* aData) override; + protected: virtual ~TextInputProcessor(); @@ -61,7 +67,6 @@ private: nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent, uint32_t aKeyFlags, bool& aDoDefault); - TextEventDispatcher::DispatchTo GetDispatchTo() const; nsresult IsValidStateForComposition(); void UnlinkFromTextEventDispatcher(); nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent, diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 2c833f7dbc..abbe378a63 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2603,8 +2603,7 @@ nsJSContext::EnsureStatics() AsmJSCacheOpenEntryForRead, asmjscache::CloseEntryForRead, AsmJSCacheOpenEntryForWrite, - asmjscache::CloseEntryForWrite, - asmjscache::GetBuildId + asmjscache::CloseEntryForWrite }; JS::SetAsmJSCacheOps(sRuntime, &asmJSCacheOps); diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 9c908c2c93..6dd9c8cffe 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -99,6 +99,7 @@ #include "nsISpellChecker.h" #include "nsClipboardProxy.h" #include "nsISystemMessageCache.h" +#include "nsDirectoryService.h" #include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceDefs.h" #include "nsContentPermissionHelper.h" @@ -143,6 +144,7 @@ #ifdef XP_WIN #include #define getpid _getpid +#include "mozilla/widget/AudioSession.h" #endif #ifdef MOZ_X11 @@ -1397,12 +1399,29 @@ StartMacOSContentSandbox() MOZ_CRASH("Error resolving child process path"); } + // During sandboxed content process startup, before reaching + // this point, NS_OS_TEMP_DIR is modified to refer to a sandbox- + // writable temporary directory + nsCOMPtr tempDir; + nsresult rv = nsDirectoryService::gService->Get(NS_OS_TEMP_DIR, + NS_GET_IID(nsIFile), getter_AddRefs(tempDir)); + if (NS_FAILED(rv)) { + MOZ_CRASH("Failed to get NS_OS_TEMP_DIR"); + } + + nsAutoCString tempDirPath; + rv = tempDir->GetNativePath(tempDirPath); + if (NS_FAILED(rv)) { + MOZ_CRASH("Failed to get NS_OS_TEMP_DIR path"); + } + MacSandboxInfo info; info.type = MacSandboxType_Content; info.level = Preferences::GetInt("security.sandbox.content.level"); info.appPath.assign(appPath.get()); info.appBinaryPath.assign(appBinaryPath.get()); info.appDir.assign(appDir.get()); + info.appTempDir.assign(tempDirPath.get()); std::string err; if (!mozilla::StartMacSandbox(info, err)) { @@ -3009,6 +3028,10 @@ ContentChild::RecvShutdown() "content-child-shutdown", nullptr); } +#if defined(XP_WIN) + mozilla::widget::StopAudioSession(); +#endif + GetIPCChannel()->SetAbortOnError(false); #ifdef MOZ_ENABLE_PROFILER_SPS @@ -3088,6 +3111,26 @@ ContentChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) return true; } +bool +ContentChild::RecvSetAudioSessionData(const nsID& aId, + const nsString& aDisplayName, + const nsString& aIconPath) +{ +#if defined(XP_WIN) + if (NS_FAILED(mozilla::widget::RecvAudioSessionData(aId, aDisplayName, + aIconPath))) { + return true; + } + + // Ignore failures here; we can't really do anything about them + mozilla::widget::StartAudioSession(); + return true; +#else + NS_RUNTIMEABORT("Not Reached!"); + return false; +#endif +} + // This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp // can't include ContentChild.h since it includes windows.h. @@ -3181,15 +3224,6 @@ ContentChild::RecvEndDragSession(const bool& aDoneDrag, return true; } -bool -ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) -{ -#if defined(XP_WIN) - gfxPlatform::GetPlatform()->TestDeviceReset(DeviceResetReason(aResetReason)); -#endif - return true; -} - bool ContentChild::RecvPush(const nsCString& aScope, const IPC::Principal& aPrincipal) diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 2c0f0d9698..b947a9c8e0 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -601,7 +601,11 @@ public: virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override; - virtual bool RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) override; + // Windows specific - set up audio session + virtual bool + RecvSetAudioSessionData(const nsID& aId, + const nsString& aDisplayName, + const nsString& aIconPath) override; private: virtual void ActorDestroy(ActorDestroyReason why) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index da98e43031..31fe6621fe 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -261,6 +261,10 @@ using namespace mozilla::system; #include "mozilla/dom/GamepadMonitoring.h" #endif +#ifdef XP_WIN +#include "mozilla/widget/AudioSession.h" +#endif + #include "VRManagerParent.h" // for VRManagerParent static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); @@ -2612,6 +2616,16 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority, KillHard("SandboxInitFailed"); } #endif +#if defined(XP_WIN) + // Send the info needed to join the browser process's audio session. + nsID id; + nsString sessionName; + nsString iconPath; + if (NS_SUCCEEDED(mozilla::widget::GetAudioSessionData(id, sessionName, + iconPath))) { + Unused << SendSetAudioSessionData(id, sessionName, iconPath); + } +#endif } bool diff --git a/dom/ipc/ContentProcess.cpp b/dom/ipc/ContentProcess.cpp index e3f3ba8bf8..ae4bb3f06a 100644 --- a/dom/ipc/ContentProcess.cpp +++ b/dom/ipc/ContentProcess.cpp @@ -9,8 +9,11 @@ #include "ContentProcess.h" #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) -#include "mozilla/Preferences.h" #include "mozilla/WindowsVersion.h" +#endif + +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) +#include "mozilla/Preferences.h" #include "nsDirectoryService.h" #include "nsDirectoryServiceDefs.h" #endif @@ -21,29 +24,60 @@ namespace mozilla { namespace dom { #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) +static bool +IsSandboxTempDirRequired() +{ + // On Windows, a sandbox-writable temp directory is only used + // for Vista or later with sandbox pref level >= 1. + return (IsVistaOrLater() && + (Preferences::GetInt("security.sandbox.content.level") >= 1)); +} + +static const char* +SandboxTempDirParent() +{ + // On Windows, the sandbox-writable temp directory resides in the + // low integrity sandbox base directory. + return NS_WIN_LOW_INTEGRITY_TEMP_BASE; +} +#endif + +#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) +static bool +IsSandboxTempDirRequired() +{ + // On OSX, use the sandbox-writable temp when the pref level >= 1. + return (Preferences::GetInt("security.sandbox.content.level") >= 1); +} + +static const char* +SandboxTempDirParent() +{ + return NS_OS_TEMP_DIR; +} +#endif + +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) static void SetUpSandboxEnvironment() { MOZ_ASSERT(nsDirectoryService::gService, "SetUpSandboxEnvironment relies on nsDirectoryService being initialized"); - // A low integrity temp only currently makes sense for Vista or Later and - // sandbox pref level >= 1. - if (!IsVistaOrLater() || - Preferences::GetInt("security.sandbox.content.level") < 1) { + if (!IsSandboxTempDirRequired()) { return; } nsAdoptingString tempDirSuffix = Preferences::GetString("security.sandbox.content.tempDirSuffix"); if (tempDirSuffix.IsEmpty()) { - NS_WARNING("Low integrity temp suffix pref not set."); + NS_WARNING("Sandbox-writable temp directory suffix pref not set."); return; } - // Get the base low integrity Mozilla temp directory. + // Get the parent of our sandbox writable temp directory. nsCOMPtr lowIntegrityTemp; - nsresult rv = nsDirectoryService::gService->Get(NS_WIN_LOW_INTEGRITY_TEMP_BASE, + nsresult rv = nsDirectoryService::gService->Get(SandboxTempDirParent(), NS_GET_IID(nsIFile), getter_AddRefs(lowIntegrityTemp)); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -56,7 +90,7 @@ SetUpSandboxEnvironment() return; } - // Change the gecko defined temp directory to our low integrity one. + // Change the gecko defined temp directory to our sandbox-writable one. // Undefine returns a failure if the property is not already set. Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR); rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp); @@ -82,10 +116,10 @@ ContentProcess::Init() mContent.InitXPCOM(); mContent.InitGraphicsDeviceData(); -#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) +#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) SetUpSandboxEnvironment(); #endif - + return true; } diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 9f314e02a1..09bf45efb0 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -703,12 +703,6 @@ child: */ async GamepadUpdate(GamepadChangeEvent aGamepadEvent); - /** - * Tell the child that for testing purposes, a graphics device reset has - * occurred. - */ - async TestGraphicsDeviceReset(uint32_t aReason); - /** * Notify the child that presentation receiver has been launched with the * correspondent iframe. @@ -741,6 +735,13 @@ child: */ async PushSubscriptionChange(nsCString scope, Principal principal); + /** + * Windows specific: associate this content process with the browsers + * audio session. + */ + async SetAudioSessionData(nsID aID, + nsString aDisplayName, + nsString aIconPath); parent: /** * Tell the content process some attributes of itself. This is diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 6779408ea2..d6d9c82a3b 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -109,6 +109,7 @@ #include "nsIScriptError.h" #include "mozilla/EventForwards.h" #include "nsDeviceContext.h" +#include "FrameLayerBuilder.h" #define BROWSER_ELEMENT_CHILD_SCRIPT \ NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") @@ -2831,6 +2832,31 @@ TabChild::ClearCachedResources() manager->ClearCachedResources(); } +void +TabChild::InvalidateLayers() +{ + MOZ_ASSERT(mPuppetWidget); + MOZ_ASSERT(mPuppetWidget->GetLayerManager()); + MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == + LayersBackend::LAYERS_CLIENT); + + RefPtr lm = mPuppetWidget->GetLayerManager(); + FrameLayerBuilder::InvalidateAllLayers(lm); +} + +void +TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier) +{ + gfxPlatform::GetPlatform()->UpdateRenderModeIfDeviceReset(); + + RefPtr lm = mPuppetWidget->GetLayerManager(); + ClientLayerManager* clm = lm->AsClientLayerManager(); + + mTextureFactoryIdentifier = aNewIdentifier; + clm->UpdateTextureFactoryIdentifier(aNewIdentifier); + FrameLayerBuilder::InvalidateAllLayers(clm); +} + NS_IMETHODIMP TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index ab46b9b30b..5900406c08 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -512,6 +512,8 @@ public: const TimeStamp& aCompositeReqEnd); void ClearCachedResources(); + void InvalidateLayers(); + void CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier); static inline TabChild* GetFrom(nsIDOMWindow* aWindow) { diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index 405234f270..504931b87a 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -2356,8 +2356,8 @@ PluginModuleChromeParent::RecvNP_InitializeResult(const NPError& aError) SetPluginFuncs(mNPPIface); } - // Send the info needed to join the chrome process's audio session to the - // plugin process + // Send the info needed to join the browser process's audio session to the + // plugin process. nsID id; nsString sessionName; nsString iconPath; diff --git a/dom/plugins/test/unit/test_nice_plugin_name.js b/dom/plugins/test/unit/test_nice_plugin_name.js index bdc63b0db8..45454726f4 100644 --- a/dom/plugins/test/unit/test_nice_plugin_name.js +++ b/dom/plugins/test/unit/test_nice_plugin_name.js @@ -9,57 +9,19 @@ const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); -let gAppInfo = null; +var gAppInfo = null; -function createAppInfo(id, name, version, platformVersion) { - gAppInfo = { - // nsIXULAppInfo - vendor: "Mozilla", - name: name, - ID: id, - version: version, - appBuildID: "2007010101", - platformVersion: platformVersion ? platformVersion : "1.0", - platformBuildID: "2007010101", - - // nsIXULRuntime - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - invalidateCachesOnRestart: function invalidateCachesOnRestart() { - // Do nothing - }, - - // nsICrashReporter - annotations: {}, - - annotateCrashReport: function(key, data) { - this.annotations[key] = data; - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, - Ci.nsIXULRuntime, - Ci.nsICrashReporter, - Ci.nsISupports]) - }; - - let XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Components.results.NS_ERROR_NO_AGGREGATION; - return gAppInfo.QueryInterface(iid); - } - }; - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", - XULAPPINFO_CONTRACTID, XULAppInfoFactory); +function createAppInfo(ID, name, version, platformVersion="1.0") { + let tmp = {}; + Cu.import("resource://testing-common/AppInfo.jsm", tmp); + tmp.updateAppInfo({ + ID, name, version, platformVersion, + crashReporter: true + }); + gAppInfo = tmp.getAppInfo(); } -let gDirSvc = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - -let gPluginHost = null; +var gPluginHost = null; function test_expected_permission_string(aPermString) { gPluginHost.reloadPlugins(false); diff --git a/dom/security/ContentVerifier.cpp b/dom/security/ContentVerifier.cpp new file mode 100644 index 0000000000..9a83f91430 --- /dev/null +++ b/dom/security/ContentVerifier.cpp @@ -0,0 +1,375 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "ContentVerifier.h" + +#include "mozilla/fallible.h" +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" +#include "mozilla/StaticPtr.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsIInputStream.h" +#include "nsIRequest.h" +#include "nssb64.h" +#include "nsSecurityHeaderParser.h" +#include "nsServiceManagerUtils.h" +#include "nsStringStream.h" +#include "nsThreadUtils.h" + +using namespace mozilla; + +static LazyLogModule gContentVerifierPRLog("ContentVerifier"); +#define CSV_LOG(args) MOZ_LOG(gContentVerifierPRLog, LogLevel::Debug, args) + +// Content-Signature prefix +const nsLiteralCString kPREFIX = NS_LITERAL_CSTRING("Content-Signature:\x00"); + +NS_IMPL_ISUPPORTS(ContentVerifier, nsIStreamListener, nsISupports); + +nsresult +ContentVerifier::Init(const nsAString& aContentSignatureHeader) +{ + mVks = Preferences::GetString("browser.newtabpage.remote.keys"); + + if (aContentSignatureHeader.IsEmpty() || mVks.IsEmpty()) { + CSV_LOG( + ("Content-Signature header and verification keys must not be empty!\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + + nsresult rv = ParseContentSignatureHeader(aContentSignatureHeader); + NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_SIGNATURE); + return CreateContext(); +} + +/** + * Implement nsIStreamListener + * We buffer the entire content here and kick off verification + */ +NS_METHOD +AppendNextSegment(nsIInputStream* aInputStream, void* aClosure, + const char* aRawSegment, uint32_t aToOffset, uint32_t aCount, + uint32_t* outWrittenCount) +{ + FallibleTArray* decodedData = + static_cast*>(aClosure); + nsAutoCString segment(aRawSegment, aCount); + if (!decodedData->AppendElement(segment, fallible)) { + return NS_ERROR_OUT_OF_MEMORY; + } + *outWrittenCount = aCount; + return NS_OK; +} + +NS_IMETHODIMP +ContentVerifier::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) +{ + return NS_OK; +} + +NS_IMETHODIMP +ContentVerifier::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, + nsresult aStatus) +{ + // Verify the content: + // If this fails, we return an invalid signature error to load a fallback page. + // If everthing is good, we return a new stream to the next listener and kick + // that one of. + CSV_LOG(("VerifySignedContent, b64signature: %s\n", mSignature.get())); + CSV_LOG(("VerifySignedContent, key: \n[\n%s\n]\n", mKey.get())); + bool verified = false; + nsresult rv = End(&verified); + if (NS_FAILED(rv) || !verified || NS_FAILED(aStatus)) { + // cancel the request and return error + if (NS_FAILED(aStatus)) { + rv = aStatus; + } else { + rv = NS_ERROR_INVALID_SIGNATURE; + } + CSV_LOG(("failed to verify content\n")); + mNextListener->OnStartRequest(aRequest, aContext); + mNextListener->OnStopRequest(aRequest, aContext, rv); + return NS_ERROR_INVALID_SIGNATURE; + } + CSV_LOG(("Successfully verified content signature.\n")); + + // start the next listener + rv = mNextListener->OnStartRequest(aRequest, aContext); + if (NS_SUCCEEDED(rv)) { + // We emptied aInStr so we have to create a new one from buf to hand it + // to the consuming listener. + for (uint32_t i = 0; i < mContent.Length(); ++i) { + nsCOMPtr oInStr; + rv = NS_NewCStringInputStream(getter_AddRefs(oInStr), mContent[i]); + if (NS_FAILED(rv)) { + break; + } + // let the next listener know that there is data in oInStr + rv = mNextListener->OnDataAvailable(aRequest, aContext, oInStr, 0, + mContent[i].Length()); + if (NS_FAILED(rv)) { + break; + } + } + } + + // propagate OnStopRequest and return + return mNextListener->OnStopRequest(aRequest, aContext, rv); +} + +NS_IMETHODIMP +ContentVerifier::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, + nsIInputStream* aInputStream, uint64_t aOffset, + uint32_t aCount) +{ + // buffer the entire stream + uint32_t read; + nsresult rv = aInputStream->ReadSegments(AppendNextSegment, &mContent, aCount, + &read); + if (NS_FAILED(rv)) { + return rv; + } + + // update the signature verifier + return Update(mContent[mContent.Length()-1]); +} + +/** + * ContentVerifier logic and utils + */ + +nsresult +ContentVerifier::GetVerificationKey(const nsAString& aKeyId) +{ + // get verification keys from the pref and see if we have |aKeyId| + nsCharSeparatedTokenizer tokenizerVK(mVks, ';'); + while (tokenizerVK.hasMoreTokens()) { + nsDependentSubstring token = tokenizerVK.nextToken(); + nsCharSeparatedTokenizer tokenizerKey(token, '='); + nsString prefKeyId; + if (tokenizerKey.hasMoreTokens()) { + prefKeyId = tokenizerKey.nextToken(); + } + nsString key; + if (tokenizerKey.hasMoreTokens()) { + key = tokenizerKey.nextToken(); + } + if (prefKeyId.Equals(aKeyId)) { + mKey.Assign(NS_ConvertUTF16toUTF8(key)); + return NS_OK; + } + } + + // we didn't find the appropriate key + return NS_ERROR_INVALID_SIGNATURE; +} + +nsresult +ContentVerifier::ParseContentSignatureHeader( + const nsAString& aContentSignatureHeader) +{ + // We only support p384 ecdsa according to spec + NS_NAMED_LITERAL_CSTRING(keyid_var, "keyid"); + NS_NAMED_LITERAL_CSTRING(signature_var, "p384ecdsa"); + + nsAutoString contentSignature; + nsAutoString keyId; + nsAutoCString header = NS_ConvertUTF16toUTF8(aContentSignatureHeader); + nsSecurityHeaderParser parser(header.get()); + nsresult rv = parser.Parse(); + if (NS_FAILED(rv)) { + CSV_LOG(("ContentVerifier: could not parse ContentSignature header\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + LinkedList* directives = parser.GetDirectives(); + + for (nsSecurityHeaderDirective* directive = directives->getFirst(); + directive != nullptr; directive = directive->getNext()) { + CSV_LOG(("ContentVerifier: found directive %s\n", directive->mName.get())); + if (directive->mName.Length() == keyid_var.Length() && + directive->mName.EqualsIgnoreCase(keyid_var.get(), + keyid_var.Length())) { + if (!keyId.IsEmpty()) { + CSV_LOG(("ContentVerifier: found two keyIds\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + + CSV_LOG(("ContentVerifier: found a keyid directive\n")); + keyId = NS_ConvertUTF8toUTF16(directive->mValue); + rv = GetVerificationKey(keyId); + NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_SIGNATURE); + } + if (directive->mName.Length() == signature_var.Length() && + directive->mName.EqualsIgnoreCase(signature_var.get(), + signature_var.Length())) { + if (!contentSignature.IsEmpty()) { + CSV_LOG(("ContentVerifier: found two ContentSignatures\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + + CSV_LOG(("ContentVerifier: found a ContentSignature directive\n")); + contentSignature = NS_ConvertUTF8toUTF16(directive->mValue); + mSignature = directive->mValue; + } + } + + // we have to ensure that we found a key and a signature at this point + if (mKey.IsEmpty()) { + CSV_LOG(("ContentVerifier: got a Content-Signature header but didn't find " + "an appropriate key.\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + if (mSignature.IsEmpty()) { + CSV_LOG(("ContentVerifier: got a Content-Signature header but didn't find " + "a signature.\n")); + return NS_ERROR_INVALID_SIGNATURE; + } + + return NS_OK; +} + +/** + * Parse signature, public key, and algorithm data for input to verification + * functions in VerifyData and CreateContext. + * + * https://datatracker.ietf.org/doc/draft-thomson-http-content-signature/ + * If aSignature is a content signature, the function returns + * NS_ERROR_INVALID_SIGNATURE if anything goes wrong. Only p384 with sha384 + * is supported and aSignature is a raw signature (r||s). + */ +nsresult +ContentVerifier::ParseInput(ScopedSECKEYPublicKey& aPublicKeyOut, + ScopedSECItem& aSignatureItemOut, + SECOidTag& aOidOut, + const nsNSSShutDownPreventionLock&) +{ + // Base 64 decode the key + ScopedSECItem keyItem(::SECITEM_AllocItem(nullptr, nullptr, 0)); + if (!keyItem || + !NSSBase64_DecodeBuffer(nullptr, keyItem, + mKey.get(), + mKey.Length())) { + return NS_ERROR_INVALID_SIGNATURE; + } + + // Extract the public key from the keyItem + ScopedCERTSubjectPublicKeyInfo pki( + SECKEY_DecodeDERSubjectPublicKeyInfo(keyItem)); + if (!pki) { + return NS_ERROR_INVALID_SIGNATURE; + } + aPublicKeyOut = SECKEY_ExtractPublicKey(pki.get()); + + // in case we were not able to extract a key + if (!aPublicKeyOut) { + return NS_ERROR_INVALID_SIGNATURE; + } + + // Base 64 decode the signature + ScopedSECItem rawSignatureItem(::SECITEM_AllocItem(nullptr, nullptr, 0)); + if (!rawSignatureItem || + !NSSBase64_DecodeBuffer(nullptr, rawSignatureItem, + mSignature.get(), + mSignature.Length())) { + return NS_ERROR_INVALID_SIGNATURE; + } + + // get signature object and oid + if (!aSignatureItemOut) { + return NS_ERROR_INVALID_SIGNATURE; + } + // We have a raw ecdsa signature r||s so we have to DER-encode it first + // Note that we have to check rawSignatureItem->len % 2 here as + // DSAU_EncodeDerSigWithLen asserts this + if (rawSignatureItem->len == 0 || rawSignatureItem->len % 2 != 0) { + return NS_ERROR_INVALID_SIGNATURE; + } + if (DSAU_EncodeDerSigWithLen(aSignatureItemOut, rawSignatureItem, + rawSignatureItem->len) != SECSuccess) { + return NS_ERROR_INVALID_SIGNATURE; + } + aOidOut = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; + + return NS_OK; +} + +/** + * Create a context for a signature verification. + * It sets signature, public key, and algorithms that should be used to verify + * the data. It also updates the verification buffer with the content-signature + * prefix. + */ +nsresult +ContentVerifier::CreateContext() +{ + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_INVALID_SIGNATURE; + } + + // Bug 769521: We have to change b64 url to regular encoding as long as we + // don't have a b64 url decoder. This should change soon, but in the meantime + // we have to live with this. + mSignature.ReplaceChar('-', '+'); + mSignature.ReplaceChar('_', '/'); + + ScopedSECKEYPublicKey publicKey; + ScopedSECItem signatureItem(::SECITEM_AllocItem(nullptr, nullptr, 0)); + SECOidTag oid; + nsresult rv = ParseInput(publicKey, signatureItem, oid, locker); + if (NS_FAILED(rv)) { + return NS_ERROR_INVALID_SIGNATURE; + } + + mCx = UniqueVFYContext(VFY_CreateContext(publicKey, signatureItem, oid, NULL)); + if (!mCx) { + return NS_ERROR_INVALID_SIGNATURE; + } + + if (VFY_Begin(mCx.get()) != SECSuccess) { + return NS_ERROR_INVALID_SIGNATURE; + } + + // add the prefix to the verification buffer + return Update(kPREFIX); +} + +/** + * Add data to the context that should be verified. + */ +nsresult +ContentVerifier::Update(const nsACString& aData) +{ + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_INVALID_SIGNATURE; + } + + if (!aData.IsEmpty()) { + if (VFY_Update(mCx.get(), + (const unsigned char*)nsPromiseFlatCString(aData).get(), + aData.Length()) != SECSuccess) { + return NS_ERROR_INVALID_SIGNATURE; + } + } + + return NS_OK; +} + +/** + * Finish signature verification and return the result in _retval. + */ +nsresult +ContentVerifier::End(bool* _retval) +{ + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_INVALID_SIGNATURE; + } + + *_retval = (VFY_End(mCx.get()) == SECSuccess); + + return NS_OK; +} \ No newline at end of file diff --git a/dom/security/ContentVerifier.h b/dom/security/ContentVerifier.h new file mode 100644 index 0000000000..ae29418e26 --- /dev/null +++ b/dom/security/ContentVerifier.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef mozilla_dom_ContentVerifier_h +#define mozilla_dom_ContentVerifier_h + +#include "nsCOMPtr.h" +#include "nsIObserver.h" +#include "nsIStreamListener.h" +#include "nsNSSShutDown.h" +#include "nsString.h" +#include "nsTArray.h" +#include "ScopedNSSTypes.h" + +/** + * Mediator intercepting OnStartRequest in nsHttpChannel, blocks until all + * data is read from the input stream, verifies the content signature and + * releases the request to the next listener if the verification is successful. + * If the verification fails or anything else goes wrong, a + * NS_ERROR_INVALID_SIGNATURE is thrown. + */ +class ContentVerifier : public nsIStreamListener + , public nsNSSShutDownObject +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIREQUESTOBSERVER + + explicit ContentVerifier(nsIStreamListener* aMediatedListener, + nsISupports* aMediatedContext) + : mNextListener(aMediatedListener) + , mContext(aMediatedContext) + , mCx(nullptr) {} + + nsresult Init(const nsAString& aContentSignatureHeader); + + // nsNSSShutDownObject + virtual void virtualDestroyNSSReference() override + { + destructorSafeDestroyNSSReference(); + } + +protected: + virtual ~ContentVerifier() + { + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return; + } + destructorSafeDestroyNSSReference(); + shutdown(calledFromObject); + } + + void destructorSafeDestroyNSSReference() + { + mCx = nullptr; + } + +private: + nsresult ParseContentSignatureHeader(const nsAString& aContentSignatureHeader); + nsresult GetVerificationKey(const nsAString& aKeyId); + + // utility function to parse input before put into verification functions + nsresult ParseInput(mozilla::ScopedSECKEYPublicKey& aPublicKeyOut, + mozilla::ScopedSECItem& aSignatureItemOut, + SECOidTag& aOidOut, + const nsNSSShutDownPreventionLock&); + + // create a verifier context and store it in mCx + nsresult CreateContext(); + + // Adds data to the context that was used to generate the signature. + nsresult Update(const nsACString& aData); + + // Finalises the signature and returns the result of the signature + // verification. + nsresult End(bool* _retval); + + // content and next listener for nsIStreamListener + nsCOMPtr mNextListener; + nsCOMPtr mContext; + + // verifier context for incrementel verifications + mozilla::UniqueVFYContext mCx; + // buffered content to verify + FallibleTArray mContent; + // signature to verify + nsCString mSignature; + // verification key + nsCString mKey; + // verification key preference + nsString mVks; +}; + +#endif /* mozilla_dom_ContentVerifier_h */ diff --git a/dom/security/moz.build b/dom/security/moz.build index 4c3ee164e7..80e554815b 100644 --- a/dom/security/moz.build +++ b/dom/security/moz.build @@ -7,6 +7,7 @@ TEST_DIRS += ['test'] EXPORTS.mozilla.dom += [ + 'ContentVerifier.h', 'nsContentSecurityManager.h', 'nsCSPContext.h', 'nsCSPService.h', @@ -21,6 +22,7 @@ EXPORTS += [ ] UNIFIED_SOURCES += [ + 'ContentVerifier.cpp', 'nsContentSecurityManager.cpp', 'nsCSPContext.cpp', 'nsCSPParser.cpp', diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 75077abcd3..3397036edc 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -794,8 +794,7 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime) AsmJSCacheOpenEntryForRead, asmjscache::CloseEntryForRead, AsmJSCacheOpenEntryForWrite, - asmjscache::CloseEntryForWrite, - asmjscache::GetBuildId + asmjscache::CloseEntryForWrite }; JS::SetAsmJSCacheOps(aRuntime, &asmJSCacheOps); diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 1ec0fe763b..1e2b0b0965 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -124,7 +124,7 @@ class Layer; class TextureSource; class DataTextureSource; class CompositingRenderTarget; -class PCompositorParent; +class CompositorParent; class LayerManagerComposite; enum SurfaceInitMode @@ -183,7 +183,7 @@ protected: public: NS_INLINE_DECL_REFCOUNTING(Compositor) - explicit Compositor(PCompositorParent* aParent = nullptr) + explicit Compositor(CompositorParent* aParent = nullptr) : mCompositorID(0) , mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC) , mParent(aParent) @@ -450,6 +450,8 @@ public: */ virtual bool Ready() { return true; } + virtual void ForcePresent() { } + // XXX I expect we will want to move mWidget into this class and implement // these methods properly. virtual nsIWidget* GetWidget() const { return nullptr; } @@ -542,7 +544,7 @@ protected: uint32_t mCompositorID; DiagnosticTypes mDiagnosticTypes; - PCompositorParent* mParent; + CompositorParent* mParent; /** * We keep track of the total number of pixels filled as we composite the diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index aa5e1a0f53..f5c022a302 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -102,6 +102,7 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget) , mNeedsComposite(false) , mPaintSequenceNumber(0) , mForwarder(new ShadowLayerForwarder) + , mDeviceCounter(gfxPlatform::GetPlatform()->GetDeviceCounter()) { MOZ_COUNT_CTOR(ClientLayerManager); mMemoryPressureObserver = new MemoryPressureObserver(this); @@ -189,6 +190,10 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) NS_ASSERTION(!InTransaction(), "Nested transactions not allowed"); mPhase = PHASE_CONSTRUCTION; + if (DependsOnStaleDevice()) { + FrameLayerBuilder::InvalidateAllLayers(this); + } + MOZ_ASSERT(mKeepAlive.IsEmpty(), "uncommitted txn?"); // If the last transaction was incomplete (a failed DoEmptyTransaction), @@ -550,6 +555,12 @@ ClientLayerManager::FlushRendering() } } +void +ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) +{ + mForwarder->UpdateTextureFactoryIdentifier(aNewIdentifier); +} + void ClientLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) { @@ -829,6 +840,12 @@ ClientLayerManager::RemoveDidCompositeObserver(DidCompositeObserver* aObserver) mDidCompositeObservers.RemoveElement(aObserver); } +bool +ClientLayerManager::DependsOnStaleDevice() const +{ + return gfxPlatform::GetPlatform()->GetDeviceCounter() != mDeviceCounter; +} + ClientLayer::~ClientLayer() { if (HasShadow()) { diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index 94295c0856..a3616afd46 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -97,6 +97,7 @@ public: virtual already_AddRefed CreateColorLayer() override; virtual already_AddRefed CreateRefLayer() override; + void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier); TextureFactoryIdentifier GetTextureFactoryIdentifier() { return mForwarder->GetTextureFactoryIdentifier(); @@ -307,6 +308,8 @@ private: void* aCallbackData, EndTransactionFlags); + bool DependsOnStaleDevice() const; + LayerRefArray mKeepAlive; nsIWidget* mWidget; @@ -357,6 +360,7 @@ private: nsTArray mDidCompositeObservers; RefPtr mMemoryPressureObserver; + uint64_t mDeviceCounter; }; class ClientLayer : public ShadowableLayer diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index a2eeb3a80b..6521b2a08d 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -710,7 +710,8 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator, if (parentBackend == LayersBackend::LAYERS_D3D11 && (moz2DBackend == gfx::BackendType::DIRECT2D || moz2DBackend == gfx::BackendType::DIRECT2D1_1 || - !!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT)) && + (!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) && + gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice())) && aSize.width <= maxTextureSize && aSize.height <= maxTextureSize) { diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 07dab08825..7397eacd21 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -210,6 +210,9 @@ ContainerRenderVR(ContainerT* aContainer, if (!layer->IsVisible() && !layer->AsContainerLayer()) { continue; } + if (layerToRender->HasStaleCompositor()) { + continue; + } // We flip between pre-rendered and Gecko-rendered VR based on // whether the child layer of this VR container layer has @@ -554,6 +557,10 @@ RenderLayers(ContainerT* aContainer, const RenderTargetIntRect& clipRect = preparedData.mClipRect; Layer* layer = layerToRender->GetLayer(); + if (layerToRender->HasStaleCompositor()) { + continue; + } + Color color; if (NeedToDrawCheckerboardingForLayer(layer, &color)) { if (gfxPrefs::APZHighlightCheckerboardedAreas()) { diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 2420db26d6..2e7abcfd95 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -133,13 +133,6 @@ LayerManagerComposite::~LayerManagerComposite() } -bool -LayerManagerComposite::Initialize() -{ - bool result = mCompositor->Initialize(); - return result; -} - void LayerManagerComposite::Destroy() { @@ -1499,6 +1492,14 @@ LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect() mCompositable->RemoveMaskEffect(); } +void +LayerManagerComposite::ChangeCompositor(Compositor* aNewCompositor) +{ + mCompositor = aNewCompositor; + mTextRenderer = new TextRenderer(aNewCompositor); + mTwoPassTmpTarget = nullptr; +} + LayerComposite::LayerComposite(LayerManagerComposite *aManager) : mCompositeManager(aManager) , mCompositor(aManager->GetCompositor()) @@ -1576,6 +1577,12 @@ LayerComposite::GetFullyRenderedRegion() { } } +bool +LayerComposite::HasStaleCompositor() const +{ + return mCompositeManager->GetCompositor() != mCompositor; +} + #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS /*static*/ bool diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index c74b7ec278..3fb8bf0660 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -76,11 +76,6 @@ public: virtual void Destroy() override; - /** - * return True if initialization was succesful, false when it was not. - */ - bool Initialize(); - /** * Sets the clipping region for this layer manager. This is important on * windows because using OGL we no longer have GDI's native clipping. Therefor @@ -230,6 +225,12 @@ public: return mCompositor; } + // Called by CompositorParent when a new compositor has been created due + // to a device reset. The layer manager must clear any cached resources + // attached to the old compositor, and make a best effort at ignoring + // layer or texture updates against the old compositor. + void ChangeCompositor(Compositor* aNewCompositor); + /** * LayerManagerComposite provides sophisticated debug overlays * that can request a next frame. @@ -285,6 +286,8 @@ public: // overlay. void SetWindowOverlayChanged() { mWindowOverlayChanged = true; } + void ForcePresent() { mCompositor->ForcePresent(); } + private: /** Region we're clipping our current drawing to. */ nsIntRegion mClippingRegion; @@ -335,6 +338,8 @@ private: bool aInvertEffect, float aContrastEffect); + void ChangeCompositorInternal(Compositor* aNewCompositor); + float mWarningLevel; mozilla::TimeStamp mWarnTime; bool mUnusedApzTransformWarning; @@ -485,6 +490,9 @@ public: bool HasLayerBeenComposited() { return mLayerComposited; } gfx::IntRect GetClearRect() { return mClearRect; } + // Returns false if the layer is attached to an older compositor. + bool HasStaleCompositor() const; + /** * Return the part of the visible region that has been fully rendered. * While progressive drawing is in progress this region will be diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index 1621e03918..a285844293 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -143,6 +143,8 @@ public: return LayersBackend::LAYERS_D3D11; } + virtual void ForcePresent() { mSwapChain->Present(0, 0); } + virtual nsIWidget* GetWidget() const override { return mWidget; } ID3D11Device* GetDevice() { return mDevice; } diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp index fd8d3c03be..2093980059 100644 --- a/gfx/layers/d3d9/CompositorD3D9.cpp +++ b/gfx/layers/d3d9/CompositorD3D9.cpp @@ -17,13 +17,14 @@ #include "mozilla/layers/LayerManagerComposite.h" #include "gfxPrefs.h" #include "gfxCrashReporterUtils.h" +#include "mozilla/layers/CompositorParent.h" namespace mozilla { namespace layers { using namespace mozilla::gfx; -CompositorD3D9::CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget) +CompositorD3D9::CompositorD3D9(CompositorParent* aParent, nsIWidget *aWidget) : Compositor(aParent) , mWidget(aWidget) , mDeviceResetCount(0) @@ -581,7 +582,7 @@ CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture) } /** - * In the next few methods we call |mParent->SendInvalidateAll()| - that has + * In the next few methods we call |mParent->InvalidateRemoteLayers()| - that has * a few uses - if our device or swap chain is not ready, it causes us to try * to render again, that means we keep trying to get a good device and swap * chain and don't block the main thread (which we would if we kept trying in @@ -614,7 +615,7 @@ CompositorD3D9::EnsureSwapChain() if (state == DeviceMustRecreate) { mDeviceManager = nullptr; } - mParent->SendInvalidateAll(); + mParent->InvalidateRemoteLayers(); return false; } } @@ -630,7 +631,7 @@ CompositorD3D9::EnsureSwapChain() mDeviceManager = nullptr; mSwapChain = nullptr; } - mParent->SendInvalidateAll(); + mParent->InvalidateRemoteLayers(); return false; } @@ -638,7 +639,7 @@ void CompositorD3D9::CheckResetCount() { if (mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) { - mParent->SendInvalidateAll(); + mParent->InvalidateRemoteLayers(); } mDeviceResetCount = mDeviceManager->GetDeviceResetCount(); } @@ -663,7 +664,7 @@ CompositorD3D9::Ready() mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); if (!mDeviceManager) { FailedToResetDevice(); - mParent->SendInvalidateAll(); + mParent->InvalidateRemoteLayers(); return false; } if (EnsureSwapChain()) { diff --git a/gfx/layers/d3d9/CompositorD3D9.h b/gfx/layers/d3d9/CompositorD3D9.h index 5ea6f1b6fd..e46787df07 100644 --- a/gfx/layers/d3d9/CompositorD3D9.h +++ b/gfx/layers/d3d9/CompositorD3D9.h @@ -21,7 +21,7 @@ namespace layers { class CompositorD3D9 : public Compositor { public: - CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget); + CompositorD3D9(CompositorParent* aParent, nsIWidget *aWidget); ~CompositorD3D9(); virtual bool Initialize() override; diff --git a/gfx/layers/ipc/CompositableForwarder.h b/gfx/layers/ipc/CompositableForwarder.h index f4fef20987..97dd70db18 100644 --- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -136,6 +136,9 @@ public: void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier); + void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) { + mTextureFactoryIdentifier = aNewIdentifier; + } virtual int32_t GetMaxTextureSize() const override { return mTextureFactoryIdentifier.mMaxTextureSize; diff --git a/gfx/layers/ipc/CompositorChild.cpp b/gfx/layers/ipc/CompositorChild.cpp index d899119939..030f277408 100644 --- a/gfx/layers/ipc/CompositorChild.cpp +++ b/gfx/layers/ipc/CompositorChild.cpp @@ -197,10 +197,30 @@ CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor) } bool -CompositorChild::RecvInvalidateAll() +CompositorChild::RecvInvalidateLayers(const uint64_t& aLayersId) { if (mLayerManager) { + MOZ_ASSERT(aLayersId == 0); FrameLayerBuilder::InvalidateAllLayers(mLayerManager); + } else if (aLayersId != 0) { + if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) { + child->InvalidateLayers(); + } + } + return true; +} + +bool +CompositorChild::RecvCompositorUpdated(const uint64_t& aLayersId, + const TextureFactoryIdentifier& aNewIdentifier) +{ + if (mLayerManager) { + // This case is handled directly by nsBaseWidget. + MOZ_ASSERT(aLayersId == 0); + } else if (aLayersId != 0) { + if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) { + child->CompositorUpdated(aNewIdentifier); + } } return true; } diff --git a/gfx/layers/ipc/CompositorChild.h b/gfx/layers/ipc/CompositorChild.h index a8ce648ddc..d9716a4c22 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -79,7 +79,11 @@ public: const TimeStamp& aCompositeEnd) override; virtual bool - RecvInvalidateAll() override; + RecvInvalidateLayers(const uint64_t& aLayersId) override; + + virtual bool + RecvCompositorUpdated(const uint64_t& aLayersId, + const TextureFactoryIdentifier& aNewIdentifier) override; virtual bool RecvOverfill(const uint32_t &aOverfill) override; diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index af3cca858a..1c2419aeb4 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -132,6 +132,19 @@ static void EnsureLayerTreeMapReady() } } +template +inline void +CompositorParent::ForEachIndirectLayerTree(const Lambda& aCallback) +{ + sIndirectLayerTreesLock->AssertCurrentThreadOwns(); + for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end(); it++) { + LayerTreeState* state = &it->second; + if (state->mParent == this) { + aCallback(state, it->first); + } + } +} + /** * A global map referencing each compositor by ID. * @@ -662,6 +675,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, , mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight) , mPauseCompositionMonitor("PauseCompositionMonitor") , mResumeCompositionMonitor("ResumeCompositionMonitor") + , mResetCompositorMonitor("ResetCompositorMonitor") , mRootLayerTreeID(AllocateLayerTreeId()) , mOverrideComposeReadiness(false) , mForceCompositionTask(nullptr) @@ -765,16 +779,11 @@ CompositorParent::RecvWillStop() // Ensure that the layer manager is destroyed before CompositorChild. if (mLayerManager) { MonitorAutoLock lock(*sIndirectLayerTreesLock); - for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin(); - it != sIndirectLayerTrees.end(); it++) - { - LayerTreeState* lts = &it->second; - if (lts->mParent == this) { - mLayerManager->ClearCachedResources(lts->mRoot); - lts->mLayerManager = nullptr; - lts->mParent = nullptr; - } - } + ForEachIndirectLayerTree([this] (LayerTreeState* lts, uint64_t) -> void { + mLayerManager->ClearCachedResources(lts->mRoot); + lts->mLayerManager = nullptr; + lts->mParent = nullptr; + }); mLayerManager->Destroy(); mLayerManager = nullptr; mCompositionManager = nullptr; @@ -863,6 +872,15 @@ CompositorParent::RecvFlushRendering() return true; } +bool +CompositorParent::RecvForcePresent() +{ + if (mLayerManager) { + mLayerManager->ForcePresent(); + } + return true; +} + bool CompositorParent::RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) { @@ -1539,6 +1557,20 @@ CompositorParent::InitializeLayerManager(const nsTArray& aBackend NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager"); NS_ASSERTION(!mCompositor, "Already initialised mCompositor"); + mCompositor = NewCompositor(aBackendHints); + if (!mCompositor) { + return; + } + + mLayerManager = new LayerManagerComposite(mCompositor); + + MonitorAutoLock lock(*sIndirectLayerTreesLock); + sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = mLayerManager; +} + +RefPtr +CompositorParent::NewCompositor(const nsTArray& aBackendHints) +{ for (size_t i = 0; i < aBackendHints.Length(); ++i) { RefPtr compositor; if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) { @@ -1563,24 +1595,13 @@ CompositorParent::InitializeLayerManager(const nsTArray& aBackend #endif } - if (!compositor) { - // We passed a backend hint for which we can't create a compositor. - // For example, we sometime pass LayersBackend::LAYERS_NONE as filler in aBackendHints. - continue; - } - - compositor->SetCompositorID(mCompositorID); - RefPtr layerManager = new LayerManagerComposite(compositor); - - if (layerManager->Initialize()) { - mLayerManager = layerManager; - MOZ_ASSERT(compositor); - mCompositor = compositor; - MonitorAutoLock lock(*sIndirectLayerTreesLock); - sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = layerManager; - return; + if (compositor && compositor->Initialize()) { + compositor->SetCompositorID(mCompositorID); + return compositor; } } + + return nullptr; } PLayerTransactionParent* @@ -1896,6 +1917,7 @@ public: virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override { return true; } virtual bool RecvFlushRendering() override { return true; } + virtual bool RecvForcePresent() override { return true; } virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; } virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; } virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) override { return true; } @@ -1999,14 +2021,114 @@ CompositorParent::DidComposite(TimeStamp& aCompositeStart, } MonitorAutoLock lock(*sIndirectLayerTreesLock); - for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin(); - it != sIndirectLayerTrees.end(); it++) { - LayerTreeState* lts = &it->second; - if (lts->mParent == this && lts->mCrossProcessParent) { - static_cast(lts->mCrossProcessParent)->DidComposite( - it->first, aCompositeStart, aCompositeEnd); + ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void { + if (lts->mCrossProcessParent) { + auto cpcp = static_cast(lts->mCrossProcessParent); + cpcp->DidComposite(aLayersId, aCompositeStart, aCompositeEnd); } + }); +} + +void +CompositorParent::InvalidateRemoteLayers() +{ + MOZ_ASSERT(CompositorLoop() == MessageLoop::current()); + + Unused << PCompositorParent::SendInvalidateLayers(0); + + MonitorAutoLock lock(*sIndirectLayerTreesLock); + ForEachIndirectLayerTree([] (LayerTreeState* lts, const uint64_t& aLayersId) -> void { + if (lts->mCrossProcessParent) { + auto cpcp = static_cast(lts->mCrossProcessParent); + Unused << cpcp->SendInvalidateLayers(aLayersId); + } + }); +} + +bool +CompositorParent::ResetCompositor(const nsTArray& aBackendHints, + TextureFactoryIdentifier* aOutIdentifier) +{ + Maybe newIdentifier; + { + MonitorAutoLock lock(mResetCompositorMonitor); + + CompositorLoop()->PostTask(FROM_HERE, + NewRunnableMethod(this, + &CompositorParent::ResetCompositorTask, + aBackendHints, + &newIdentifier)); + + mResetCompositorMonitor.Wait(); } + + if (!newIdentifier) { + return false; + } + + *aOutIdentifier = newIdentifier.value(); + return true; +} + +// Invoked on the compositor thread. The main thread is waiting on the given +// monitor. +void +CompositorParent::ResetCompositorTask(const nsTArray& aBackendHints, + Maybe* aOutNewIdentifier) +{ + // Perform the reset inside a lock, so the main thread can wake up as soon as + // possible. We notify child processes (if necessary) outside the lock. + Maybe newIdentifier; + { + MonitorAutoLock lock(mResetCompositorMonitor); + + newIdentifier = ResetCompositorImpl(aBackendHints); + *aOutNewIdentifier = newIdentifier; + + mResetCompositorMonitor.NotifyAll(); + } + + // NOTE: |aBackendHints|, and |aOutNewIdentifier| are now all invalid since + // they are allocated on ResetCompositor's stack on the main thread, which + // is no longer waiting on the lock. + + if (!newIdentifier) { + // No compositor change; nothing to do. + return; + } + + MonitorAutoLock lock(*sIndirectLayerTreesLock); + ForEachIndirectLayerTree([&] (LayerTreeState* lts, uint64_t layersId) -> void { + if (CrossProcessCompositorParent* cpcp = lts->mCrossProcessParent) { + Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value()); + } + }); +} + +Maybe +CompositorParent::ResetCompositorImpl(const nsTArray& aBackendHints) +{ + if (!mLayerManager) { + return Nothing(); + } + + RefPtr compositor = NewCompositor(aBackendHints); + if (!compositor) { + return Nothing(); + } + + // Don't bother changing from basic->basic. + if (mCompositor && + mCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC && + compositor->GetBackendType() == LayersBackend::LAYERS_BASIC) + { + return Nothing(); + } + + mCompositor = compositor; + mLayerManager->ChangeCompositor(compositor); + + return Some(compositor->GetTextureFactoryIdentifier()); } static void diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index e21f29577c..a570bf41a7 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -22,6 +22,7 @@ #include "base/thread.h" // for Thread #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 #include "mozilla/Attributes.h" // for override +#include "mozilla/Maybe.h" #include "mozilla/Monitor.h" // for Monitor #include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/TimeStamp.h" // for TimeStamp @@ -238,6 +239,7 @@ public: const gfx::IntRect& aRect) override; virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override; virtual bool RecvFlushRendering() override; + virtual bool RecvForcePresent() override; virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) override; @@ -274,6 +276,20 @@ public: const nsTArray& aTargets) override; virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) override { return mCompositionManager; } + /** + * Request that the compositor be recreated due to a shared device reset. + * This must be called on the main thread, and blocks until a task posted + * to the compositor thread has completed. + * + * Note that this posts a task directly, rather than using synchronous + * IPDL, and waits on a monitor notification from the compositor thread. + * We do this as a best-effort attempt to jump any IPDL messages that + * have not yet been posted (and are sitting around in the IO pipe), to + * minimize the amount of time the main thread is blocked. + */ + bool ResetCompositor(const nsTArray& aBackendHints, + TextureFactoryIdentifier* aOutIdentifier); + /** * This forces the is-first-paint flag to true. This is intended to * be called by the widget code when it loses its viewport information @@ -318,6 +334,15 @@ public: */ uint64_t RootLayerTreeId(); + /** + * Notify local and remote layer trees connected to this compositor that + * the compositor's local device is being reset. All layers must be + * invalidated to clear any cached TextureSources. + * + * This must be called on the compositor thread. + */ + void InvalidateRemoteLayers(); + /** * Returns a pointer to the compositor corresponding to the given ID. */ @@ -491,6 +516,11 @@ protected: void CancelCurrentCompositeTask(); void Invalidate(); + RefPtr NewCompositor(const nsTArray& aBackendHints); + void ResetCompositorTask(const nsTArray& aBackendHints, + Maybe* aOutNewIdentifier); + Maybe ResetCompositorImpl(const nsTArray& aBackendHints); + /** * Add a compositor to the global compositor map. */ @@ -508,6 +538,11 @@ protected: void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd); + // The indirect layer tree lock must be held before calling this function. + // Callback should take (LayerTreeState* aState, const uint64_t& aLayersId) + template + inline void ForEachIndirectLayerTree(const Lambda& aCallback); + RefPtr mLayerManager; RefPtr mCompositor; RefPtr mCompositionManager; @@ -524,6 +559,7 @@ protected: mozilla::Monitor mPauseCompositionMonitor; mozilla::Monitor mResumeCompositionMonitor; + mozilla::Monitor mResetCompositorMonitor; uint64_t mCompositorID; const uint64_t mRootLayerTreeID; diff --git a/gfx/layers/ipc/PCompositor.ipdl b/gfx/layers/ipc/PCompositor.ipdl index 94e44e5ffa..4c2375ba0e 100644 --- a/gfx/layers/ipc/PCompositor.ipdl +++ b/gfx/layers/ipc/PCompositor.ipdl @@ -41,8 +41,15 @@ sync protocol PCompositor manages PLayerTransaction; child: - // The child should invalidate everything so that the whole window is redrawn. - async InvalidateAll(); + // The child should invalidate retained layers. This is used for local + // compositor device resets, such as in CompositorD3D9, and ensures that + // TextureSources are recreated. + async InvalidateLayers(uint64_t layersId); + + // The compositor type or device has changed, and a new texture factory + // identifier is available. Layers must be invalidated and the new identifier + // must be propagated. + async CompositorUpdated(uint64_t layersId, TextureFactoryIdentifier newIdentifier); // The compositor completed a layers transaction. id is the layers id // of the child layer tree that was composited (or 0 when notifying @@ -140,6 +147,10 @@ parent: // block until they are completed. sync FlushRendering(); + // Force an additional frame presentation to be executed. This is used to + // work around a windows presentation bug (See Bug 1232042) + async ForcePresent(); + // Get the size of the tiles. This number should not change at runtime. sync GetTileSize() returns (int32_t tileWidth, int32_t tileHeight); diff --git a/gfx/tests/gtest/TestCompositor.cpp b/gfx/tests/gtest/TestCompositor.cpp index f344ce25e6..a21a3b1bd5 100644 --- a/gfx/tests/gtest/TestCompositor.cpp +++ b/gfx/tests/gtest/TestCompositor.cpp @@ -127,7 +127,7 @@ static already_AddRefed CreateTestCompositor(LayersBackend backend, #endif } - if (!compositor) { + if (!compositor || !compositor->Initialize()) { printf_stderr("Failed to construct layer manager for the requested backend\n"); abort(); } @@ -150,8 +150,6 @@ static std::vector GetLayerManagers(std::vector RefPtr layerManager = new LayerManagerComposite(compositor); - layerManager->Initialize(); - managers.push_back(LayerManagerData(compositor, widget, layerManager)); } diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 65423126f1..77e39c6fb1 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -477,6 +477,7 @@ gfxPlatform::gfxPlatform() , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo) , mCompositorBackend(layers::LayersBackend::LAYERS_NONE) , mScreenDepth(0) + , mDeviceCounter(0) { mAllowDownloadableFonts = UNINITIALIZED_VALUE; mFallbackUsesCmaps = UNINITIALIZED_VALUE; @@ -2416,3 +2417,9 @@ gfxPlatform::SupportsApzDragInput() const { return gfxPrefs::APZDragEnabled(); } + +void +gfxPlatform::BumpDeviceCounter() +{ + mDeviceCounter++; +} diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 362c24c4aa..f88519d366 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -611,11 +611,14 @@ public: virtual void FlushContentDrawing() {} - // If a device reset has occurred, update the necessary platform backend - // bits. - virtual bool UpdateForDeviceReset() { - return false; - } + // If a device reset has occurred, schedule any necessary paints in the + // widget. This should only be used within nsRefreshDriver. + virtual void SchedulePaintIfDeviceReset() {} + + // Immediately update all platform bits if a device reset has occurred. + // This should only be used at the top of the callstack (i.e. within + // a task, OS event, or IPDL message). + virtual void UpdateRenderModeIfDeviceReset() {} /** * Helper method, creates a draw target for a specific Azure backend. @@ -637,10 +640,6 @@ public: return mCompositorBackend; } - // Trigger a test-driven graphics device reset. - virtual void TestDeviceReset(DeviceResetReason aReason) - {} - // Return information on how child processes should initialize graphics // devices. Currently this is only used on Windows. virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut); @@ -656,6 +655,10 @@ public: return false; } + uint64_t GetDeviceCounter() const { + return mDeviceCounter; + } + protected: gfxPlatform(); virtual ~gfxPlatform(); @@ -685,6 +688,11 @@ protected: */ void UpdateDeviceInitData(); + /** + * Increase the global device counter after a device has been removed/reset. + */ + void BumpDeviceCounter(); + /** * Called when new device preferences are available. */ @@ -797,6 +805,9 @@ private: int32_t mScreenDepth; mozilla::gfx::IntSize mScreenSize; + + // Generation number for devices that ClientLayerManagers might depend on. + uint64_t mDeviceCounter; }; #endif /* GFX_PLATFORM_H */ diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 1beced6b73..a485ae2926 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -463,17 +463,7 @@ gfxWindowsPlatform::HandleDeviceReset() return false; } - if (mHasFakeDeviceReset) { - if (XRE_IsParentProcess()) { - // Notify child processes that we got a device reset. - nsTArray processes; - dom::ContentParent::GetAll(processes); - - for (size_t i = 0; i < processes.Length(); i++) { - processes[i]->SendTestGraphicsDeviceReset(uint32_t(resetReason)); - } - } - } else { + if (!mHasFakeDeviceReset) { Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason)); } @@ -496,6 +486,7 @@ gfxWindowsPlatform::HandleDeviceReset() // list of which devices to create. UpdateDeviceInitData(); InitializeDevices(); + BumpDeviceCounter(); return true; } @@ -1063,13 +1054,13 @@ InvalidateWindowForDeviceReset(HWND aWnd, LPARAM aMsg) return TRUE; } -bool -gfxWindowsPlatform::UpdateForDeviceReset() +void +gfxWindowsPlatform::SchedulePaintIfDeviceReset() { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS); if (!DidRenderingDeviceReset()) { - return false; + return; } // Trigger an ::OnPaint for each window. @@ -1078,7 +1069,16 @@ gfxWindowsPlatform::UpdateForDeviceReset() 0); gfxCriticalNote << "Detected rendering device reset on refresh"; - return true; +} + +void +gfxWindowsPlatform::UpdateRenderModeIfDeviceReset() +{ + PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS); + + if (DidRenderingDeviceReset()) { + UpdateRenderMode(); + } } void diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 51011799ef..1426f2f871 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -204,7 +204,8 @@ public: virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) override; bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override; - bool UpdateForDeviceReset() override; + void SchedulePaintIfDeviceReset() override; + void UpdateRenderModeIfDeviceReset() override; mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override; @@ -272,7 +273,7 @@ public: mozilla::gfx::FeatureStatus GetD2D1Status() const; unsigned GetD3D11Version(); - void TestDeviceReset(DeviceResetReason aReason) override; + void TestDeviceReset(DeviceResetReason aReason); virtual already_AddRefed CreateHardwareVsyncSource() override; static mozilla::Atomic sD3D11MemoryUsed; diff --git a/js/src/asmjs/WasmSerialize.h b/js/src/asmjs/WasmSerialize.h index 6efccb8355..b13ab5f06f 100644 --- a/js/src/asmjs/WasmSerialize.h +++ b/js/src/asmjs/WasmSerialize.h @@ -274,9 +274,9 @@ class MachineId public: bool extractCurrentState(ExclusiveContext* cx) { - if (!cx->asmJSCacheOps().buildId) + if (!cx->buildIdOp()) return false; - if (!cx->asmJSCacheOps().buildId(&buildId_)) + if (!cx->buildIdOp()(&buildId_)) return false; if (!GetCPUID(&cpuId_)) return false; diff --git a/js/src/frontend/SourceNotes.h b/js/src/frontend/SourceNotes.h index 98fe620753..dd2a95ad1e 100644 --- a/js/src/frontend/SourceNotes.h +++ b/js/src/frontend/SourceNotes.h @@ -33,9 +33,6 @@ namespace js { * * NB: the js_SrcNoteSpec array in BytecodeEmitter.cpp is indexed by this * enum, so its initializers need to match the order here. - * - * Don't forget to update XDR_BYTECODE_VERSION in vm/Xdr.h for all such - * incompatible source note or other bytecode changes. */ #define FOR_EACH_SRC_NOTE_TYPE(M) \ M(SRC_NULL, "null", 0) /* Terminates a note vector. */ \ diff --git a/js/src/js.msg b/js/src/js.msg index 22063dc45b..02354867de 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -169,9 +169,10 @@ MSG_DEF(JSMSG_USER_DEFINED_ERROR, 0, JSEXN_ERR, "JS_ReportError was called" // Internal errors MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size overflow") +MSG_DEF(JSMSG_BAD_BUILD_ID, 0, JSEXN_INTERNALERR, "bad build ID for XDR script") MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}") -MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 0, JSEXN_INTERNALERR, "bad script XDR magic number") MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small") +MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE, 0, JSEXN_INTERNALERR, "build ID is not available") MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})") MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties") MSG_DEF(JSMSG_INACTIVE, 0, JSEXN_INTERNALERR, "nothing active on context") diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp index 3fc66437eb..a28cc464d4 100644 --- a/js/src/jsapi-tests/testXDR.cpp +++ b/js/src/jsapi-tests/testXDR.cpp @@ -12,9 +12,18 @@ #include "jsscriptinlines.h" +static bool +GetBuildId(JS::BuildIdCharVector* buildId) +{ + const char buildid[] = "testXDR"; + return buildId->append(buildid, sizeof(buildid)); +} + static JSScript* FreezeThaw(JSContext* cx, JS::HandleScript script) { + JS::SetBuildIdOp(cx->runtime(), GetBuildId); + // freeze uint32_t nbytes; void* memory = JS_EncodeScript(cx, script, &nbytes); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index bfa080c28e..8dbbb02b5a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -6298,6 +6298,12 @@ JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length) return funobj; } +JS_PUBLIC_API(void) +JS::SetBuildIdOp(JSRuntime* rt, JS::BuildIdOp buildIdOp) +{ + rt->buildIdOp = buildIdOp; +} + JS_PUBLIC_API(void) JS::SetAsmJSCacheOps(JSRuntime* rt, const JS::AsmJSCacheOps* ops) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 36c7c1816e..1701210df0 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -5585,12 +5585,14 @@ struct AsmJSCacheOps CloseAsmJSCacheEntryForReadOp closeEntryForRead; OpenAsmJSCacheEntryForWriteOp openEntryForWrite; CloseAsmJSCacheEntryForWriteOp closeEntryForWrite; - BuildIdOp buildId; }; extern JS_PUBLIC_API(void) SetAsmJSCacheOps(JSRuntime* rt, const AsmJSCacheOps* callbacks); +extern JS_PUBLIC_API(void) +SetBuildIdOp(JSRuntime* rt, BuildIdOp buildIdOp); + /** * Convenience class for imitating a JS level for-of loop. Typical usage: * diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 6c5fb0c267..3b0b26e185 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -190,6 +190,7 @@ class ExclusiveContext : public ContextFriendFields, bool isPermanentAtomsInitialized() { return !!runtime_->permanentAtoms; } FrozenAtomSet& permanentAtoms() { return *runtime_->permanentAtoms; } WellKnownSymbols& wellKnownSymbols() { return *runtime_->wellKnownSymbols; } + JS::BuildIdOp buildIdOp() { return runtime_->buildIdOp; } const JS::AsmJSCacheOps& asmJSCacheOps() { return runtime_->asmJSCacheOps; } PropertyName* emptyString() { return runtime_->emptyString; } FreeOp* defaultFreeOp() { return runtime_->defaultFreeOp(); } diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index babd207d71..d34e402239 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -926,9 +926,6 @@ JS_FRIEND_API(bool) IsObjectInContextCompartment(JSObject* obj, const JSContext* cx); /* - * NB: these flag bits are encoded into the bytecode stream in the immediate - * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's - * XDR_BYTECODE_VERSION. * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h. * The first three are omitted because they shouldn't be used in new code. */ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 8e4dbae86c..d142874280 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -6305,8 +6305,7 @@ static const JS::AsmJSCacheOps asmJSCacheOps = { ShellOpenAsmJSCacheEntryForRead, ShellCloseAsmJSCacheEntryForRead, ShellOpenAsmJSCacheEntryForWrite, - ShellCloseAsmJSCacheEntryForWrite, - ShellBuildId + ShellCloseAsmJSCacheEntryForWrite }; static JSContext* @@ -7215,6 +7214,7 @@ main(int argc, char** argv, char** envp) JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy); JS_SetInterruptCallback(rt, ShellInterruptCallback); + JS::SetBuildIdOp(rt, ShellBuildId); JS::SetAsmJSCacheOps(rt, &asmJSCacheOps); JS_SetNativeStackQuota(rt, gMaxStackSize); diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index d7d04e38d5..180d66ee5a 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -205,6 +205,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime) destroyPrincipals(nullptr), readPrincipals(nullptr), errorReporter(nullptr), + buildIdOp(nullptr), propertyRemovals(0), #if !EXPOSE_INTL_API thousandsSeparator(0), diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 73fc60e8eb..55ffc78906 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1231,6 +1231,8 @@ struct JSRuntime : public JS::shadow::Runtime, /* Optional error reporter. */ JSErrorReporter errorReporter; + JS::BuildIdOp buildIdOp; + /* AsmJSCache callbacks are runtime-wide. */ JS::AsmJSCacheOps asmJSCacheOps; diff --git a/js/src/vm/Xdr.cpp b/js/src/vm/Xdr.cpp index f648c4318d..5e38f9ca1e 100644 --- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -6,6 +6,8 @@ #include "vm/Xdr.h" +#include "mozilla/PodOperations.h" + #include #include "jsapi.h" @@ -15,6 +17,7 @@ #include "vm/ScopeObject.h" using namespace js; +using mozilla::PodEqual; void XDRBuffer::freeBuffer() @@ -92,19 +95,48 @@ template static bool VersionCheck(XDRState* xdr) { - uint32_t bytecodeVer; + JS::BuildIdCharVector buildId; + if (!xdr->cx()->buildIdOp() || !xdr->cx()->buildIdOp()(&buildId)) { + JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BUILD_ID_NOT_AVAILABLE); + return false; + } + MOZ_ASSERT(!buildId.empty()); + + uint32_t buildIdLength; if (mode == XDR_ENCODE) - bytecodeVer = XDR_BYTECODE_VERSION; + buildIdLength = buildId.length(); - if (!xdr->codeUint32(&bytecodeVer)) + if (!xdr->codeUint32(&buildIdLength)) return false; - if (mode == XDR_DECODE && bytecodeVer != XDR_BYTECODE_VERSION) { - /* We do not provide binary compatibility with older scripts. */ - JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_SCRIPT_MAGIC); + if (mode == XDR_DECODE && buildIdLength != buildId.length()) { + JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID); return false; } + if (mode == XDR_ENCODE) { + if (!xdr->codeBytes(buildId.begin(), buildIdLength)) + return false; + } else { + JS::BuildIdCharVector decodedBuildId; + + // buildIdLength is already checked against the length of current + // buildId. + if (!decodedBuildId.resize(buildIdLength)) { + ReportOutOfMemory(xdr->cx()); + return false; + } + + if (!xdr->codeBytes(decodedBuildId.begin(), buildIdLength)) + return false; + + if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength)) { + // We do not provide binary compatibility with older scripts. + JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID); + return false; + } + } + return true; } diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 8da356e1a6..e6ce55c015 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -15,32 +15,6 @@ namespace js { -/* - * Bytecode version number. Increment the subtrahend whenever JS bytecode - * changes incompatibly. - * - * This version number is XDR'd near the front of xdr bytecode and aborts - * deserialization if there is a mismatch between the current and saved - * versions. If deserialization fails, the data should be invalidated if - * possible. - * - * When you change this, run make_opcode_doc.py and copy the new output into - * this wiki page: - * - * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode - * - * (If you're wondering, 0xb973c0de is used because it looks like "bytecode".) - */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 335; -static const uint32_t XDR_BYTECODE_VERSION = - uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); - -static_assert(JSErr_Limit == 445, - "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or " - "removed MSG_DEFs from js.msg, you should increment " - "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " - "expected JSErr_Limit value."); - class XDRBuffer { public: explicit XDRBuffer(JSContext* cx) diff --git a/js/src/vm/make_opcode_doc.py b/js/src/vm/make_opcode_doc.py index 321c4527eb..55bcb26bef 100755 --- a/js/src/vm/make_opcode_doc.py +++ b/js/src/vm/make_opcode_doc.py @@ -3,7 +3,7 @@ """ Usage: make_opcode_doc.py PATH_TO_MOZILLA_CENTRAL This script generates SpiderMonkey bytecode documentation - from js/src/vm/Opcodes.h and js/src/vm/Xdr.h. + from js/src/vm/Opcodes.h. Output is written to stdout and should be pasted into the following MDN page: @@ -21,25 +21,6 @@ def error(message): print("Error: {message}".format(message=message), file=sys.stderr) sys.exit(1) -def get_xdr_version(dir): - subtrahend_pat = re.compile('XDR_BYTECODE_VERSION_SUBTRAHEND\s*=\s*(\d+);', re.S) - version_expr_pat = re.compile('XDR_BYTECODE_VERSION\s*=\s*uint32_t\(0xb973c0de\s*-\s*(.+?)\);', re.S) - - with open('{dir}/js/src/vm/Xdr.h'.format(dir=dir), 'r') as f: - data = f.read() - - m = subtrahend_pat.search(data) - if not m: - error('XDR_BYTECODE_VERSION_SUBTRAHEND is not recognized.') - - subtrahend = int(m.group(1)) - - m = version_expr_pat.search(data) - if not m: - error('XDR_BYTECODE_VERSION is not recognized.') - - return subtrahend - quoted_pat = re.compile(r"([^A-Za-z0-9]|^)'([^']+)'") js_pat = re.compile(r"([^A-Za-z0-9]|^)(JS[A-Z0-9_\*]+)") def codify(text): @@ -355,21 +336,15 @@ def make_element_id(category, type=''): id_cache[key] = id return id -def print_doc(version, index): +def print_doc(index): print("""
{{{{SpiderMonkeySidebar("Internals")}}}}

Bytecode Listing

This document is automatically generated from -Opcodes.h and -Xdr.h by +Opcodes.h by make_opcode_doc.py.

- -

Bytecode version: {version} -(0x{actual_version:08x}).

-""".format(source_base=SOURCE_BASE, - version=version, - actual_version=0xb973c0de - version)) +""".format(source_base=SOURCE_BASE)) for (category_name, types) in index: print('

{name}

'.format(name=category_name, @@ -390,6 +365,5 @@ if __name__ == '__main__': file=sys.stderr) sys.exit(1) dir = sys.argv[1] - version = get_xdr_version(dir) index = get_opcodes(dir) - print_doc(version, index) + print_doc(index) diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 208e6e4a73..5112a1d08f 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -699,6 +699,9 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo, // cache. Could mean that the cache was corrupted and got removed, // but either way we're going to write this out. writeToCache = true; + // ReadCachedScript and ReadCachedFunction may have set a pending + // exception. + JS_ClearPendingException(cx); } } diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index 67b27dcac0..f6f559b07d 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -656,8 +656,13 @@ mozJSSubScriptLoader::DoLoadSubScriptWithOptions(const nsAString& url, RootedFunction function(cx); RootedScript script(cx); - if (cache && !options.ignoreCache) + if (cache && !options.ignoreCache) { rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script); + if (NS_FAILED(rv)) { + // ReadCachedScript may have set a pending exception. + JS_ClearPendingException(cx); + } + } // If we are doing an async load, trigger it and bail out. if (!script && options.async) { diff --git a/js/xpconnect/tests/unit/test_xpcomutils.js b/js/xpconnect/tests/unit/test_xpcomutils.js index 82807f7bf6..ea41b08e8d 100644 --- a/js/xpconnect/tests/unit/test_xpcomutils.js +++ b/js/xpconnect/tests/unit/test_xpcomutils.js @@ -123,23 +123,14 @@ add_test(function test_categoryRegistration() const XULAPPINFO_CID = Components.ID("{fc937916-656b-4fb3-a395-8c63569e27a8}"); // Create a fake app entry for our category registration apps filter. - let XULAppInfo = { - vendor: "Mozilla", + let tmp = {}; + Components.utils.import("resource://testing-common/AppInfo.jsm", tmp); + let XULAppInfo = tmp.newAppInfo({ name: "catRegTest", ID: "{adb42a9a-0d19-4849-bf4d-627614ca19be}", version: "1", - appBuildID: "2007010101", platformVersion: "", - platformBuildID: "2007010101", - inSafeMode: false, - logConsoleErrors: true, - OS: "XPCShell", - XPCOMABI: "noarch-spidermonkey", - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIXULAppInfo, - Ci.nsIXULRuntime, - ]) - }; + }); let XULAppInfoFactory = { createInstance: function (outer, iid) { if (outer != null) diff --git a/layout/base/UnitTransforms.h b/layout/base/UnitTransforms.h index b6e6a25504..d229dbd590 100644 --- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -9,6 +9,7 @@ #include "Units.h" #include "mozilla/gfx/Matrix.h" +#include "mozilla/Maybe.h" #include "nsRegion.h" namespace mozilla { diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index a90837d168..96c4b5024a 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -1664,7 +1664,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) AutoRestore restoreTickStart(mTickStart); mTickStart = TimeStamp::Now(); - gfxPlatform::GetPlatform()->UpdateForDeviceReset(); + gfxPlatform::GetPlatform()->SchedulePaintIfDeviceReset(); /* * The timer holds a reference to |this| while calling |Notify|. diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5893d50125..bfc58a9143 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2326,6 +2326,13 @@ pref("security.ssl.enable_ocsp_must_staple", true); // Enable pinning checks by default. pref("security.cert_pinning.enforcement_level", 2); +#ifdef RELEASE_BUILD +pref("security.onecrl.via.amo", true); +#else +pref("security.onecrl.via.amo", false); +#endif + + // Modifier key prefs: default to Windows settings, // menu access key = alt, accelerator key = control. // Use 17 for Ctrl, 18 for Alt, 224 for Meta, 91 for Win, 0 for none. Mac settings in macprefs.js diff --git a/security/apps/AppSignatureVerification.cpp b/security/apps/AppSignatureVerification.cpp index c7016f3594..aaf75026fb 100644 --- a/security/apps/AppSignatureVerification.cpp +++ b/security/apps/AppSignatureVerification.cpp @@ -40,7 +40,7 @@ using namespace mozilla::pkix; using namespace mozilla; using namespace mozilla::psm; -extern PRLogModuleInfo* gPIPNSSLog; +extern mozilla::LazyLogModule gPIPNSSLog; namespace { diff --git a/security/apps/AppTrustDomain.cpp b/security/apps/AppTrustDomain.cpp index a1dc797ede..7995aa2246 100644 --- a/security/apps/AppTrustDomain.cpp +++ b/security/apps/AppTrustDomain.cpp @@ -37,7 +37,7 @@ using namespace mozilla::pkix; -extern PRLogModuleInfo* gPIPNSSLog; +extern mozilla::LazyLogModule gPIPNSSLog; static const unsigned int DEFAULT_MIN_RSA_BITS = 2048; static char kDevImportedDER[] = diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp index 069af61145..629f270cf4 100644 --- a/security/certverifier/CertVerifier.cpp +++ b/security/certverifier/CertVerifier.cpp @@ -12,17 +12,20 @@ #include "NSSCertDBTrustDomain.h" #include "NSSErrorsService.h" #include "cert.h" +#include "nsNSSComponent.h" +#include "nsServiceManagerUtils.h" #include "pk11pub.h" #include "pkix/pkix.h" #include "pkix/pkixnss.h" #include "prerror.h" #include "secerr.h" +#include "secmod.h" #include "sslerr.h" using namespace mozilla::pkix; using namespace mozilla::psm; -PRLogModuleInfo* gCertVerifierLog = nullptr; +mozilla::LazyLogModule gCertVerifierLog("certverifier"); namespace mozilla { namespace psm { @@ -52,33 +55,69 @@ CertVerifier::~CertVerifier() void InitCertVerifierLog() { - if (!gCertVerifierLog) { - gCertVerifierLog = PR_NewLogModule("certverifier"); - } } -SECStatus -IsCertBuiltInRoot(CERTCertificate* cert, bool& result) { +Result +IsCertChainRootBuiltInRoot(CERTCertList* chain, bool& result) +{ + if (!chain || CERT_LIST_EMPTY(chain)) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; + } + CERTCertListNode* rootNode = CERT_LIST_TAIL(chain); + if (!rootNode) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; + } + CERTCertificate* root = rootNode->cert; + if (!root) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; + } + return IsCertBuiltInRoot(root, result); +} + +Result +IsCertBuiltInRoot(CERTCertificate* cert, bool& result) +{ result = false; - ScopedPK11SlotList slots; - slots = PK11_GetAllSlotsForCert(cert, nullptr); - if (!slots) { - if (PORT_GetError() == SEC_ERROR_NO_TOKEN) { - // no list - return SECSuccess; - } - return SECFailure; + nsCOMPtr component(do_GetService(PSM_COMPONENT_CONTRACTID)); + if (!component) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; } - for (PK11SlotListElement* le = slots->head; le; le = le->next) { - char* token = PK11_GetTokenName(le->slot); - MOZ_LOG(gCertVerifierLog, LogLevel::Debug, - ("BuiltInRoot? subject=%s token=%s",cert->subjectName, token)); - if (strcmp("Builtin Object Token", token) == 0) { - result = true; - return SECSuccess; - } + nsresult rv; +#ifdef DEBUG + rv = component->IsCertTestBuiltInRoot(cert, result); + if (NS_FAILED(rv)) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; } - return SECSuccess; + if (result) { + return Success; + } +#endif // DEBUG + nsAutoString modName; + rv = component->GetPIPNSSBundleString("RootCertModuleName", modName); + if (NS_FAILED(rv)) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; + } + NS_ConvertUTF16toUTF8 modNameUTF8(modName); + UniqueSECMODModule builtinRootsModule(SECMOD_FindModule(modNameUTF8.get())); + // If the built-in roots module isn't loaded, nothing is a built-in root. + if (!builtinRootsModule) { + return Success; + } + UniquePK11SlotInfo builtinSlot(SECMOD_FindSlot(builtinRootsModule.get(), + "Builtin Object Token")); + // This could happen if the user loaded a module that is acting like the + // built-in roots module but doesn't actually have a slot called "Builtin + // Object Token". In that case, again nothing is a built-in root. + if (!builtinSlot) { + return Success; + } + // Attempt to find a copy of the given certificate in the "Builtin Object + // Token" slot of the built-in root module. If we get a valid handle, this + // certificate exists in the root module, so we consider it a built-in root. + CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(builtinSlot.get(), cert, + nullptr); + result = (handle != CK_INVALID_HANDLE); + return Success; } static Result @@ -115,19 +154,37 @@ BuildCertChainForOneKeyUsage(NSSCertDBTrustDomain& trustDomain, Input certDER, return rv; } +bool +CertVerifier::SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode) +{ + switch (mSHA1Mode) { + case SHA1Mode::Forbidden: + return mode != SHA1Mode::Forbidden; + case SHA1Mode::Before2016: + return mode != SHA1Mode::Forbidden && mode != SHA1Mode::Before2016; + case SHA1Mode::ImportedRoot: + return mode == SHA1Mode::Allowed; + case SHA1Mode::Allowed: + return false; + default: + MOZ_ASSERT(false, "unexpected SHA1Mode type"); + return true; + } +} + static const unsigned int MIN_RSA_BITS = 2048; static const unsigned int MIN_RSA_BITS_WEAK = 1024; SECStatus CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, Time time, void* pinArg, const char* hostname, - const Flags flags, + /*out*/ ScopedCERTCertList& builtChain, + /*optional*/ const Flags flags, /*optional*/ const SECItem* stapledOCSPResponseSECItem, - /*optional out*/ ScopedCERTCertList* builtChain, /*optional out*/ SECOidTag* evOidPolicy, /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus, /*optional out*/ KeySizeStatus* keySizeStatus, - /*optional out*/ SignatureDigestStatus* sigDigestStatus, + /*optional out*/ SHA1ModeResult* sha1ModeResult, /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo) { MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Top of VerifyCert\n")); @@ -135,11 +192,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, PR_ASSERT(cert); PR_ASSERT(usage == certificateUsageSSLServer || !(flags & FLAG_MUST_BE_EV)); PR_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus); - PR_ASSERT(usage == certificateUsageSSLServer || !sigDigestStatus); + PR_ASSERT(usage == certificateUsageSSLServer || !sha1ModeResult); - if (builtChain) { - *builtChain = nullptr; - } if (evOidPolicy) { *evOidPolicy = SEC_OID_UNKNOWN; } @@ -159,12 +213,12 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, *keySizeStatus = KeySizeStatus::NeverChecked; } - if (sigDigestStatus) { + if (sha1ModeResult) { if (usage != certificateUsageSSLServer) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } - *sigDigestStatus = SignatureDigestStatus::NeverChecked; + *sha1ModeResult = SHA1ModeResult::NeverChecked; } if (!cert || @@ -216,8 +270,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeEndEntity, KeyUsage::digitalSignature, @@ -231,24 +285,27 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, // restrict the acceptable key usage based on the key exchange method // chosen by the server. - SignatureDigestOption digestAlgorithmOptions[] = { - DisableSHA1Everywhere, - DisableSHA1ForCA, - DisableSHA1ForEE, - AcceptAllAlgorithms + // These configurations are in order of most restrictive to least + // restrictive. This enables us to gather telemetry on the expected + // results of setting the default policy to a particular configuration. + SHA1Mode sha1ModeConfigurations[] = { + SHA1Mode::Forbidden, + SHA1Mode::Before2016, + SHA1Mode::ImportedRoot, + SHA1Mode::Allowed, }; - SignatureDigestStatus digestAlgorithmStatuses[] = { - SignatureDigestStatus::GoodAlgorithmsOnly, - SignatureDigestStatus::WeakEECert, - SignatureDigestStatus::WeakCACert, - SignatureDigestStatus::WeakCAAndEE + SHA1ModeResult sha1ModeResults[] = { + SHA1ModeResult::SucceededWithoutSHA1, + SHA1ModeResult::SucceededWithSHA1Before2016, + SHA1ModeResult::SucceededWithImportedRoot, + SHA1ModeResult::SucceededWithSHA1, }; - size_t digestAlgorithmOptionsCount = MOZ_ARRAY_LENGTH(digestAlgorithmStatuses); + size_t sha1ModeConfigurationsCount = MOZ_ARRAY_LENGTH(sha1ModeConfigurations); - static_assert(MOZ_ARRAY_LENGTH(digestAlgorithmOptions) == - MOZ_ARRAY_LENGTH(digestAlgorithmStatuses), + static_assert(MOZ_ARRAY_LENGTH(sha1ModeConfigurations) == + MOZ_ARRAY_LENGTH(sha1ModeResults), "digestAlgorithm array lengths differ"); rv = Result::ERROR_UNKNOWN_ERROR; @@ -263,21 +320,30 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, CertPolicyId evPolicy; SECOidTag evPolicyOidTag; SECStatus srv = GetFirstEVPolicy(cert, evPolicy, evPolicyOidTag); - for (size_t i=0; - i < digestAlgorithmOptionsCount && rv != Success && srv == SECSuccess; + for (size_t i = 0; + i < sha1ModeConfigurationsCount && rv != Success && srv == SECSuccess; i++) { // Because of the try-strict and fallback approach, we have to clear any // previously noted telemetry information if (pinningTelemetryInfo) { pinningTelemetryInfo->Reset(); } + // Don't attempt verification if the SHA1 mode set by preferences + // (mSHA1Mode) is more restrictive than the SHA1 mode option we're on. + // (To put it another way, only attempt verification if the SHA1 mode + // option we're on is as restrictive or more restrictive than + // mSHA1Mode.) This allows us to gather telemetry information while + // still enforcing the mode set by preferences. + if (SHA1ModeMoreRestrictiveThanGivenMode(sha1ModeConfigurations[i])) { + continue; + } NSSCertDBTrustDomain trustDomain(trustSSL, evOCSPFetching, mOCSPCache, pinArg, ocspGETConfig, mCertShortLifetimeInDays, mPinningMode, MIN_RSA_BITS, ValidityCheckingMode::CheckForEV, - digestAlgorithmOptions[i], mSHA1Mode, - pinningTelemetryInfo, hostname, builtChain); + sha1ModeConfigurations[i], builtChain, + pinningTelemetryInfo, hostname); rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time, KeyUsage::digitalSignature,// (EC)DHE KeyUsage::keyEncipherment, // RSA @@ -285,14 +351,34 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, KeyPurposeId::id_kp_serverAuth, evPolicy, stapledOCSPResponse, ocspStaplingStatus); + // If we succeeded with the SHA1Mode of only allowing imported roots to + // issue SHA1 certificates after 2015, if the chain we built doesn't + // terminate with an imported root, we must reject it. (This only works + // because we try SHA1 configurations in order of decreasing + // strictness.) + // Note that if there existed a certificate chain with a built-in root + // that had SHA1 certificates issued before 2016, it would have already + // been accepted. If such a chain had SHA1 certificates issued after + // 2015, it will only be accepted in the SHA1Mode::Allowed case. + if (rv == Success && + sha1ModeConfigurations[i] == SHA1Mode::ImportedRoot) { + bool isBuiltInRoot = false; + rv = IsCertChainRootBuiltInRoot(builtChain, isBuiltInRoot); + if (rv != Success) { + break; + } + if (isBuiltInRoot) { + rv = Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; + } + } if (rv == Success) { MOZ_LOG(gCertVerifierLog, LogLevel::Debug, - ("cert is EV with status %i\n", digestAlgorithmStatuses[i])); + ("cert is EV with status %i\n", sha1ModeResults[i])); if (evOidPolicy) { *evOidPolicy = evPolicyOidTag; } - if (sigDigestStatus) { - *sigDigestStatus = digestAlgorithmStatuses[i]; + if (sha1ModeResult) { + *sha1ModeResult = sha1ModeResults[i]; } } } @@ -323,17 +409,21 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, size_t keySizeOptionsCount = MOZ_ARRAY_LENGTH(keySizeStatuses); - for (size_t i=0; iReset(); } - // If we're not going to do SHA-1 in any case, don't try - if (mSHA1Mode == SHA1Mode::Forbidden && - digestAlgorithmOptions[i] != DisableSHA1Everywhere) { + // Don't attempt verification if the SHA1 mode set by preferences + // (mSHA1Mode) is more restrictive than the SHA1 mode option we're on. + // (To put it another way, only attempt verification if the SHA1 mode + // option we're on is as restrictive or more restrictive than + // mSHA1Mode.) This allows us to gather telemetry information while + // still enforcing the mode set by preferences. + if (SHA1ModeMoreRestrictiveThanGivenMode(sha1ModeConfigurations[j])) { continue; } @@ -342,9 +432,9 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, mPinningMode, keySizeOptions[i], ValidityCheckingMode::CheckingOff, - digestAlgorithmOptions[j], - mSHA1Mode, pinningTelemetryInfo, - hostname, builtChain); + sha1ModeConfigurations[j], + builtChain, pinningTelemetryInfo, + hostname); rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time, KeyUsage::digitalSignature,//(EC)DHE KeyUsage::keyEncipherment,//RSA @@ -353,32 +443,49 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, CertPolicyId::anyPolicy, stapledOCSPResponse, ocspStaplingStatus); + // If we succeeded with the SHA1Mode of only allowing imported roots + // to issue SHA1 certificates after 2015, if the chain we built + // doesn't terminate with an imported root, we must reject it. (This + // only works because we try SHA1 configurations in order of + // decreasing strictness.) + // Note that if there existed a certificate chain with a built-in root + // that had SHA1 certificates issued before 2016, it would have + // already been accepted. If such a chain had SHA1 certificates issued + // after 2015, it will only be accepted in the SHA1Mode::Allowed case. + if (rv == Success && + sha1ModeConfigurations[j] == SHA1Mode::ImportedRoot) { + bool isBuiltInRoot = false; + rv = IsCertChainRootBuiltInRoot(builtChain, isBuiltInRoot); + if (rv != Success) { + break; + } + if (isBuiltInRoot) { + rv = Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; + } + } if (rv == Success) { if (keySizeStatus) { *keySizeStatus = keySizeStatuses[i]; } - if (sigDigestStatus) { - *sigDigestStatus = digestAlgorithmStatuses[j]; + if (sha1ModeResult) { + *sha1ModeResult = sha1ModeResults[j]; } } } } if (rv == Success) { - // If SHA-1 is forbidden by preference, don't accumulate SHA-1 - // telemetry, to avoid skewing the results. - if (sigDigestStatus && mSHA1Mode == SHA1Mode::Forbidden) { - *sigDigestStatus = SignatureDigestStatus::NeverChecked; - } - break; } if (keySizeStatus) { *keySizeStatus = KeySizeStatus::AlreadyBad; } - if (sigDigestStatus && mSHA1Mode != SHA1Mode::Forbidden) { - *sigDigestStatus = SignatureDigestStatus::AlreadyBad; + // Only collect CERT_CHAIN_SHA1_POLICY_STATUS telemetry indicating a + // failure when mSHA1Mode is the default. + // NB: When we change the default, we have to change this. + if (sha1ModeResult && mSHA1Mode == SHA1Mode::Allowed) { + *sha1ModeResult = SHA1ModeResult::Failed; } break; @@ -390,8 +497,7 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, mSHA1Mode, - nullptr, nullptr, builtChain); + mSHA1Mode, builtChain, nullptr, nullptr); rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeCA, KeyUsage::keyCertSign, KeyPurposeId::id_kp_serverAuth, @@ -405,8 +511,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeEndEntity, KeyUsage::digitalSignature, @@ -431,8 +537,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeEndEntity, KeyUsage::keyEncipherment, // RSA @@ -454,8 +560,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeEndEntity, KeyUsage::digitalSignature, @@ -486,8 +592,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, pinArg, ocspGETConfig, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(sslTrust, certDER, time, endEntityOrCA, keyUsage, eku, CertPolicyId::anyPolicy, stapledOCSPResponse); @@ -497,8 +603,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, mCertShortLifetimeInDays, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, nullptr, + nullptr); rv = BuildCertChain(emailTrust, certDER, time, endEntityOrCA, keyUsage, eku, CertPolicyId::anyPolicy, stapledOCSPResponse); @@ -510,8 +616,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, pinningDisabled, MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff, - AcceptAllAlgorithms, SHA1Mode::Allowed, - nullptr, nullptr, builtChain); + SHA1Mode::Allowed, builtChain, + nullptr, nullptr); rv = BuildCertChain(objectSigningTrust, certDER, time, endEntityOrCA, keyUsage, eku, CertPolicyId::anyPolicy, stapledOCSPResponse); @@ -539,13 +645,13 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert, Time time, /*optional*/ void* pinarg, const char* hostname, - bool saveIntermediatesInPermanentDatabase, - Flags flags, - /*optional out*/ ScopedCERTCertList* builtChain, + /*out*/ ScopedCERTCertList& builtChain, + /*optional*/ bool saveIntermediatesInPermanentDatabase, + /*optional*/ Flags flags, /*optional out*/ SECOidTag* evOidPolicy, /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus, /*optional out*/ KeySizeStatus* keySizeStatus, - /*optional out*/ SignatureDigestStatus* sigDigestStatus, + /*optional out*/ SHA1ModeResult* sha1ModeResult, /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo) { PR_ASSERT(peerCert); @@ -553,9 +659,6 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert, PR_ASSERT(hostname); PR_ASSERT(hostname[0]); - if (builtChain) { - *builtChain = nullptr; - } if (evOidPolicy) { *evOidPolicy = SEC_OID_UNKNOWN; } @@ -565,14 +668,12 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert, return SECFailure; } - ScopedCERTCertList builtChainTemp; // CreateCertErrorRunnable assumes that CheckCertHostname is only called // if VerifyCert succeeded. SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg, - hostname, flags, stapledOCSPResponse, - &builtChainTemp, evOidPolicy, ocspStaplingStatus, - keySizeStatus, sigDigestStatus, - pinningTelemetryInfo); + hostname, builtChain, flags, stapledOCSPResponse, + evOidPolicy, ocspStaplingStatus, keySizeStatus, + sha1ModeResult, pinningTelemetryInfo); if (rv != SECSuccess) { return rv; } @@ -625,11 +726,7 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert, } if (saveIntermediatesInPermanentDatabase) { - SaveIntermediateCerts(builtChainTemp); - } - - if (builtChain) { - *builtChain = builtChainTemp.forget(); + SaveIntermediateCerts(builtChain); } return SECSuccess; diff --git a/security/certverifier/CertVerifier.h b/security/certverifier/CertVerifier.h index 98b2abc221..8edb1f7422 100644 --- a/security/certverifier/CertVerifier.h +++ b/security/certverifier/CertVerifier.h @@ -22,14 +22,14 @@ enum class KeySizeStatus { AlreadyBad = 3, }; -// These values correspond to the CERT_CHAIN_SIGNATURE_DIGEST telemetry. -enum class SignatureDigestStatus { +// These values correspond to the CERT_CHAIN_SHA1_POLICY_STATUS telemetry. +enum class SHA1ModeResult { NeverChecked = 0, - GoodAlgorithmsOnly = 1, - WeakEECert = 2, - WeakCACert = 3, - WeakCAAndEE = 4, - AlreadyBad = 5, + SucceededWithoutSHA1 = 1, + SucceededWithSHA1Before2016 = 2, + SucceededWithImportedRoot = 3, + SucceededWithSHA1 = 4, + Failed = 5, }; class PinningTelemetryInfo @@ -73,13 +73,13 @@ public: mozilla::pkix::Time time, void* pinArg, const char* hostname, + /*out*/ ScopedCERTCertList& builtChain, Flags flags = 0, /*optional in*/ const SECItem* stapledOCSPResponse = nullptr, - /*optional out*/ ScopedCERTCertList* builtChain = nullptr, /*optional out*/ SECOidTag* evOidPolicy = nullptr, /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr, /*optional out*/ KeySizeStatus* keySizeStatus = nullptr, - /*optional out*/ SignatureDigestStatus* sigDigestStatus = nullptr, + /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr, /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr); SECStatus VerifySSLServerCert( @@ -88,13 +88,13 @@ public: mozilla::pkix::Time time, /*optional*/ void* pinarg, const char* hostname, - bool saveIntermediatesInPermanentDatabase = false, - Flags flags = 0, - /*optional out*/ ScopedCERTCertList* builtChain = nullptr, + /*out*/ ScopedCERTCertList& builtChain, + /*optional*/ bool saveIntermediatesInPermanentDatabase = false, + /*optional*/ Flags flags = 0, /*optional out*/ SECOidTag* evOidPolicy = nullptr, /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr, /*optional out*/ KeySizeStatus* keySizeStatus = nullptr, - /*optional out*/ SignatureDigestStatus* sigDigestStatus = nullptr, + /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr, /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr); enum PinningMode { @@ -107,7 +107,8 @@ public: enum class SHA1Mode { Allowed = 0, Forbidden = 1, - OnlyBefore2016 = 2 + Before2016 = 2, + ImportedRoot = 3, }; enum OcspDownloadConfig { @@ -134,10 +135,16 @@ public: private: OCSPCache mOCSPCache; + + // Returns true if the configured SHA1 mode is more restrictive than the given + // mode. SHA1Mode::Forbidden is more restrictive than any other mode except + // Forbidden. Next is Before2016, then ImportedRoot, then Allowed. + // (A mode is never more restrictive than itself.) + bool SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode); }; void InitCertVerifierLog(); -SECStatus IsCertBuiltInRoot(CERTCertificate* cert, bool& result); +mozilla::pkix::Result IsCertBuiltInRoot(CERTCertificate* cert, bool& result); mozilla::pkix::Result CertListContainsExpectedKeys( const CERTCertList* certList, const char* hostname, mozilla::pkix::Time time, CertVerifier::PinningMode pinningMode); diff --git a/security/certverifier/ExtendedValidation.cpp b/security/certverifier/ExtendedValidation.cpp index 205968c7af..a65e43b2a4 100644 --- a/security/certverifier/ExtendedValidation.cpp +++ b/security/certverifier/ExtendedValidation.cpp @@ -16,7 +16,7 @@ #include "prerror.h" #include "prinit.h" -extern PRLogModuleInfo* gPIPNSSLog; +extern mozilla::LazyLogModule gPIPNSSLog; #define CONST_OID static const unsigned char #define OI(x) { siDEROID, (unsigned char*) x, sizeof x } diff --git a/security/certverifier/NSSCertDBTrustDomain.cpp b/security/certverifier/NSSCertDBTrustDomain.cpp index 80359513dd..d3cfd81355 100644 --- a/security/certverifier/NSSCertDBTrustDomain.cpp +++ b/security/certverifier/NSSCertDBTrustDomain.cpp @@ -34,7 +34,7 @@ using namespace mozilla; using namespace mozilla::pkix; -extern PRLogModuleInfo* gCertVerifierLog; +extern LazyLogModule gCertVerifierLog; static const uint64_t ServerFailureDelaySeconds = 5 * 60; @@ -51,11 +51,10 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType, CertVerifier::PinningMode pinningMode, unsigned int minRSABits, ValidityCheckingMode validityCheckingMode, - SignatureDigestOption signatureDigestOption, CertVerifier::SHA1Mode sha1Mode, + ScopedCERTCertList& builtChain, /*optional*/ PinningTelemetryInfo* pinningTelemetryInfo, - /*optional*/ const char* hostname, - /*optional*/ ScopedCERTCertList* builtChain) + /*optional*/ const char* hostname) : mCertDBTrustType(certDBTrustType) , mOCSPFetching(ocspFetching) , mOCSPCache(ocspCache) @@ -65,11 +64,10 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType, , mPinningMode(pinningMode) , mMinRSABits(minRSABits) , mValidityCheckingMode(validityCheckingMode) - , mSignatureDigestOption(signatureDigestOption) , mSHA1Mode(sha1Mode) + , mBuiltChain(builtChain) , mPinningTelemetryInfo(pinningTelemetryInfo) , mHostname(hostname) - , mBuiltChain(builtChain) , mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID)) , mOCSPStaplingStatus(CertVerifier::OCSP_STAPLING_NEVER_CHECKED) { @@ -783,9 +781,9 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time) } bool isBuiltInRoot = false; - srv = IsCertBuiltInRoot(root, isBuiltInRoot); - if (srv != SECSuccess) { - return MapPRErrorCodeToResult(PR_GetError()); + Result rv = IsCertBuiltInRoot(root, isBuiltInRoot); + if (rv != Success) { + return rv; } bool skipPinningChecksBecauseOfMITMMode = (!isBuiltInRoot && mPinningMode == CertVerifier::pinningAllowUserCAMITM); @@ -807,9 +805,7 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time) } } - if (mBuiltChain) { - *mBuiltChain = certList.forget(); - } + mBuiltChain = certList.forget(); return Success; } @@ -825,40 +821,25 @@ NSSCertDBTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm aAlg, MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("NSSCertDBTrustDomain: CheckSignatureDigestAlgorithm")); if (aAlg == DigestAlgorithm::sha1) { - // First check based on SHA1Mode switch (mSHA1Mode) { case CertVerifier::SHA1Mode::Forbidden: MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("SHA-1 certificate rejected")); return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; - case CertVerifier::SHA1Mode::OnlyBefore2016: + case CertVerifier::SHA1Mode::Before2016: if (JANUARY_FIRST_2016 <= notBefore) { MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Post-2015 SHA-1 certificate rejected")); return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; } break; case CertVerifier::SHA1Mode::Allowed: + // Enforcing that the resulting chain uses an imported root is only + // possible at a higher level. This is done in CertVerifier::VerifyCert. + case CertVerifier::SHA1Mode::ImportedRoot: default: break; } - - // Then check the signatureDigestOption values - if (mSignatureDigestOption == DisableSHA1Everywhere) { - MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("SHA-1 certificate rejected")); - return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; - } - - if (endEntityOrCA == EndEntityOrCA::MustBeCA) { - MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("CA cert is SHA-1")); - return mSignatureDigestOption == DisableSHA1ForCA - ? Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED - : Success; - } else { - MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("EE cert is SHA-1")); - return mSignatureDigestOption == DisableSHA1ForEE - ? Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED - : Success; - } } + return Success; } @@ -1042,7 +1023,7 @@ LoadLoadableRoots(/*optional*/ const char* dir, const char* modNameUTF8) return SECFailure; } - ScopedSECMODModule rootsModule(SECMOD_LoadUserModule(pkcs11ModuleSpec.get(), + UniqueSECMODModule rootsModule(SECMOD_LoadUserModule(pkcs11ModuleSpec.get(), nullptr, false)); if (!rootsModule) { return SECFailure; @@ -1060,7 +1041,7 @@ void UnloadLoadableRoots(const char* modNameUTF8) { PR_ASSERT(modNameUTF8); - ScopedSECMODModule rootsModule(SECMOD_FindModule(modNameUTF8)); + UniqueSECMODModule rootsModule(SECMOD_FindModule(modNameUTF8)); if (rootsModule) { SECMOD_UnloadUserModule(rootsModule.get()); diff --git a/security/certverifier/NSSCertDBTrustDomain.h b/security/certverifier/NSSCertDBTrustDomain.h index 831ef17cab..298f6de78e 100644 --- a/security/certverifier/NSSCertDBTrustDomain.h +++ b/security/certverifier/NSSCertDBTrustDomain.h @@ -41,13 +41,6 @@ char* DefaultServerNicknameForCert(CERTCertificate* cert); void SaveIntermediateCerts(const ScopedCERTCertList& certList); -enum SignatureDigestOption { - AcceptAllAlgorithms, - DisableSHA1ForEE, - DisableSHA1ForCA, - DisableSHA1Everywhere, -}; - class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain { @@ -69,11 +62,10 @@ public: CertVerifier::PinningMode pinningMode, unsigned int minRSABits, ValidityCheckingMode validityCheckingMode, - SignatureDigestOption signatureDigestOption, CertVerifier::SHA1Mode sha1Mode, + ScopedCERTCertList& builtChain, /*optional*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr, - /*optional*/ const char* hostname = nullptr, - /*optional out*/ ScopedCERTCertList* builtChain = nullptr); + /*optional*/ const char* hostname = nullptr); virtual Result FindIssuer(mozilla::pkix::Input encodedIssuerName, IssuerChecker& checker, @@ -156,11 +148,10 @@ private: CertVerifier::PinningMode mPinningMode; const unsigned int mMinRSABits; ValidityCheckingMode mValidityCheckingMode; - SignatureDigestOption mSignatureDigestOption; CertVerifier::SHA1Mode mSHA1Mode; + ScopedCERTCertList& mBuiltChain; // non-owning PinningTelemetryInfo* mPinningTelemetryInfo; const char* mHostname; // non-owning - only used for pinning checks - ScopedCERTCertList* mBuiltChain; // non-owning nsCOMPtr mCertBlocklist; CertVerifier::OCSPStaplingStatus mOCSPStaplingStatus; }; diff --git a/security/certverifier/OCSPCache.cpp b/security/certverifier/OCSPCache.cpp index 29796bc61d..3999e00cc6 100644 --- a/security/certverifier/OCSPCache.cpp +++ b/security/certverifier/OCSPCache.cpp @@ -32,7 +32,7 @@ #include "ScopedNSSTypes.h" #include "secerr.h" -extern PRLogModuleInfo* gCertVerifierLog; +extern mozilla::LazyLogModule gCertVerifierLog; using namespace mozilla::pkix; diff --git a/security/certverifier/OCSPRequestor.cpp b/security/certverifier/OCSPRequestor.cpp index c750447e62..8ac370aaed 100644 --- a/security/certverifier/OCSPRequestor.cpp +++ b/security/certverifier/OCSPRequestor.cpp @@ -16,7 +16,7 @@ #include "nsServiceManagerUtils.h" #include "secerr.h" -extern PRLogModuleInfo* gCertVerifierLog; +extern mozilla::LazyLogModule gCertVerifierLog; namespace mozilla { diff --git a/security/manager/.eslintrc b/security/manager/.eslintrc.json similarity index 62% rename from security/manager/.eslintrc rename to security/manager/.eslintrc.json index fdb997bcaa..5bf8c26970 100644 --- a/security/manager/.eslintrc +++ b/security/manager/.eslintrc.json @@ -6,12 +6,24 @@ // Require spacing around => "arrow-spacing": 2, + // Always require spacing around a single line block + "block-spacing": 2, + + // No space before always a space after a comma + "comma-spacing": [2, {"before": false, "after": true}], + // Commas at the end of the line not the start "comma-style": 2, + // Don't require spaces around computed properties + "computed-property-spacing": [2, "never"], + // Functions must always return something or nothing "consistent-return": 2, + // Require braces around blocks that start a new line + "curly": [2, "multi-line"], + // Always require a trailing EOL "eol-last": 2, @@ -27,6 +39,12 @@ // Always require parenthesis for new calls "new-parens": 2, + // Use [] instead of Array() + "no-array-constructor": 2, + + // Disallow use of debugger + "no-debugger": 2, + // No duplicate arguments in function declarations "no-dupe-args": 2, @@ -39,6 +57,9 @@ // No labels "no-labels": 2, + // If an if block ends with a return no need for an else block + "no-else-return": 2, + // No empty character classes in regex "no-empty-character-class": 2, @@ -63,21 +84,41 @@ // No odd whitespace characters "no-irregular-whitespace": 2, + // No single if block inside an else block + "no-lonely-if": 2, + // No mixing spaces and tabs in indent "no-mixed-spaces-and-tabs": [2, "smart-tabs"], + // No unnecessary spacing + "no-multi-spaces": [2, { "exceptions": { + "AssignmentExpression": true, + "VariableDeclarator": true, + "ArrayExpression": true, + "ObjectExpression": true + }}], + // No reassigning native JS objects "no-native-reassign": 2, // No (!foo in bar) "no-negated-in-lhs": 2, + // Nested ternary statements are confusing + "no-nested-ternary": 2, + // Use {} instead of new Object() "no-new-object": 2, // No Math() or JSON() "no-obj-calls": 2, + // No octal literals + "no-octal": 2, + + // No redeclaring variables + "no-redeclare": 2, + // No unnecessary comparisons "no-self-compare": 2, @@ -87,6 +128,16 @@ // No spaces between function name and parentheses "no-spaced-func": 2, + // Disallow throwing literals (eg. |throw "error"| instead of + // |throw new Error("error")|) + "no-throw-literal": 2, + + // No trailing whitespace + "no-trailing-spaces": 2, + + // No using undeclared variables + "no-undef": 2, + // Error on newline where a semicolon is needed "no-unexpected-multiline": 2, @@ -99,16 +150,28 @@ // No using with "no-with": 2, + // Always require semicolon at end of statement + "semi": [2, "always"], + + // Require space after keywords + // Note: Replaced by keyword-spacing in ESLint v2.0. + "space-after-keywords": 2, + // Require space before blocks "space-before-blocks": 2, // Require spaces before finally, catch, etc. + // Note: Replaced by keyword-spacing in ESLint v2.0. "space-before-keywords": [2, "always"], // No space padding in parentheses "space-in-parens": [2, "never"], + // Require spaces around operators + "space-infix-ops": 2, + // Require spaces after return, throw and case + // Note: Replaced by keyword-spacing in ESLint v2.0. "space-return-throw-case": 2, // ++ and -- should not need spacing @@ -118,6 +181,13 @@ "use-isnan": 2, // Only check typeof against valid results - "valid-typeof": 2, + "valid-typeof": 2 + }, + "env": { + "browser": true + }, + "globals": { + "Components": false, + "dump": false } } diff --git a/security/manager/locales/en-US/chrome/pippki/certManager.dtd b/security/manager/locales/en-US/chrome/pippki/certManager.dtd index 35b1f10cc1..6ad47bf7ee 100644 --- a/security/manager/locales/en-US/chrome/pippki/certManager.dtd +++ b/security/manager/locales/en-US/chrome/pippki/certManager.dtd @@ -39,10 +39,6 @@ - - - - @@ -61,8 +57,6 @@ - - diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 33505e36ae..67232999f9 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -12,11 +12,6 @@ unnamedCA=Certificate Authority (unnamed) #For editing cert trust editTrustCA=The certificate "%S" represents a Certificate Authority. -editTrustEmail=The certificate "%S" was issued by: -issuerNotTrusted=Because you do not trust the certificate authority that issued this certificate, you do not trust the authenticity of this certificate unless otherwise indicated here. -issuerTrusted=Because you trust the certificate authority that issued this certificate, you trust the authenticity of this certificate unless otherwise indicated here. -issuerNotKnown=Because you do not know the certificate authority that issued this certificate, you do not trust the authenticity of this certificate unless otherwise indicated here. -issuerCertNotFound=Certificate for this certificate authority was not found #For Deleting Certificates deleteSslCertConfirm3=Are you sure you want to delete these server exceptions? @@ -114,10 +109,9 @@ unable_to_toggle_fips=Unable to change the FIPS mode for the security device. It resetPasswordConfirmationTitle=Reset Master Password resetPasswordConfirmationMessage=Your password has been reset. -#Import certificate(s) file dialog +# Import certificate(s) file dialog importEmailCertPrompt=Select File containing somebody's Email certificate to import importCACertsPrompt=Select File containing CA certificate(s) to import -importServerCertPrompt=Select File containing Server certificate to import file_browse_Certificate_spec=Certificate Files # Cert export diff --git a/security/manager/pki/resources/content/OthersOverlay.xul b/security/manager/pki/resources/content/OthersOverlay.xul index ec1291e5ed..0f51542773 100644 --- a/security/manager/pki/resources/content/OthersOverlay.xul +++ b/security/manager/pki/resources/content/OthersOverlay.xul @@ -29,7 +29,7 @@ - + @@ -37,10 +37,6 @@ label="&certmgr.view2.label;" accesskey="&certmgr.view2.accesskey;" disabled="true" oncommand="viewCerts();"/> -