From d9c487dfd1b3e249fdbf3a094f625357907c6d77 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 7 Jun 2020 18:58:28 -0400 Subject: [PATCH 1/7] Issue #1580 - Add missing MP3Demuxer.h to MediaDecoderReader.h Follow up for dom/media work on Issue #80. Fixes non-optimized build bustage. --- dom/media/MediaDecoderReader.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index f53c74689f..a31687be87 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -17,6 +17,7 @@ #include "MediaMetadataManager.h" #include "MediaQueue.h" #include "MediaTimer.h" +#include "MP3Demuxer.h" #include "AudioCompactor.h" #include "Intervals.h" #include "TimeUnits.h" From fa84efcf6d7d6f37e4791dfbc4c612312553c76a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 8 Jun 2020 18:07:02 +0000 Subject: [PATCH 2/7] [NSS] Update exported symbols Some symbols were missing from export which might lead to build bustage. --- config/external/nss/nss.symbols | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/external/nss/nss.symbols b/config/external/nss/nss.symbols index 705af4a94a..83f5dc524c 100644 --- a/config/external/nss/nss.symbols +++ b/config/external/nss/nss.symbols @@ -112,6 +112,7 @@ CERT_GetCertChainFromCert CERT_GetCertEmailAddress CERT_GetCertificateDer CERT_GetCertificateRequestExtensions +CERT_GetCertKeyType CERT_GetCertTimes CERT_GetCertTrust CERT_GetCommonName @@ -270,6 +271,7 @@ NSS_Init NSS_Initialize NSS_InitWithMerge NSS_IsInitialized +NSS_OptionGet NSS_OptionSet NSS_NoDB_Init NSS_SecureMemcmp @@ -383,6 +385,7 @@ PK11_GetNextSymKey PK11_GetPadMechanism PK11_GetPrivateKeyNickname PK11_GetPrivateModulusLen +PK11_GetSlotFromPrivateKey PK11_GetSlotID PK11_GetSlotInfo PK11_GetSlotName From 594c930eca6ed025ca8d9efffb322ed025db6a42 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 8 Jun 2020 18:12:08 +0000 Subject: [PATCH 3/7] Issue #439 - Remove, fix and clean up automated tests With the big amount of code churn around DOM a lot of tests broke severely enough that they caused build bustage. This commit cleans up, removes or otherwise fixes tests that are broken, no longer relevant or obsolete. --- dom/base/test/chrome/chrome.ini | 2 - dom/base/test/mochitest.ini | 2 - dom/bindings/moz.build | 29 - dom/bindings/test/Makefile.in | 21 - dom/bindings/test/TestBindingHeader.h | 1464 ---------------- dom/bindings/test/TestCImplementedInterface.h | 43 - dom/bindings/test/TestCodeGen.webidl | 1281 -------------- dom/bindings/test/TestDictionary.webidl | 9 - dom/bindings/test/TestExampleGen.webidl | 815 --------- dom/bindings/test/TestFunctions.cpp | 94 -- dom/bindings/test/TestFunctions.h | 52 - .../test/TestInterfaceIterableDouble.cpp | 82 - .../test/TestInterfaceIterableDouble.h | 51 - .../test/TestInterfaceIterableDoubleUnion.cpp | 83 - .../test/TestInterfaceIterableDoubleUnion.h | 51 - .../test/TestInterfaceIterableSingle.cpp | 77 - .../test/TestInterfaceIterableSingle.h | 51 - dom/bindings/test/TestInterfaceJS.js | 166 -- dom/bindings/test/TestInterfaceJS.manifest | 4 - dom/bindings/test/TestInterfaceJSMaplike.js | 38 - dom/bindings/test/TestInterfaceMaplike.cpp | 84 - dom/bindings/test/TestInterfaceMaplike.h | 52 - .../test/TestInterfaceMaplikeObject.cpp | 88 - .../test/TestInterfaceMaplikeObject.h | 52 - dom/bindings/test/TestInterfaceSetlike.cpp | 58 - dom/bindings/test/TestInterfaceSetlike.h | 46 - .../test/TestInterfaceSetlikeNode.cpp | 58 - dom/bindings/test/TestInterfaceSetlikeNode.h | 46 - dom/bindings/test/TestJSImplGen.webidl | 840 ---------- .../test/TestJSImplInheritanceGen.webidl | 29 - dom/bindings/test/TestTypedef.webidl | 7 - dom/bindings/test/chrome.ini | 22 - dom/bindings/test/file_InstanceOf.html | 12 - dom/bindings/test/file_bug775543.html | 5 - .../file_document_location_set_via_xray.html | 5 - dom/bindings/test/file_dom_xrays.html | 24 - dom/bindings/test/file_focuser.html | 24 - .../test/file_fullScreenPropertyAccessor.html | 24 - dom/bindings/test/file_proxies_via_xray.html | 8 - dom/bindings/test/forOf_iframe.html | 13 - dom/bindings/test/mochitest.ini | 79 - dom/bindings/test/moz.build | 58 - dom/bindings/test/test_ByteString.html | 32 - dom/bindings/test/test_InstanceOf.html | 54 - .../test/test_Object.prototype_props.html | 20 - dom/bindings/test/test_async_stacks.html | 108 -- .../test/test_barewordGetsWindow.html | 60 - ...test_blacklisted_prerendering_function.xul | 124 -- dom/bindings/test/test_bug1036214.html | 123 -- dom/bindings/test/test_bug1041646.html | 49 - .../test/test_bug1123516_maplikesetlike.html | 271 --- .../test_bug1123516_maplikesetlikechrome.xul | 68 - dom/bindings/test/test_bug1123875.html | 14 - dom/bindings/test/test_bug1287912.html | 37 - dom/bindings/test/test_bug560072.html | 34 - dom/bindings/test/test_bug742191.html | 36 - dom/bindings/test/test_bug759621.html | 29 - dom/bindings/test/test_bug773326.html | 11 - dom/bindings/test/test_bug775543.html | 37 - dom/bindings/test/test_bug788369.html | 30 - dom/bindings/test/test_bug852846.html | 34 - dom/bindings/test/test_bug862092.html | 37 - dom/bindings/test/test_bug963382.html | 43 - .../test_callback_across_document_open.html | 21 - .../test/test_callback_default_thisval.html | 36 - .../test/test_callback_exceptions.html | 17 - .../test/test_cloneAndImportNode.html | 48 - .../test_crossOriginWindowSymbolAccess.html | 23 - dom/bindings/test/test_defineProperty.html | 157 -- .../test_document_location_set_via_xray.html | 49 - ...est_document_location_via_xray_cached.html | 36 - .../test/test_domProxyArrayLengthGetter.html | 28 - dom/bindings/test/test_dom_xrays.html | 231 --- dom/bindings/test/test_enums.html | 15 - .../test/test_exceptionSanitization.html | 45 - dom/bindings/test/test_exceptionThrowing.html | 56 - .../test/test_exception_messages.html | 82 - ..._exception_options_from_jsimplemented.html | 166 -- .../test_exceptions_from_jsimplemented.html | 56 - dom/bindings/test/test_forOf.html | 86 - dom/bindings/test/test_integers.html | 50 - dom/bindings/test/test_interfaceName.html | 28 - dom/bindings/test/test_interfaceToString.html | 47 - dom/bindings/test/test_iterable.html | 241 --- .../test/test_jsimplemented_eventhandler.html | 47 - ...t_kill_longrunning_prerendered_content.xul | 85 - dom/bindings/test/test_lenientThis.html | 27 - dom/bindings/test/test_lookupGetter.html | 49 - dom/bindings/test/test_namedNoIndexed.html | 36 - .../test/test_named_getter_enumerability.html | 40 - dom/bindings/test/test_oom_reporting.html | 42 - dom/bindings/test/test_primitive_this.html | 45 - ...promise_rejections_from_jsimplemented.html | 143 -- dom/bindings/test/test_proxies_via_xray.html | 99 -- dom/bindings/test/test_queryInterface.html | 41 - dom/bindings/test/test_returnUnion.html | 59 - .../test/test_sequence_detection.html | 53 - dom/bindings/test/test_sequence_wrapping.html | 59 - .../test_setWithNamedGetterNoNamedSetter.html | 40 - dom/bindings/test/test_stringBindings.html | 59 - .../test/test_throwing_method_noDCE.html | 27 - dom/bindings/test/test_traceProtos.html | 37 - .../test/test_treat_non_object_as_null.html | 39 - .../test/test_unforgeablesonexpando.html | 18 - dom/bindings/test/test_usvstring.html | 41 - dom/bindings/test/test_worker_UnwrapArg.html | 58 - dom/media/gtest/moz.build | 5 - .../webaudio/gtest/TestAudioEventTimeline.cpp | 11 - dom/plugins/test/mochitest/mochitest.ini | 1 - .../mochitest/webcomponents/mochitest.ini | 5 - image/moz.build | 2 - image/test/gtest/Common.cpp | 673 -------- image/test/gtest/Common.h | 419 ----- .../gtest/TestADAM7InterpolatingFilter.cpp | 671 -------- image/test/gtest/TestCopyOnWrite.cpp | 235 --- image/test/gtest/TestDecodeToSurface.cpp | 123 -- image/test/gtest/TestDecoders.cpp | 669 -------- image/test/gtest/TestDeinterlacingFilter.cpp | 672 -------- image/test/gtest/TestDownscalingFilter.cpp | 231 --- .../gtest/TestDownscalingFilterNoSkia.cpp | 57 - image/test/gtest/TestLoader.cpp | 84 - image/test/gtest/TestMetadata.cpp | 255 --- .../test/gtest/TestRemoveFrameRectFilter.cpp | 327 ---- image/test/gtest/TestSourceBuffer.cpp | 810 --------- image/test/gtest/TestStreamingLexer.cpp | 973 ----------- .../test/gtest/TestSurfacePipeIntegration.cpp | 508 ------ image/test/gtest/TestSurfaceSink.cpp | 1491 ----------------- .../animated-with-extra-image-sub-blocks.gif | Bin 434 -> 0 bytes .../gtest/corrupt-with-bad-bmp-height.ico | Bin 41663 -> 0 bytes .../test/gtest/corrupt-with-bad-bmp-width.ico | Bin 41663 -> 0 bytes image/test/gtest/corrupt.jpg | Bin 2477 -> 0 bytes image/test/gtest/downscaled.bmp | Bin 30138 -> 0 bytes image/test/gtest/downscaled.gif | Bin 223 -> 0 bytes image/test/gtest/downscaled.ico | Bin 41662 -> 0 bytes image/test/gtest/downscaled.icon | Bin 40003 -> 0 bytes image/test/gtest/downscaled.jpg | Bin 6035 -> 0 bytes image/test/gtest/downscaled.png | Bin 1015 -> 0 bytes image/test/gtest/first-frame-green.gif | Bin 317 -> 0 bytes image/test/gtest/first-frame-green.png | Bin 364 -> 0 bytes image/test/gtest/first-frame-padding.gif | Bin 49 -> 0 bytes image/test/gtest/green-1x1-truncated.gif | Bin 53 -> 0 bytes image/test/gtest/green.bmp | Bin 30138 -> 0 bytes image/test/gtest/green.gif | Bin 156 -> 0 bytes image/test/gtest/green.ico | Bin 41662 -> 0 bytes image/test/gtest/green.icon | Bin 40002 -> 0 bytes image/test/gtest/green.jpg | Bin 361 -> 0 bytes image/test/gtest/green.png | Bin 255 -> 0 bytes .../test/gtest/invalid-truncated-metadata.bmp | Bin 54 -> 0 bytes image/test/gtest/moz.build | 79 - image/test/gtest/no-frame-delay.gif | Bin 317 -> 0 bytes image/test/gtest/rle4.bmp | Bin 3686 -> 0 bytes image/test/gtest/rle8.bmp | Bin 1288 -> 0 bytes .../gtest/transparent-ico-with-and-mask.ico | Bin 3262 -> 0 bytes .../test/gtest/transparent-if-within-ico.bmp | Bin 4234 -> 0 bytes image/test/gtest/transparent.gif | Bin 355 -> 0 bytes image/test/gtest/transparent.png | Bin 419 -> 0 bytes security/manager/ssl/tests/unit/moz.build | 1 - toolkit/mozapps/update/updater/moz.build | 2 - .../updater/updater-xpcshell/Makefile.in | 41 - .../update/updater/updater-xpcshell/moz.build | 14 - 160 files changed, 18321 deletions(-) delete mode 100644 dom/bindings/test/Makefile.in delete mode 100644 dom/bindings/test/TestBindingHeader.h delete mode 100644 dom/bindings/test/TestCImplementedInterface.h delete mode 100644 dom/bindings/test/TestCodeGen.webidl delete mode 100644 dom/bindings/test/TestDictionary.webidl delete mode 100644 dom/bindings/test/TestExampleGen.webidl delete mode 100644 dom/bindings/test/TestFunctions.cpp delete mode 100644 dom/bindings/test/TestFunctions.h delete mode 100644 dom/bindings/test/TestInterfaceIterableDouble.cpp delete mode 100644 dom/bindings/test/TestInterfaceIterableDouble.h delete mode 100644 dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp delete mode 100644 dom/bindings/test/TestInterfaceIterableDoubleUnion.h delete mode 100644 dom/bindings/test/TestInterfaceIterableSingle.cpp delete mode 100644 dom/bindings/test/TestInterfaceIterableSingle.h delete mode 100644 dom/bindings/test/TestInterfaceJS.js delete mode 100644 dom/bindings/test/TestInterfaceJS.manifest delete mode 100644 dom/bindings/test/TestInterfaceJSMaplike.js delete mode 100644 dom/bindings/test/TestInterfaceMaplike.cpp delete mode 100644 dom/bindings/test/TestInterfaceMaplike.h delete mode 100644 dom/bindings/test/TestInterfaceMaplikeObject.cpp delete mode 100644 dom/bindings/test/TestInterfaceMaplikeObject.h delete mode 100644 dom/bindings/test/TestInterfaceSetlike.cpp delete mode 100644 dom/bindings/test/TestInterfaceSetlike.h delete mode 100644 dom/bindings/test/TestInterfaceSetlikeNode.cpp delete mode 100644 dom/bindings/test/TestInterfaceSetlikeNode.h delete mode 100644 dom/bindings/test/TestJSImplGen.webidl delete mode 100644 dom/bindings/test/TestJSImplInheritanceGen.webidl delete mode 100644 dom/bindings/test/TestTypedef.webidl delete mode 100644 dom/bindings/test/chrome.ini delete mode 100644 dom/bindings/test/file_InstanceOf.html delete mode 100644 dom/bindings/test/file_bug775543.html delete mode 100644 dom/bindings/test/file_document_location_set_via_xray.html delete mode 100644 dom/bindings/test/file_dom_xrays.html delete mode 100644 dom/bindings/test/file_focuser.html delete mode 100644 dom/bindings/test/file_fullScreenPropertyAccessor.html delete mode 100644 dom/bindings/test/file_proxies_via_xray.html delete mode 100644 dom/bindings/test/forOf_iframe.html delete mode 100644 dom/bindings/test/mochitest.ini delete mode 100644 dom/bindings/test/moz.build delete mode 100644 dom/bindings/test/test_ByteString.html delete mode 100644 dom/bindings/test/test_InstanceOf.html delete mode 100644 dom/bindings/test/test_Object.prototype_props.html delete mode 100644 dom/bindings/test/test_async_stacks.html delete mode 100644 dom/bindings/test/test_barewordGetsWindow.html delete mode 100644 dom/bindings/test/test_blacklisted_prerendering_function.xul delete mode 100644 dom/bindings/test/test_bug1036214.html delete mode 100644 dom/bindings/test/test_bug1041646.html delete mode 100644 dom/bindings/test/test_bug1123516_maplikesetlike.html delete mode 100644 dom/bindings/test/test_bug1123516_maplikesetlikechrome.xul delete mode 100644 dom/bindings/test/test_bug1123875.html delete mode 100644 dom/bindings/test/test_bug1287912.html delete mode 100644 dom/bindings/test/test_bug560072.html delete mode 100644 dom/bindings/test/test_bug742191.html delete mode 100644 dom/bindings/test/test_bug759621.html delete mode 100644 dom/bindings/test/test_bug773326.html delete mode 100644 dom/bindings/test/test_bug775543.html delete mode 100644 dom/bindings/test/test_bug788369.html delete mode 100644 dom/bindings/test/test_bug852846.html delete mode 100644 dom/bindings/test/test_bug862092.html delete mode 100644 dom/bindings/test/test_bug963382.html delete mode 100644 dom/bindings/test/test_callback_across_document_open.html delete mode 100644 dom/bindings/test/test_callback_default_thisval.html delete mode 100644 dom/bindings/test/test_callback_exceptions.html delete mode 100644 dom/bindings/test/test_cloneAndImportNode.html delete mode 100644 dom/bindings/test/test_crossOriginWindowSymbolAccess.html delete mode 100644 dom/bindings/test/test_defineProperty.html delete mode 100644 dom/bindings/test/test_document_location_set_via_xray.html delete mode 100644 dom/bindings/test/test_document_location_via_xray_cached.html delete mode 100644 dom/bindings/test/test_domProxyArrayLengthGetter.html delete mode 100644 dom/bindings/test/test_dom_xrays.html delete mode 100644 dom/bindings/test/test_enums.html delete mode 100644 dom/bindings/test/test_exceptionSanitization.html delete mode 100644 dom/bindings/test/test_exceptionThrowing.html delete mode 100644 dom/bindings/test/test_exception_messages.html delete mode 100644 dom/bindings/test/test_exception_options_from_jsimplemented.html delete mode 100644 dom/bindings/test/test_exceptions_from_jsimplemented.html delete mode 100644 dom/bindings/test/test_forOf.html delete mode 100644 dom/bindings/test/test_integers.html delete mode 100644 dom/bindings/test/test_interfaceName.html delete mode 100644 dom/bindings/test/test_interfaceToString.html delete mode 100644 dom/bindings/test/test_iterable.html delete mode 100644 dom/bindings/test/test_jsimplemented_eventhandler.html delete mode 100644 dom/bindings/test/test_kill_longrunning_prerendered_content.xul delete mode 100644 dom/bindings/test/test_lenientThis.html delete mode 100644 dom/bindings/test/test_lookupGetter.html delete mode 100644 dom/bindings/test/test_namedNoIndexed.html delete mode 100644 dom/bindings/test/test_named_getter_enumerability.html delete mode 100644 dom/bindings/test/test_oom_reporting.html delete mode 100644 dom/bindings/test/test_primitive_this.html delete mode 100644 dom/bindings/test/test_promise_rejections_from_jsimplemented.html delete mode 100644 dom/bindings/test/test_proxies_via_xray.html delete mode 100644 dom/bindings/test/test_queryInterface.html delete mode 100644 dom/bindings/test/test_returnUnion.html delete mode 100644 dom/bindings/test/test_sequence_detection.html delete mode 100644 dom/bindings/test/test_sequence_wrapping.html delete mode 100644 dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html delete mode 100644 dom/bindings/test/test_stringBindings.html delete mode 100644 dom/bindings/test/test_throwing_method_noDCE.html delete mode 100644 dom/bindings/test/test_traceProtos.html delete mode 100644 dom/bindings/test/test_treat_non_object_as_null.html delete mode 100644 dom/bindings/test/test_unforgeablesonexpando.html delete mode 100644 dom/bindings/test/test_usvstring.html delete mode 100644 dom/bindings/test/test_worker_UnwrapArg.html delete mode 100644 image/test/gtest/Common.cpp delete mode 100644 image/test/gtest/Common.h delete mode 100644 image/test/gtest/TestADAM7InterpolatingFilter.cpp delete mode 100644 image/test/gtest/TestCopyOnWrite.cpp delete mode 100644 image/test/gtest/TestDecodeToSurface.cpp delete mode 100644 image/test/gtest/TestDecoders.cpp delete mode 100644 image/test/gtest/TestDeinterlacingFilter.cpp delete mode 100644 image/test/gtest/TestDownscalingFilter.cpp delete mode 100644 image/test/gtest/TestDownscalingFilterNoSkia.cpp delete mode 100644 image/test/gtest/TestLoader.cpp delete mode 100644 image/test/gtest/TestMetadata.cpp delete mode 100644 image/test/gtest/TestRemoveFrameRectFilter.cpp delete mode 100644 image/test/gtest/TestSourceBuffer.cpp delete mode 100644 image/test/gtest/TestStreamingLexer.cpp delete mode 100644 image/test/gtest/TestSurfacePipeIntegration.cpp delete mode 100644 image/test/gtest/TestSurfaceSink.cpp delete mode 100644 image/test/gtest/animated-with-extra-image-sub-blocks.gif delete mode 100644 image/test/gtest/corrupt-with-bad-bmp-height.ico delete mode 100644 image/test/gtest/corrupt-with-bad-bmp-width.ico delete mode 100644 image/test/gtest/corrupt.jpg delete mode 100644 image/test/gtest/downscaled.bmp delete mode 100644 image/test/gtest/downscaled.gif delete mode 100644 image/test/gtest/downscaled.ico delete mode 100644 image/test/gtest/downscaled.icon delete mode 100644 image/test/gtest/downscaled.jpg delete mode 100644 image/test/gtest/downscaled.png delete mode 100644 image/test/gtest/first-frame-green.gif delete mode 100644 image/test/gtest/first-frame-green.png delete mode 100644 image/test/gtest/first-frame-padding.gif delete mode 100644 image/test/gtest/green-1x1-truncated.gif delete mode 100644 image/test/gtest/green.bmp delete mode 100644 image/test/gtest/green.gif delete mode 100644 image/test/gtest/green.ico delete mode 100644 image/test/gtest/green.icon delete mode 100644 image/test/gtest/green.jpg delete mode 100644 image/test/gtest/green.png delete mode 100644 image/test/gtest/invalid-truncated-metadata.bmp delete mode 100644 image/test/gtest/moz.build delete mode 100644 image/test/gtest/no-frame-delay.gif delete mode 100644 image/test/gtest/rle4.bmp delete mode 100644 image/test/gtest/rle8.bmp delete mode 100644 image/test/gtest/transparent-ico-with-and-mask.ico delete mode 100644 image/test/gtest/transparent-if-within-ico.bmp delete mode 100644 image/test/gtest/transparent.gif delete mode 100644 image/test/gtest/transparent.png delete mode 100644 toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in delete mode 100644 toolkit/mozapps/update/updater/updater-xpcshell/moz.build diff --git a/dom/base/test/chrome/chrome.ini b/dom/base/test/chrome/chrome.ini index c6ee423918..64b1c8454b 100644 --- a/dom/base/test/chrome/chrome.ini +++ b/dom/base/test/chrome/chrome.ini @@ -62,8 +62,6 @@ support-files = ../file_bug357450.js [test_bug1139964.xul] [test_bug1209621.xul] [test_cpows.xul] -[test_custom_element_content.xul] -[test_custom_element_ep.xul] [test_domparsing.xul] [test_fileconstructor.xul] [test_fileconstructor_tempfile.xul] diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 928727f81d..8183dab8be 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -630,7 +630,6 @@ skip-if = toolkit == 'android' #bug 904183 [test_document.all_unqualified.html] [test_document_constructor.html] [test_document_importNode_document.html] -[test_custom_element.html] [test_domcursor.html] [test_domparser_null_char.html] [test_domparsing.html] @@ -698,7 +697,6 @@ skip-if = (os != 'android') # meta-viewport tag support is mobile-only skip-if = toolkit == 'android' #TIMED_OUT [test_mozMatchesSelector.html] [test_mutationobserver_anonymous.html] -[test_mutationobservers.html] [test_named_frames.html] [test_navigator_hardwareConcurrency.html] [test_navigator_language.html] diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build index 649689c41c..fae0fd15a9 100644 --- a/dom/bindings/moz.build +++ b/dom/bindings/moz.build @@ -4,8 +4,6 @@ # 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/. -TEST_DIRS += ['test'] - XPIDL_SOURCES += [ 'nsIScriptError.idl' ] @@ -107,33 +105,6 @@ SOURCES += [ 'StructuredClone.cpp', ] -# Tests for maplike and setlike require bindings to be built, which means they -# must be included in libxul. This breaks the "no test classes are exported" -# rule stated in the test/ directory, but it's the only way this will work. -# Test classes are only built in debug mode, and all tests requiring use of -# them are only run in debug mode. -if CONFIG['MOZ_DEBUG']: - EXPORTS.mozilla.dom += [ - "test/TestFunctions.h", - "test/TestInterfaceIterableDouble.h", - "test/TestInterfaceIterableDoubleUnion.h", - "test/TestInterfaceIterableSingle.h", - "test/TestInterfaceMaplike.h", - "test/TestInterfaceMaplikeObject.h", - "test/TestInterfaceSetlike.h", - "test/TestInterfaceSetlikeNode.h" - ] - UNIFIED_SOURCES += [ - "test/TestFunctions.cpp", - "test/TestInterfaceIterableDouble.cpp", - "test/TestInterfaceIterableDoubleUnion.cpp", - "test/TestInterfaceIterableSingle.cpp", - "test/TestInterfaceMaplike.cpp", - "test/TestInterfaceMaplikeObject.cpp", - "test/TestInterfaceSetlike.cpp", - "test/TestInterfaceSetlikeNode.cpp", - ] - include('/ipc/chromium/chromium-config.mozbuild') if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']: diff --git a/dom/bindings/test/Makefile.in b/dom/bindings/test/Makefile.in deleted file mode 100644 index 844a51c270..0000000000 --- a/dom/bindings/test/Makefile.in +++ /dev/null @@ -1,21 +0,0 @@ -# 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/. - -ifdef COMPILE_ENVIRONMENT - -include ../webidlsrcs.mk - -# $(test_sources) comes from webidlsrcs.mk. -# TODO Update this variable in backend.mk. -CPPSRCS += $(addprefix ../,$(test_sources)) - -# Include rules.mk before any of our targets so our first target is coming from -# rules.mk and running make with no target in this dir does the right thing. -include $(topsrcdir)/config/rules.mk - -endif - -check:: - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h deleted file mode 100644 index 4e2e10e43e..0000000000 --- a/dom/bindings/test/TestBindingHeader.h +++ /dev/null @@ -1,1464 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#ifndef TestBindingHeader_h -#define TestBindingHeader_h - -#include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/Date.h" -#include "mozilla/dom/MozMap.h" -#include "mozilla/dom/TypedArray.h" -#include "mozilla/ErrorResult.h" -#include "nsCOMPtr.h" -#include "nsGenericHTMLElement.h" -#include "nsWrapperCache.h" - -// Forward declare this before we include TestCodeGenBinding.h, because that header relies on including -// this one for it, for ParentDict. Hopefully it won't begin to rely on it in more fundamental ways. -namespace mozilla { -namespace dom { -class DocGroup; -class TestExternalInterface; -class Promise; -} // namespace dom -} // namespace mozilla - -// We don't export TestCodeGenBinding.h, but it's right in our parent dir. -#include "../TestCodeGenBinding.h" - -extern bool TestFuncControlledMember(JSContext*, JSObject*); - -namespace mozilla { -namespace dom { - -// IID for nsRenamedInterface -#define NS_RENAMED_INTERFACE_IID \ -{ 0xd4b19ef3, 0xe68b, 0x4e3f, \ - { 0x94, 0xbc, 0xc9, 0xde, 0x3a, 0x69, 0xb0, 0xe8 } } - -class nsRenamedInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_RENAMED_INTERFACE_IID) - NS_DECL_ISUPPORTS - - // We need a GetParentObject and GetDocGroup to make binding codegen happy - virtual nsISupports* GetParentObject(); - DocGroup* GetDocGroup() const; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsRenamedInterface, NS_RENAMED_INTERFACE_IID) - -// IID for the IndirectlyImplementedInterface -#define NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID \ -{ 0xfed55b69, 0x7012, 0x4849, \ - { 0xaf, 0x56, 0x4b, 0xa9, 0xee, 0x41, 0x30, 0x89 } } - -class IndirectlyImplementedInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID) - NS_DECL_ISUPPORTS - - // We need a GetParentObject and GetDocGroup to make binding codegen happy - virtual nsISupports* GetParentObject(); - DocGroup* GetDocGroup() const; - - bool IndirectlyImplementedProperty(); - void IndirectlyImplementedProperty(bool); - void IndirectlyImplementedMethod(); -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(IndirectlyImplementedInterface, NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID) - -// IID for the TestExternalInterface -#define NS_TEST_EXTERNAL_INTERFACE_IID \ -{ 0xd5ba0c99, 0x9b1d, 0x4e71, \ - { 0x8a, 0x94, 0x56, 0x38, 0x6c, 0xa3, 0xda, 0x3d } } -class TestExternalInterface : public nsISupports -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_EXTERNAL_INTERFACE_IID) - NS_DECL_ISUPPORTS -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(TestExternalInterface, NS_TEST_EXTERNAL_INTERFACE_IID) - -class TestNonWrapperCacheInterface : public nsISupports -{ -public: - NS_DECL_ISUPPORTS - - bool WrapObject(JSContext* aCx, JS::Handle aGivenProto, JS::MutableHandle aReflector); -}; - -class OnlyForUseInConstructor : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); -}; - -class TestInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - // And now our actual WebIDL API - // Constructors - static - already_AddRefed - Constructor(const GlobalObject&, ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, const nsAString&, ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, uint32_t, const Nullable&, - ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, TestInterface*, ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, uint32_t, IndirectlyImplementedInterface&, ErrorResult&); - - static - already_AddRefed - Constructor(const GlobalObject&, Date&, ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, const ArrayBuffer&, ErrorResult&); - static - already_AddRefed - Constructor(const GlobalObject&, const Uint8Array&, ErrorResult&); - /* static - already_AddRefed - Constructor(const GlobalObject&, uint32_t, uint32_t, - const TestInterfaceOrOnlyForUseInConstructor&, ErrorResult&); - */ - - static - already_AddRefed Test(const GlobalObject&, ErrorResult&); - static - already_AddRefed Test(const GlobalObject&, const nsAString&, - ErrorResult&); - static - already_AddRefed Test(const GlobalObject&, const nsACString&, - ErrorResult&); - - static - already_AddRefed Test2(const GlobalObject&, - const DictForConstructor&, - JS::Handle, - JS::Handle, - JS::Handle, - const Sequence&, - JS::Handle, - const Optional >&, - const Optional >&, - ErrorResult&); - - static - already_AddRefed Test3(const GlobalObject&, - const LongOrAnyMozMap&, - ErrorResult&); - - // Integer types - int8_t ReadonlyByte(); - int8_t WritableByte(); - void SetWritableByte(int8_t); - void PassByte(int8_t); - int8_t ReceiveByte(); - void PassOptionalByte(const Optional&); - void PassOptionalByteBeforeRequired(const Optional&, int8_t); - void PassOptionalByteWithDefault(int8_t); - void PassOptionalByteWithDefaultBeforeRequired(int8_t, int8_t); - void PassNullableByte(const Nullable&); - void PassOptionalNullableByte(const Optional< Nullable >&); - void PassVariadicByte(const Sequence&); - int8_t CachedByte(); - int8_t CachedConstantByte(); - int8_t CachedWritableByte(); - void SetCachedWritableByte(int8_t); - int8_t SideEffectFreeByte(); - int8_t SetSideEffectFreeByte(int8_t); - int8_t DomDependentByte(); - int8_t SetDomDependentByte(int8_t); - int8_t ConstantByte(); - int8_t DeviceStateDependentByte(); - int8_t ReturnByteSideEffectFree(); - int8_t ReturnDOMDependentByte(); - int8_t ReturnConstantByte(); - int8_t ReturnDeviceStateDependentByte(); - - void UnsafePrerenderMethod(); - int32_t UnsafePrerenderWritable(); - void SetUnsafePrerenderWritable(int32_t); - int32_t UnsafePrerenderReadonly(); - int16_t ReadonlyShort(); - int16_t WritableShort(); - void SetWritableShort(int16_t); - void PassShort(int16_t); - int16_t ReceiveShort(); - void PassOptionalShort(const Optional&); - void PassOptionalShortWithDefault(int16_t); - - int32_t ReadonlyLong(); - int32_t WritableLong(); - void SetWritableLong(int32_t); - void PassLong(int32_t); - int16_t ReceiveLong(); - void PassOptionalLong(const Optional&); - void PassOptionalLongWithDefault(int32_t); - - int64_t ReadonlyLongLong(); - int64_t WritableLongLong(); - void SetWritableLongLong(int64_t); - void PassLongLong(int64_t); - int64_t ReceiveLongLong(); - void PassOptionalLongLong(const Optional&); - void PassOptionalLongLongWithDefault(int64_t); - - uint8_t ReadonlyOctet(); - uint8_t WritableOctet(); - void SetWritableOctet(uint8_t); - void PassOctet(uint8_t); - uint8_t ReceiveOctet(); - void PassOptionalOctet(const Optional&); - void PassOptionalOctetWithDefault(uint8_t); - - uint16_t ReadonlyUnsignedShort(); - uint16_t WritableUnsignedShort(); - void SetWritableUnsignedShort(uint16_t); - void PassUnsignedShort(uint16_t); - uint16_t ReceiveUnsignedShort(); - void PassOptionalUnsignedShort(const Optional&); - void PassOptionalUnsignedShortWithDefault(uint16_t); - - uint32_t ReadonlyUnsignedLong(); - uint32_t WritableUnsignedLong(); - void SetWritableUnsignedLong(uint32_t); - void PassUnsignedLong(uint32_t); - uint32_t ReceiveUnsignedLong(); - void PassOptionalUnsignedLong(const Optional&); - void PassOptionalUnsignedLongWithDefault(uint32_t); - - uint64_t ReadonlyUnsignedLongLong(); - uint64_t WritableUnsignedLongLong(); - void SetWritableUnsignedLongLong(uint64_t); - void PassUnsignedLongLong(uint64_t); - uint64_t ReceiveUnsignedLongLong(); - void PassOptionalUnsignedLongLong(const Optional&); - void PassOptionalUnsignedLongLongWithDefault(uint64_t); - - float WritableFloat() const; - void SetWritableFloat(float); - float WritableUnrestrictedFloat() const; - void SetWritableUnrestrictedFloat(float); - Nullable GetWritableNullableFloat() const; - void SetWritableNullableFloat(Nullable); - Nullable GetWritableNullableUnrestrictedFloat() const; - void SetWritableNullableUnrestrictedFloat(Nullable); - double WritableDouble() const; - void SetWritableDouble(double); - double WritableUnrestrictedDouble() const; - void SetWritableUnrestrictedDouble(double); - Nullable GetWritableNullableDouble() const; - void SetWritableNullableDouble(Nullable); - Nullable GetWritableNullableUnrestrictedDouble() const; - void SetWritableNullableUnrestrictedDouble(Nullable); - void PassFloat(float, float, Nullable, Nullable, - double, double, Nullable, Nullable, - const Sequence&, const Sequence&, - const Sequence >&, - const Sequence >&, - const Sequence&, const Sequence&, - const Sequence >&, - const Sequence >&); - void PassLenientFloat(float, float, Nullable, Nullable, - double, double, Nullable, Nullable, - const Sequence&, const Sequence&, - const Sequence >&, - const Sequence >&, - const Sequence&, const Sequence&, - const Sequence >&, - const Sequence >&); - float LenientFloatAttr() const; - void SetLenientFloatAttr(float); - double LenientDoubleAttr() const; - void SetLenientDoubleAttr(double); - - void PassUnrestricted(float arg1, - float arg2, - float arg3, - float arg4, - double arg5, - double arg6, - double arg7, - double arg8); - - // Interface types - already_AddRefed ReceiveSelf(); - already_AddRefed ReceiveNullableSelf(); - TestInterface* ReceiveWeakSelf(); - TestInterface* ReceiveWeakNullableSelf(); - void PassSelf(TestInterface&); - void PassNullableSelf(TestInterface*); - already_AddRefed NonNullSelf(); - void SetNonNullSelf(TestInterface&); - already_AddRefed GetNullableSelf(); - already_AddRefed CachedSelf(); - void SetNullableSelf(TestInterface*); - void PassOptionalSelf(const Optional &); - void PassOptionalNonNullSelf(const Optional >&); - void PassOptionalSelfWithDefault(TestInterface*); - - already_AddRefed ReceiveNonWrapperCacheInterface(); - already_AddRefed ReceiveNullableNonWrapperCacheInterface(); - void ReceiveNonWrapperCacheInterfaceSequence(nsTArray >&); - void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray >&); - void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable > >&); - void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable > >&); - - already_AddRefed ReceiveOther(); - already_AddRefed ReceiveNullableOther(); - IndirectlyImplementedInterface* ReceiveWeakOther(); - IndirectlyImplementedInterface* ReceiveWeakNullableOther(); - void PassOther(IndirectlyImplementedInterface&); - void PassNullableOther(IndirectlyImplementedInterface*); - already_AddRefed NonNullOther(); - void SetNonNullOther(IndirectlyImplementedInterface&); - already_AddRefed GetNullableOther(); - void SetNullableOther(IndirectlyImplementedInterface*); - void PassOptionalOther(const Optional&); - void PassOptionalNonNullOther(const Optional >&); - void PassOptionalOtherWithDefault(IndirectlyImplementedInterface*); - - already_AddRefed ReceiveExternal(); - already_AddRefed ReceiveNullableExternal(); - TestExternalInterface* ReceiveWeakExternal(); - TestExternalInterface* ReceiveWeakNullableExternal(); - void PassExternal(TestExternalInterface*); - void PassNullableExternal(TestExternalInterface*); - already_AddRefed NonNullExternal(); - void SetNonNullExternal(TestExternalInterface*); - already_AddRefed GetNullableExternal(); - void SetNullableExternal(TestExternalInterface*); - void PassOptionalExternal(const Optional&); - void PassOptionalNonNullExternal(const Optional&); - void PassOptionalExternalWithDefault(TestExternalInterface*); - - already_AddRefed ReceiveCallbackInterface(); - already_AddRefed ReceiveNullableCallbackInterface(); - TestCallbackInterface* ReceiveWeakCallbackInterface(); - TestCallbackInterface* ReceiveWeakNullableCallbackInterface(); - void PassCallbackInterface(TestCallbackInterface&); - void PassNullableCallbackInterface(TestCallbackInterface*); - already_AddRefed NonNullCallbackInterface(); - void SetNonNullCallbackInterface(TestCallbackInterface&); - already_AddRefed GetNullableCallbackInterface(); - void SetNullableCallbackInterface(TestCallbackInterface*); - void PassOptionalCallbackInterface(const Optional >&); - void PassOptionalNonNullCallbackInterface(const Optional >&); - void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*); - - already_AddRefed ReceiveConsequentialInterface(); - void PassConsequentialInterface(IndirectlyImplementedInterface&); - - // Sequence types - void GetReadonlySequence(nsTArray&); - void GetReadonlySequenceOfDictionaries(JSContext*, nsTArray&); - void GetReadonlyNullableSequenceOfDictionaries(JSContext*, Nullable >&); - void GetReadonlyFrozenSequence(JSContext*, nsTArray&); - void GetReadonlyFrozenNullableSequence(JSContext*, Nullable>&); - void ReceiveSequence(nsTArray&); - void ReceiveNullableSequence(Nullable< nsTArray >&); - void ReceiveSequenceOfNullableInts(nsTArray< Nullable >&); - void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable > >&); - void PassSequence(const Sequence &); - void PassNullableSequence(const Nullable< Sequence >&); - void PassSequenceOfNullableInts(const Sequence >&); - void PassOptionalSequenceOfNullableInts(const Optional > > &); - void PassOptionalNullableSequenceOfNullableInts(const Optional > > > &); - void ReceiveCastableObjectSequence(nsTArray< RefPtr > &); - void ReceiveCallbackObjectSequence(nsTArray< RefPtr > &); - void ReceiveNullableCastableObjectSequence(nsTArray< RefPtr > &); - void ReceiveNullableCallbackObjectSequence(nsTArray< RefPtr > &); - void ReceiveCastableObjectNullableSequence(Nullable< nsTArray< RefPtr > >&); - void ReceiveNullableCastableObjectNullableSequence(Nullable< nsTArray< RefPtr > >&); - void ReceiveWeakCastableObjectSequence(nsTArray> &); - void ReceiveWeakNullableCastableObjectSequence(nsTArray> &); - void ReceiveWeakCastableObjectNullableSequence(Nullable< nsTArray> >&); - void ReceiveWeakNullableCastableObjectNullableSequence(Nullable< nsTArray> >&); - void PassCastableObjectSequence(const Sequence< OwningNonNull >&); - void PassNullableCastableObjectSequence(const Sequence< RefPtr > &); - void PassCastableObjectNullableSequence(const Nullable< Sequence< OwningNonNull > >&); - void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< RefPtr > >&); - void PassOptionalSequence(const Optional >&); - void PassOptionalSequenceWithDefaultValue(const Sequence &); - void PassOptionalNullableSequence(const Optional > >&); - void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence >&); - void PassOptionalNullableSequenceWithDefaultValue2(const Nullable< Sequence >&); - void PassOptionalObjectSequence(const Optional > >&); - void PassExternalInterfaceSequence(const Sequence >&); - void PassNullableExternalInterfaceSequence(const Sequence >&); - - void ReceiveStringSequence(nsTArray&); - void PassStringSequence(const Sequence&); - - void ReceiveByteStringSequence(nsTArray&); - void PassByteStringSequence(const Sequence&); - - void ReceiveAnySequence(JSContext*, nsTArray&); - void ReceiveNullableAnySequence(JSContext*, Nullable >&); - void ReceiveAnySequenceSequence(JSContext*, nsTArray >&); - - void ReceiveObjectSequence(JSContext*, nsTArray&); - void ReceiveNullableObjectSequence(JSContext*, nsTArray&); - - void PassSequenceOfSequences(const Sequence< Sequence >&); - void PassSequenceOfSequencesOfSequences(const Sequence>>&); - void ReceiveSequenceOfSequences(nsTArray< nsTArray >&); - void ReceiveSequenceOfSequencesOfSequences(nsTArray>>&); - - // MozMap types - void PassMozMap(const MozMap &); - void PassNullableMozMap(const Nullable< MozMap >&); - void PassMozMapOfNullableInts(const MozMap >&); - void PassOptionalMozMapOfNullableInts(const Optional > > &); - void PassOptionalNullableMozMapOfNullableInts(const Optional > > > &); - void PassCastableObjectMozMap(const MozMap< OwningNonNull >&); - void PassNullableCastableObjectMozMap(const MozMap< RefPtr > &); - void PassCastableObjectNullableMozMap(const Nullable< MozMap< OwningNonNull > >&); - void PassNullableCastableObjectNullableMozMap(const Nullable< MozMap< RefPtr > >&); - void PassOptionalMozMap(const Optional >&); - void PassOptionalNullableMozMap(const Optional > >&); - void PassOptionalNullableMozMapWithDefaultValue(const Nullable< MozMap >&); - void PassOptionalObjectMozMap(const Optional > >&); - void PassExternalInterfaceMozMap(const MozMap >&); - void PassNullableExternalInterfaceMozMap(const MozMap >&); - void PassStringMozMap(const MozMap&); - void PassByteStringMozMap(const MozMap&); - void PassMozMapOfMozMaps(const MozMap< MozMap >&); - void ReceiveMozMap(MozMap&); - void ReceiveNullableMozMap(Nullable>&); - void ReceiveMozMapOfNullableInts(MozMap>&); - void ReceiveNullableMozMapOfNullableInts(Nullable>>&); - void ReceiveMozMapOfMozMaps(MozMap>&); - void ReceiveAnyMozMap(JSContext*, MozMap&); - - // Typed array types - void PassArrayBuffer(const ArrayBuffer&); - void PassNullableArrayBuffer(const Nullable&); - void PassOptionalArrayBuffer(const Optional&); - void PassOptionalNullableArrayBuffer(const Optional >&); - void PassOptionalNullableArrayBufferWithDefaultValue(const Nullable&); - void PassArrayBufferView(const ArrayBufferView&); - void PassInt8Array(const Int8Array&); - void PassInt16Array(const Int16Array&); - void PassInt32Array(const Int32Array&); - void PassUint8Array(const Uint8Array&); - void PassUint16Array(const Uint16Array&); - void PassUint32Array(const Uint32Array&); - void PassUint8ClampedArray(const Uint8ClampedArray&); - void PassFloat32Array(const Float32Array&); - void PassFloat64Array(const Float64Array&); - void PassSequenceOfArrayBuffers(const Sequence&); - void PassSequenceOfNullableArrayBuffers(const Sequence >&); - void PassMozMapOfArrayBuffers(const MozMap&); - void PassMozMapOfNullableArrayBuffers(const MozMap >&); - void PassVariadicTypedArray(const Sequence&); - void PassVariadicNullableTypedArray(const Sequence >&); - void ReceiveUint8Array(JSContext*, JS::MutableHandle); - void SetUint8ArrayAttr(const Uint8Array&); - void GetUint8ArrayAttr(JSContext*, JS::MutableHandle); - - // DOMString types - void PassString(const nsAString&); - void PassNullableString(const nsAString&); - void PassOptionalString(const Optional&); - void PassOptionalStringWithDefaultValue(const nsAString&); - void PassOptionalNullableString(const Optional&); - void PassOptionalNullableStringWithDefaultValue(const nsAString&); - void PassVariadicString(const Sequence&); - void ReceiveString(DOMString&); - - // ByteString types - void PassByteString(const nsCString&); - void PassNullableByteString(const nsCString&); - void PassOptionalByteString(const Optional&); - void PassOptionalByteStringWithDefaultValue(const nsCString&); - void PassOptionalNullableByteString(const Optional&); - void PassOptionalNullableByteStringWithDefaultValue(const nsCString&); - void PassVariadicByteString(const Sequence&); - void PassOptionalUnionByteString(const Optional&); - void PassOptionalUnionByteStringWithDefaultValue(const ByteStringOrLong&); - - // USVString types - void PassUSVS(const nsAString&); - void PassNullableUSVS(const nsAString&); - void PassOptionalUSVS(const Optional&); - void PassOptionalUSVSWithDefaultValue(const nsAString&); - void PassOptionalNullableUSVS(const Optional&); - void PassOptionalNullableUSVSWithDefaultValue(const nsAString&); - void PassVariadicUSVS(const Sequence&); - void ReceiveUSVS(DOMString&); - - // Enumerated types - void PassEnum(TestEnum); - void PassNullableEnum(const Nullable&); - void PassOptionalEnum(const Optional&); - void PassEnumWithDefault(TestEnum); - void PassOptionalNullableEnum(const Optional >&); - void PassOptionalNullableEnumWithDefaultValue(const Nullable&); - void PassOptionalNullableEnumWithDefaultValue2(const Nullable&); - TestEnum ReceiveEnum(); - Nullable ReceiveNullableEnum(); - TestEnum EnumAttribute(); - TestEnum ReadonlyEnumAttribute(); - void SetEnumAttribute(TestEnum); - - // Callback types - void PassCallback(TestCallback&); - void PassNullableCallback(TestCallback*); - void PassOptionalCallback(const Optional >&); - void PassOptionalNullableCallback(const Optional >&); - void PassOptionalNullableCallbackWithDefaultValue(TestCallback*); - already_AddRefed ReceiveCallback(); - already_AddRefed ReceiveNullableCallback(); - void PassNullableTreatAsNullCallback(TestTreatAsNullCallback*); - void PassOptionalNullableTreatAsNullCallback(const Optional >&); - void PassOptionalNullableTreatAsNullCallbackWithDefaultValue(TestTreatAsNullCallback*); - void SetTreatAsNullCallback(TestTreatAsNullCallback&); - already_AddRefed TreatAsNullCallback(); - void SetNullableTreatAsNullCallback(TestTreatAsNullCallback*); - already_AddRefed GetNullableTreatAsNullCallback(); - - void ForceCallbackGeneration(TestIntegerReturn&, - TestNullableIntegerReturn&, - TestBooleanReturn&, - TestFloatReturn&, - TestStringReturn&, - TestEnumReturn&, - TestInterfaceReturn&, - TestNullableInterfaceReturn&, - TestExternalInterfaceReturn&, - TestNullableExternalInterfaceReturn&, - TestCallbackInterfaceReturn&, - TestNullableCallbackInterfaceReturn&, - TestCallbackReturn&, - TestNullableCallbackReturn&, - TestObjectReturn&, - TestNullableObjectReturn&, - TestTypedArrayReturn&, - TestNullableTypedArrayReturn&, - TestSequenceReturn&, - TestNullableSequenceReturn&, - TestIntegerArguments&, - TestInterfaceArguments&, - TestStringEnumArguments&, - TestObjectArguments&, - TestOptionalArguments&); - - // Any types - void PassAny(JSContext*, JS::Handle); - void PassVariadicAny(JSContext*, const Sequence&); - void PassOptionalAny(JSContext*, JS::Handle); - void PassAnyDefaultNull(JSContext*, JS::Handle); - void PassSequenceOfAny(JSContext*, const Sequence&); - void PassNullableSequenceOfAny(JSContext*, const Nullable >&); - void PassOptionalSequenceOfAny(JSContext*, const Optional >&); - void PassOptionalNullableSequenceOfAny(JSContext*, const Optional > >&); - void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, const Nullable >&); - void PassSequenceOfSequenceOfAny(JSContext*, const Sequence >&); - void PassSequenceOfNullableSequenceOfAny(JSContext*, const Sequence > >&); - void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, const Nullable > > >&); - void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, const Optional > > > >&); - void PassMozMapOfAny(JSContext*, const MozMap&); - void PassNullableMozMapOfAny(JSContext*, const Nullable >&); - void PassOptionalMozMapOfAny(JSContext*, const Optional >&); - void PassOptionalNullableMozMapOfAny(JSContext*, const Optional > >&); - void PassOptionalMozMapOfAnyWithDefaultValue(JSContext*, const Nullable >&); - void PassMozMapOfMozMapOfAny(JSContext*, const MozMap >&); - void PassMozMapOfNullableMozMapOfAny(JSContext*, const MozMap > >&); - void PassNullableMozMapOfNullableMozMapOfAny(JSContext*, const Nullable > > >&); - void PassOptionalNullableMozMapOfNullableMozMapOfAny(JSContext*, const Optional>>>>&); - void PassOptionalNullableMozMapOfNullableSequenceOfAny(JSContext*, const Optional>>>>&); - void PassOptionalNullableSequenceOfNullableMozMapOfAny(JSContext*, const Optional>>>>&); - void ReceiveAny(JSContext*, JS::MutableHandle); - - // object types - void PassObject(JSContext*, JS::Handle); - void PassVariadicObject(JSContext*, const Sequence&); - void PassNullableObject(JSContext*, JS::Handle); - void PassVariadicNullableObject(JSContext*, const Sequence&); - void PassOptionalObject(JSContext*, const Optional >&); - void PassOptionalNullableObject(JSContext*, const Optional >&); - void PassOptionalNullableObjectWithDefaultValue(JSContext*, JS::Handle); - void PassSequenceOfObject(JSContext*, const Sequence&); - void PassSequenceOfNullableObject(JSContext*, const Sequence&); - void PassNullableSequenceOfObject(JSContext*, const Nullable >&); - void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, const Optional > > > >&); - void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, const Optional > > > >&); - void PassMozMapOfObject(JSContext*, const MozMap&); - void ReceiveObject(JSContext*, JS::MutableHandle); - void ReceiveNullableObject(JSContext*, JS::MutableHandle); - - // Union types - void PassUnion(JSContext*, const ObjectOrLong& arg); - void PassUnionWithNullable(JSContext* cx, const ObjectOrNullOrLong& arg) - { - OwningObjectOrLong returnValue; - if (arg.IsNull()) { - } else if (arg.IsObject()) { - JS::Rooted obj(cx, arg.GetAsObject()); - JS_GetClass(obj); - returnValue.SetAsObject() = obj; - } else { - int32_t i = arg.GetAsLong(); - i += 1; - returnValue.SetAsLong() = i; - } - } -#ifdef DEBUG - void PassUnion2(const LongOrBoolean& arg); - void PassUnion3(JSContext*, const ObjectOrLongOrBoolean& arg); - void PassUnion4(const NodeOrLongOrBoolean& arg); - void PassUnion5(JSContext*, const ObjectOrBoolean& arg); - void PassUnion6(JSContext*, const ObjectOrString& arg); - void PassUnion7(JSContext*, const ObjectOrStringOrLong& arg); - void PassUnion8(JSContext*, const ObjectOrStringOrBoolean& arg); - void PassUnion9(JSContext*, const ObjectOrStringOrLongOrBoolean& arg); - void PassUnion10(const EventInitOrLong& arg); - void PassUnion11(JSContext*, const CustomEventInitOrLong& arg); - void PassUnion12(const EventInitOrLong& arg); - void PassUnion13(JSContext*, const ObjectOrLongOrNull& arg); - void PassUnion14(JSContext*, const ObjectOrLongOrNull& arg); - void PassUnion15(const LongSequenceOrLong&); - void PassUnion16(const Optional&); - void PassUnion17(const LongSequenceOrNullOrLong&); - void PassUnion18(JSContext*, const ObjectSequenceOrLong&); - void PassUnion19(JSContext*, const Optional&); - void PassUnion20(JSContext*, const ObjectSequenceOrLong&); - void PassUnion21(const LongMozMapOrLong&); - void PassUnion22(JSContext*, const ObjectMozMapOrLong&); - void PassUnion23(const ImageDataSequenceOrLong&); - void PassUnion24(const ImageDataOrNullSequenceOrLong&); - void PassUnion25(const ImageDataSequenceSequenceOrLong&); - void PassUnion26(const ImageDataOrNullSequenceSequenceOrLong&); - void PassUnion27(const StringSequenceOrEventInit&); - void PassUnion28(const EventInitOrStringSequence&); - void PassUnionWithCallback(const EventHandlerNonNullOrNullOrLong& arg); - void PassUnionWithByteString(const ByteStringOrLong&); - void PassUnionWithMozMap(const StringMozMapOrString&); - void PassUnionWithMozMapAndSequence(const StringMozMapOrStringSequence&); - void PassUnionWithSequenceAndMozMap(const StringSequenceOrStringMozMap&); - void PassUnionWithUSVS(const USVStringOrLong&); -#endif - void PassNullableUnion(JSContext*, const Nullable&); - void PassOptionalUnion(JSContext*, const Optional&); - void PassOptionalNullableUnion(JSContext*, const Optional >&); - void PassOptionalNullableUnionWithDefaultValue(JSContext*, const Nullable&); - //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg); - //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg); - void PassUnionWithArrayBuffer(const ArrayBufferOrLong&); - void PassUnionWithString(JSContext*, const StringOrObject&); - void PassUnionWithEnum(JSContext*, const SupportedTypeOrObject&); - //void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&); - void PassUnionWithObject(JSContext*, const ObjectOrLong&); - - void PassUnionWithDefaultValue1(const DoubleOrString& arg); - void PassUnionWithDefaultValue2(const DoubleOrString& arg); - void PassUnionWithDefaultValue3(const DoubleOrString& arg); - void PassUnionWithDefaultValue4(const FloatOrString& arg); - void PassUnionWithDefaultValue5(const FloatOrString& arg); - void PassUnionWithDefaultValue6(const FloatOrString& arg); - void PassUnionWithDefaultValue7(const UnrestrictedDoubleOrString& arg); - void PassUnionWithDefaultValue8(const UnrestrictedDoubleOrString& arg); - void PassUnionWithDefaultValue9(const UnrestrictedDoubleOrString& arg); - void PassUnionWithDefaultValue10(const UnrestrictedDoubleOrString& arg); - void PassUnionWithDefaultValue11(const UnrestrictedFloatOrString& arg); - void PassUnionWithDefaultValue12(const UnrestrictedFloatOrString& arg); - void PassUnionWithDefaultValue13(const UnrestrictedFloatOrString& arg); - void PassUnionWithDefaultValue14(const DoubleOrByteString& arg); - void PassUnionWithDefaultValue15(const DoubleOrByteString& arg); - void PassUnionWithDefaultValue16(const DoubleOrByteString& arg); - void PassUnionWithDefaultValue17(const DoubleOrSupportedType& arg); - void PassUnionWithDefaultValue18(const DoubleOrSupportedType& arg); - void PassUnionWithDefaultValue19(const DoubleOrSupportedType& arg); - - void PassNullableUnionWithDefaultValue1(const Nullable& arg); - void PassNullableUnionWithDefaultValue2(const Nullable& arg); - void PassNullableUnionWithDefaultValue3(const Nullable& arg); - void PassNullableUnionWithDefaultValue4(const Nullable& arg); - void PassNullableUnionWithDefaultValue5(const Nullable& arg); - void PassNullableUnionWithDefaultValue6(const Nullable& arg); - void PassNullableUnionWithDefaultValue7(const Nullable& arg); - void PassNullableUnionWithDefaultValue8(const Nullable& arg); - void PassNullableUnionWithDefaultValue9(const Nullable& arg); - void PassNullableUnionWithDefaultValue10(const Nullable& arg); - void PassNullableUnionWithDefaultValue11(const Nullable& arg); - void PassNullableUnionWithDefaultValue12(const Nullable& arg); - void PassNullableUnionWithDefaultValue13(const Nullable& arg); - void PassNullableUnionWithDefaultValue14(const Nullable& arg); - void PassNullableUnionWithDefaultValue15(const Nullable& arg); - void PassNullableUnionWithDefaultValue16(const Nullable& arg); - void PassNullableUnionWithDefaultValue17(const Nullable& arg); - void PassNullableUnionWithDefaultValue18(const Nullable& arg); - void PassNullableUnionWithDefaultValue19(const Nullable& arg); - void PassNullableUnionWithDefaultValue20(const Nullable& arg); - - void PassSequenceOfUnions(const Sequence&); - void PassSequenceOfUnions2(JSContext*, const Sequence&); - void PassVariadicUnion(const Sequence&); - - void PassSequenceOfNullableUnions(const Sequence>&); - void PassVariadicNullableUnion(const Sequence>&); - void PassMozMapOfUnions(const MozMap&); - void PassMozMapOfUnions2(JSContext*, const MozMap&); - - void ReceiveUnion(OwningCanvasPatternOrCanvasGradient&); - void ReceiveUnion2(JSContext*, OwningObjectOrLong&); - void ReceiveUnionContainingNull(OwningCanvasPatternOrNullOrCanvasGradient&); - void ReceiveNullableUnion(Nullable&); - void ReceiveNullableUnion2(JSContext*, Nullable&); - void GetWritableUnion(OwningCanvasPatternOrCanvasGradient&); - void SetWritableUnion(const CanvasPatternOrCanvasGradient&); - void GetWritableUnionContainingNull(OwningCanvasPatternOrNullOrCanvasGradient&); - void SetWritableUnionContainingNull(const CanvasPatternOrNullOrCanvasGradient&); - void GetWritableNullableUnion(Nullable&); - void SetWritableNullableUnion(const Nullable&); - - // Date types - void PassDate(Date); - void PassNullableDate(const Nullable&); - void PassOptionalDate(const Optional&); - void PassOptionalNullableDate(const Optional >&); - void PassOptionalNullableDateWithDefaultValue(const Nullable&); - void PassDateSequence(const Sequence&); - void PassDateMozMap(const MozMap&); - void PassNullableDateSequence(const Sequence >&); - Date ReceiveDate(); - Nullable ReceiveNullableDate(); - - // Promise types - void PassPromise(Promise&); - void PassNullablePromise(Promise*); - void PassOptionalPromise(const Optional>&); - void PassOptionalNullablePromise(const Optional>&); - void PassOptionalNullablePromiseWithDefaultValue(Promise*); - void PassPromiseSequence(const Sequence>&); - void PassPromiseMozMap(const MozMap>&); - void PassNullablePromiseSequence(const Sequence> &); - Promise* ReceivePromise(); - already_AddRefed ReceiveAddrefedPromise(); - - // binaryNames tests - void MethodRenamedTo(); - void OtherMethodRenamedTo(); - void MethodRenamedTo(int8_t); - int8_t AttributeGetterRenamedTo(); - int8_t AttributeRenamedTo(); - void SetAttributeRenamedTo(int8_t); - int8_t OtherAttributeRenamedTo(); - void SetOtherAttributeRenamedTo(int8_t); - - // Dictionary tests - void PassDictionary(JSContext*, const Dict&); - void PassDictionary2(JSContext*, const Dict&); - void GetReadonlyDictionary(JSContext*, Dict&); - void GetReadonlyNullableDictionary(JSContext*, Nullable&); - void GetWritableDictionary(JSContext*, Dict&); - void SetWritableDictionary(JSContext*, const Dict&); - void GetReadonlyFrozenDictionary(JSContext*, Dict&); - void GetReadonlyFrozenNullableDictionary(JSContext*, Nullable&); - void GetWritableFrozenDictionary(JSContext*, Dict&); - void SetWritableFrozenDictionary(JSContext*, const Dict&); - void ReceiveDictionary(JSContext*, Dict&); - void ReceiveNullableDictionary(JSContext*, Nullable&); - void PassOtherDictionary(const GrandparentDict&); - void PassSequenceOfDictionaries(JSContext*, const Sequence&); - void PassMozMapOfDictionaries(const MozMap&); - void PassDictionaryOrLong(JSContext*, const Dict&); - void PassDictionaryOrLong(int32_t); - void PassDictContainingDict(JSContext*, const DictContainingDict&); - void PassDictContainingSequence(JSContext*, const DictContainingSequence&); - void ReceiveDictContainingSequence(JSContext*, DictContainingSequence&); - void PassVariadicDictionary(JSContext*, const Sequence&); - - // Typedefs - void ExerciseTypedefInterfaces1(TestInterface&); - already_AddRefed ExerciseTypedefInterfaces2(TestInterface*); - void ExerciseTypedefInterfaces3(TestInterface&); - - // Deprecated methods and attributes - int8_t DeprecatedAttribute(); - int8_t SetDeprecatedAttribute(int8_t); - int8_t DeprecatedMethod(); - int8_t DeprecatedMethodWithContext(JSContext*, const JS::Value&); - - // Static methods and attributes - static void StaticMethod(const GlobalObject&, bool); - static void StaticMethodWithContext(const GlobalObject&, const JS::Value&); - static bool StaticAttribute(const GlobalObject&); - static void SetStaticAttribute(const GlobalObject&, bool); - static void Assert(const GlobalObject&, bool); - - // Deprecated static methods and attributes - static int8_t StaticDeprecatedAttribute(const GlobalObject&); - static int8_t SetStaticDeprecatedAttribute(const GlobalObject&, int8_t); - static int8_t StaticDeprecatedMethod(const GlobalObject&); - static int8_t StaticDeprecatedMethodWithContext(const GlobalObject&, const JS::Value&); - - // Overload resolution tests - bool Overload1(TestInterface&); - TestInterface* Overload1(const nsAString&, TestInterface&); - void Overload2(TestInterface&); - void Overload2(JSContext*, const Dict&); - void Overload2(bool); - void Overload2(const nsAString&); - void Overload2(Date); - void Overload3(TestInterface&); - void Overload3(const TestCallback&); - void Overload3(bool); - void Overload4(TestInterface&); - void Overload4(TestCallbackInterface&); - void Overload4(const nsAString&); - void Overload5(int32_t); - void Overload5(TestEnum); - void Overload6(int32_t); - void Overload6(bool); - void Overload7(int32_t); - void Overload7(bool); - void Overload7(const nsCString&); - void Overload8(int32_t); - void Overload8(TestInterface&); - void Overload9(const Nullable&); - void Overload9(const nsAString&); - void Overload10(const Nullable&); - void Overload10(JSContext*, JS::Handle); - void Overload11(int32_t); - void Overload11(const nsAString&); - void Overload12(int32_t); - void Overload12(const Nullable&); - void Overload13(const Nullable&); - void Overload13(bool); - void Overload14(const Optional&); - void Overload14(TestInterface&); - void Overload15(int32_t); - void Overload15(const Optional >&); - void Overload16(int32_t); - void Overload16(const Optional&); - void Overload17(const Sequence&); - void Overload17(const MozMap&); - void Overload18(const MozMap&); - void Overload18(const Sequence&); - void Overload19(const Sequence&); - void Overload19(JSContext*, const Dict&); - void Overload20(JSContext*, const Dict&); - void Overload20(const Sequence&); - - // Variadic handling - void PassVariadicThirdArg(const nsAString&, int32_t, - const Sequence >&); - - // Conditionally exposed methods/attributes - bool Prefable1(); - bool Prefable2(); - bool Prefable3(); - bool Prefable4(); - bool Prefable5(); - bool Prefable6(); - bool Prefable7(); - bool Prefable8(); - bool Prefable9(); - void Prefable10(); - void Prefable11(); - bool Prefable12(); - void Prefable13(); - bool Prefable14(); - bool Prefable15(); - bool Prefable16(); - void Prefable17(); - void Prefable18(); - void Prefable19(); - void Prefable20(); - void Prefable21(); - void Prefable22(); - void Prefable23(); - void Prefable24(); - - // Conditionally exposed methods/attributes involving [SecureContext] - bool ConditionalOnSecureContext1(); - bool ConditionalOnSecureContext2(); - bool ConditionalOnSecureContext3(); - bool ConditionalOnSecureContext4(); - void ConditionalOnSecureContext5(); - void ConditionalOnSecureContext6(); - void ConditionalOnSecureContext7(); - void ConditionalOnSecureContext8(); - - // Miscellania - int32_t AttrWithLenientThis(); - void SetAttrWithLenientThis(int32_t); - uint32_t UnforgeableAttr(); - uint32_t UnforgeableAttr2(); - uint32_t UnforgeableMethod(); - uint32_t UnforgeableMethod2(); - void Stringify(nsString&); - void PassRenamedInterface(nsRenamedInterface&); - TestInterface* PutForwardsAttr(); - TestInterface* PutForwardsAttr2(); - TestInterface* PutForwardsAttr3(); - void GetJsonifierShouldSkipThis(JSContext*, JS::MutableHandle); - void SetJsonifierShouldSkipThis(JSContext*, JS::Rooted&); - TestParentInterface* JsonifierShouldSkipThis2(); - void SetJsonifierShouldSkipThis2(TestParentInterface&); - TestCallbackInterface* JsonifierShouldSkipThis3(); - void SetJsonifierShouldSkipThis3(TestCallbackInterface&); - void ThrowingMethod(ErrorResult& aRv); - bool GetThrowingAttr(ErrorResult& aRv) const; - void SetThrowingAttr(bool arg, ErrorResult& aRv); - bool GetThrowingGetterAttr(ErrorResult& aRv) const; - void SetThrowingGetterAttr(bool arg); - bool ThrowingSetterAttr() const; - void SetThrowingSetterAttr(bool arg, ErrorResult& aRv); - void NeedsSubjectPrincipalMethod(nsIPrincipal&); - bool NeedsSubjectPrincipalAttr(nsIPrincipal&); - void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&); - void NeedsCallerTypeMethod(CallerType); - bool NeedsCallerTypeAttr(CallerType); - void SetNeedsCallerTypeAttr(bool, CallerType); - void CeReactionsMethod(); - void CeReactionsMethodOverload(); - void CeReactionsMethodOverload(const nsAString&); - bool CeReactionsAttr() const; - void SetCeReactionsAttr(bool); - int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&); - void PassArgsWithDefaults(JSContext*, const Optional&, - TestInterface*, const Dict&, double, - const Optional&); - - void SetDashed_attribute(int8_t); - int8_t Dashed_attribute(); - void Dashed_method(); - - // Methods and properties imported via "implements" - bool ImplementedProperty(); - void SetImplementedProperty(bool); - void ImplementedMethod(); - bool ImplementedParentProperty(); - void SetImplementedParentProperty(bool); - void ImplementedParentMethod(); - bool IndirectlyImplementedProperty(); - void SetIndirectlyImplementedProperty(bool); - void IndirectlyImplementedMethod(); - uint32_t DiamondImplementedProperty(); - - // Test EnforceRange/Clamp - void DontEnforceRangeOrClamp(int8_t); - void DoEnforceRange(int8_t); - void DoClamp(int8_t); - void SetEnforcedByte(int8_t); - int8_t EnforcedByte(); - void SetClampedByte(int8_t); - int8_t ClampedByte(); - -private: - // We add signatures here that _could_ start matching if the codegen - // got data types wrong. That way if it ever does we'll have a call - // to these private deleted methods and compilation will fail. - void SetReadonlyByte(int8_t) = delete; - template - void SetWritableByte(T) = delete; - template - void PassByte(T) = delete; - void PassNullableByte(Nullable&) = delete; - template - void PassOptionalByte(const Optional&) = delete; - template - void PassOptionalByteWithDefault(T) = delete; - void PassVariadicByte(Sequence&) = delete; - - void SetReadonlyShort(int16_t) = delete; - template - void SetWritableShort(T) = delete; - template - void PassShort(T) = delete; - template - void PassOptionalShort(const Optional&) = delete; - template - void PassOptionalShortWithDefault(T) = delete; - - void SetReadonlyLong(int32_t) = delete; - template - void SetWritableLong(T) = delete; - template - void PassLong(T) = delete; - template - void PassOptionalLong(const Optional&) = delete; - template - void PassOptionalLongWithDefault(T) = delete; - - void SetReadonlyLongLong(int64_t) = delete; - template - void SetWritableLongLong(T) = delete; - template - void PassLongLong(T) = delete; - template - void PassOptionalLongLong(const Optional&) = delete; - template - void PassOptionalLongLongWithDefault(T) = delete; - - void SetReadonlyOctet(uint8_t) = delete; - template - void SetWritableOctet(T) = delete; - template - void PassOctet(T) = delete; - template - void PassOptionalOctet(const Optional&) = delete; - template - void PassOptionalOctetWithDefault(T) = delete; - - void SetReadonlyUnsignedShort(uint16_t) = delete; - template - void SetWritableUnsignedShort(T) = delete; - template - void PassUnsignedShort(T) = delete; - template - void PassOptionalUnsignedShort(const Optional&) = delete; - template - void PassOptionalUnsignedShortWithDefault(T) = delete; - - void SetReadonlyUnsignedLong(uint32_t) = delete; - template - void SetWritableUnsignedLong(T) = delete; - template - void PassUnsignedLong(T) = delete; - template - void PassOptionalUnsignedLong(const Optional&) = delete; - template - void PassOptionalUnsignedLongWithDefault(T) = delete; - - void SetReadonlyUnsignedLongLong(uint64_t) = delete; - template - void SetWritableUnsignedLongLong(T) = delete; - template - void PassUnsignedLongLong(T) = delete; - template - void PassOptionalUnsignedLongLong(const Optional&) = delete; - template - void PassOptionalUnsignedLongLongWithDefault(T) = delete; - - // Enforce that only const things are passed for sequences - void PassSequence(Sequence &) = delete; - void PassNullableSequence(Nullable< Sequence >&) = delete; - void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence >&) = delete; - void PassSequenceOfAny(JSContext*, Sequence&) = delete; - void PassNullableSequenceOfAny(JSContext*, Nullable >&) = delete; - void PassOptionalSequenceOfAny(JSContext*, Optional >&) = delete; - void PassOptionalNullableSequenceOfAny(JSContext*, Optional > >&) = delete; - void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, Nullable >&) = delete; - void PassSequenceOfSequenceOfAny(JSContext*, Sequence >&) = delete; - void PassSequenceOfNullableSequenceOfAny(JSContext*, Sequence > >&) = delete; - void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, Nullable > > >&) = delete; - void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, Optional > > > >&) = delete; - void PassSequenceOfObject(JSContext*, Sequence&) = delete; - void PassSequenceOfNullableObject(JSContext*, Sequence&) = delete; - void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, Optional > > > >&) = delete; - void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, Optional > > > >&) = delete; - - // Enforce that only const things are passed for optional - void PassOptionalByte(Optional&) = delete; - void PassOptionalNullableByte(Optional >&) = delete; - void PassOptionalShort(Optional&) = delete; - void PassOptionalLong(Optional&) = delete; - void PassOptionalLongLong(Optional&) = delete; - void PassOptionalOctet(Optional&) = delete; - void PassOptionalUnsignedShort(Optional&) = delete; - void PassOptionalUnsignedLong(Optional&) = delete; - void PassOptionalUnsignedLongLong(Optional&) = delete; - void PassOptionalSelf(Optional &) = delete; - void PassOptionalNonNullSelf(Optional >&) = delete; - void PassOptionalOther(Optional&); - void PassOptionalNonNullOther(Optional >&); - void PassOptionalExternal(Optional&) = delete; - void PassOptionalNonNullExternal(Optional&) = delete; - void PassOptionalSequence(Optional >&) = delete; - void PassOptionalNullableSequence(Optional > >&) = delete; - void PassOptionalObjectSequence(Optional > >&) = delete; - void PassOptionalArrayBuffer(Optional&) = delete; - void PassOptionalNullableArrayBuffer(Optional&) = delete; - void PassOptionalEnum(Optional&) = delete; - void PassOptionalCallback(JSContext*, Optional >&) = delete; - void PassOptionalNullableCallback(JSContext*, Optional >&) = delete; - void PassOptionalAny(Optional >&) = delete; - - // And test that string stuff is always const - void PassString(nsAString&) = delete; - void PassNullableString(nsAString&) = delete; - void PassOptionalString(Optional&) = delete; - void PassOptionalStringWithDefaultValue(nsAString&) = delete; - void PassOptionalNullableString(Optional&) = delete; - void PassOptionalNullableStringWithDefaultValue(nsAString&) = delete; - void PassVariadicString(Sequence&) = delete; - - // cstrings should be const as well - void PassByteString(nsCString&) = delete; - void PassNullableByteString(nsCString&) = delete; - void PassOptionalByteString(Optional&) = delete; - void PassOptionalByteStringWithDefaultValue(nsCString&) = delete; - void PassOptionalNullableByteString(Optional&) = delete; - void PassOptionalNullableByteStringWithDefaultValue(nsCString&) = delete; - void PassVariadicByteString(Sequence&) = delete; - - // Make sure dictionary arguments are always const - void PassDictionary(JSContext*, Dict&) = delete; - void PassOtherDictionary(GrandparentDict&) = delete; - void PassSequenceOfDictionaries(JSContext*, Sequence&) = delete; - void PassDictionaryOrLong(JSContext*, Dict&) = delete; - void PassDictContainingDict(JSContext*, DictContainingDict&) = delete; - void PassDictContainingSequence(DictContainingSequence&) = delete; - - // Make sure various nullable things are always const - void PassNullableEnum(Nullable&) = delete; - - // Make sure unions are always const - void PassUnion(JSContext*, ObjectOrLong& arg) = delete; - void PassUnionWithNullable(JSContext*, ObjectOrNullOrLong& arg) = delete; - void PassNullableUnion(JSContext*, Nullable&) = delete; - void PassOptionalUnion(JSContext*, Optional&) = delete; - void PassOptionalNullableUnion(JSContext*, Optional >&) = delete; - void PassOptionalNullableUnionWithDefaultValue(JSContext*, Nullable&) = delete; - - // Make sure various date stuff is const as needed - void PassNullableDate(Nullable&) = delete; - void PassOptionalDate(Optional&) = delete; - void PassOptionalNullableDate(Optional >&) = delete; - void PassOptionalNullableDateWithDefaultValue(Nullable&) = delete; - void PassDateSequence(Sequence&) = delete; - void PassNullableDateSequence(Sequence >&) = delete; - - // Make sure variadics are const as needed - void PassVariadicAny(JSContext*, Sequence&) = delete; - void PassVariadicObject(JSContext*, Sequence&) = delete; - void PassVariadicNullableObject(JSContext*, Sequence&) = delete; - - // Ensure NonNull does not leak in - void PassSelf(NonNull&) = delete; - void PassSelf(OwningNonNull&) = delete; - void PassSelf(const NonNull&) = delete; - void PassSelf(const OwningNonNull&) = delete; - void PassOther(NonNull&) = delete; - void PassOther(const NonNull&) = delete; - void PassOther(OwningNonNull&) = delete; - void PassOther(const OwningNonNull&) = delete; - void PassCallbackInterface(OwningNonNull&) = delete; - void PassCallbackInterface(const OwningNonNull&) = delete; - void PassCallbackInterface(NonNull&) = delete; - void PassCallbackInterface(const NonNull&) = delete; - void PassCallback(OwningNonNull&) = delete; - void PassCallback(const OwningNonNull&) = delete; - void PassCallback(NonNull&) = delete; - void PassCallback(const NonNull&) = delete; - void PassString(const NonNull&) = delete; - void PassString(NonNull&) = delete; - void PassString(const OwningNonNull&) = delete; - void PassString(OwningNonNull&) = delete; -}; - -class TestIndexedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - uint32_t IndexedGetter(uint32_t, bool&); - uint32_t IndexedGetter(uint32_t&) = delete; - uint32_t Item(uint32_t&); - uint32_t Item(uint32_t, bool&) = delete; - uint32_t Length(); - void LegacyCall(JS::Handle); -}; - -class TestNamedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedGetter(const nsAString&, bool&, nsAString&); - void GetSupportedNames(nsTArray&); -}; - -class TestIndexedGetterAndSetterAndNamedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedGetter(const nsAString&, bool&, nsAString&); - void GetSupportedNames(nsTArray&); - int32_t IndexedGetter(uint32_t, bool&); - void IndexedSetter(uint32_t, int32_t); - uint32_t Length(); -}; - -class TestIndexedAndNamedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - uint32_t IndexedGetter(uint32_t, bool&); - void NamedGetter(const nsAString&, bool&, nsAString&); - void NamedItem(const nsAString&, nsAString&); - uint32_t Length(); - void GetSupportedNames(nsTArray&); -}; - -class TestIndexedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void IndexedSetter(uint32_t, const nsAString&); - void IndexedGetter(uint32_t, bool&, nsString&); - uint32_t Length(); - void SetItem(uint32_t, const nsAString&); -}; - -class TestNamedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedSetter(const nsAString&, TestIndexedSetterInterface&); - TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&); - void GetSupportedNames(nsTArray&); -}; - -class TestIndexedAndNamedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void IndexedSetter(uint32_t, TestIndexedSetterInterface&); - TestIndexedSetterInterface* IndexedGetter(uint32_t, bool&); - uint32_t Length(); - void NamedSetter(const nsAString&, TestIndexedSetterInterface&); - TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&); - void SetNamedItem(const nsAString&, TestIndexedSetterInterface&); - void GetSupportedNames(nsTArray&); -}; - -class TestIndexedAndNamedGetterAndSetterInterface : public TestIndexedSetterInterface -{ -public: - uint32_t IndexedGetter(uint32_t, bool&); - uint32_t Item(uint32_t); - void NamedGetter(const nsAString&, bool&, nsAString&); - void NamedItem(const nsAString&, nsAString&); - void IndexedSetter(uint32_t, int32_t&); - void IndexedSetter(uint32_t, const nsAString&) = delete; - void NamedSetter(const nsAString&, const nsAString&); - void Stringify(nsAString&); - uint32_t Length(); - void GetSupportedNames(nsTArray&); -}; - -class TestCppKeywordNamedMethodsInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - bool Continue(); - bool Delete(); - int32_t Volatile(); -}; - -class TestNamedDeleterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedDeleter(const nsAString&, bool&); - long NamedGetter(const nsAString&, bool&); - void GetSupportedNames(nsTArray&); -}; - -class TestNamedDeleterWithRetvalInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - bool NamedDeleter(const nsAString&, bool&); - bool NamedDeleter(const nsAString&) = delete; - long NamedGetter(const nsAString&, bool&); - bool DelNamedItem(const nsAString&); - bool DelNamedItem(const nsAString&, bool&) = delete; - void GetSupportedNames(nsTArray&); -}; - -class TestParentInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); -}; - -class TestChildInterface : public TestParentInterface -{ -}; - -class TestDeprecatedInterface : public nsISupports, public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - static - already_AddRefed - Constructor(const GlobalObject&, ErrorResult&); - - static void AlsoDeprecated(const GlobalObject&); - - virtual nsISupports* GetParentObject(); -}; - -class TestInterfaceWithPromiseConstructorArg : public nsISupports, public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - static - already_AddRefed - Constructor(const GlobalObject&, Promise&, ErrorResult&); - - virtual nsISupports* GetParentObject(); -}; - -class TestSecureContextInterface : public nsISupports, public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - static - already_AddRefed - Constructor(const GlobalObject&, ErrorResult&); - - static void AlsoSecureContext(const GlobalObject&); - - virtual nsISupports* GetParentObject(); -}; - -class TestNamespace { -public: - static bool Foo(const GlobalObject&); - static int32_t Bar(const GlobalObject&); - static void Baz(const GlobalObject&); -}; - -class TestRenamedNamespace { -}; - -class TestProtoObjectHackedNamespace { -}; - -class TestWorkerExposedInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - nsISupports* GetParentObject(); - - void NeedsSubjectPrincipalMethod(Maybe); - bool NeedsSubjectPrincipalAttr(Maybe); - void SetNeedsSubjectPrincipalAttr(bool, Maybe); - void NeedsCallerTypeMethod(CallerType); - bool NeedsCallerTypeAttr(CallerType); - void SetNeedsCallerTypeAttr(bool, CallerType); -}; - -class TestHTMLConstructorInterface : public nsGenericHTMLElement -{ -public: - virtual nsISupports* GetParentObject(); -}; - -class TestCEReactionsInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - int32_t Item(uint32_t); - uint32_t Length() const; - int32_t IndexedGetter(uint32_t, bool &); - void IndexedSetter(uint32_t, int32_t); - void NamedDeleter(const nsAString&, bool &); - void NamedGetter(const nsAString&, bool &, nsString&); - void NamedSetter(const nsAString&, const nsAString&); - void GetSupportedNames(nsTArray&); -}; - -} // namespace dom -} // namespace mozilla - -#endif /* TestBindingHeader_h */ diff --git a/dom/bindings/test/TestCImplementedInterface.h b/dom/bindings/test/TestCImplementedInterface.h deleted file mode 100644 index 64b5c9954a..0000000000 --- a/dom/bindings/test/TestCImplementedInterface.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#ifndef TestCImplementedInterface_h -#define TestCImplementedInterface_h - -#include "../TestJSImplGenBinding.h" - -namespace mozilla { -namespace dom { - -class TestCImplementedInterface : public TestJSImplInterface -{ -public: - TestCImplementedInterface(JS::Handle aJSImpl, - nsIGlobalObject* aParent) - : TestJSImplInterface(aJSImpl, aParent) - {} -}; - -class TestCImplementedInterface2 : public nsISupports, - public nsWrapperCache -{ -public: - explicit TestCImplementedInterface2(nsIGlobalObject* aParent) - {} - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestCImplementedInterface2) - - // We need a GetParentObject to make binding codegen happy - nsISupports* GetParentObject(); -}; - - - -} // namespace dom -} // namespace mozilla - -#endif // TestCImplementedInterface_h diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl deleted file mode 100644 index 3fce5e21b7..0000000000 --- a/dom/bindings/test/TestCodeGen.webidl +++ /dev/null @@ -1,1281 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -typedef long myLong; -typedef TestInterface AnotherNameForTestInterface; -typedef TestInterface? NullableTestInterface; -typedef CustomEventInit TestDictionaryTypedef; - -interface TestExternalInterface; - -[Pref="xyz"] -interface TestRenamedInterface { -}; - -callback interface TestCallbackInterface { - readonly attribute long foo; - attribute DOMString bar; - void doSomething(); - long doSomethingElse(DOMString arg, TestInterface otherArg); - void doSequenceLongArg(sequence arg); - void doSequenceStringArg(sequence arg); - void doMozMapLongArg(MozMap arg); - sequence getSequenceOfLong(); - sequence getSequenceOfInterfaces(); - sequence? getNullableSequenceOfInterfaces(); - sequence getSequenceOfNullableInterfaces(); - sequence? getNullableSequenceOfNullableInterfaces(); - sequence getSequenceOfCallbackInterfaces(); - sequence? getNullableSequenceOfCallbackInterfaces(); - sequence getSequenceOfNullableCallbackInterfaces(); - sequence? getNullableSequenceOfNullableCallbackInterfaces(); - MozMap getMozMapOfLong(); - Dict? getDictionary(); - void passArrayBuffer(ArrayBuffer arg); - void passNullableArrayBuffer(ArrayBuffer? arg); - void passOptionalArrayBuffer(optional ArrayBuffer arg); - void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); - void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); - void passArrayBufferView(ArrayBufferView arg); - void passInt8Array(Int8Array arg); - void passInt16Array(Int16Array arg); - void passInt32Array(Int32Array arg); - void passUint8Array(Uint8Array arg); - void passUint16Array(Uint16Array arg); - void passUint32Array(Uint32Array arg); - void passUint8ClampedArray(Uint8ClampedArray arg); - void passFloat32Array(Float32Array arg); - void passFloat64Array(Float64Array arg); - void passSequenceOfArrayBuffers(sequence arg); - void passSequenceOfNullableArrayBuffers(sequence arg); - void passVariadicTypedArray(Float32Array... arg); - void passVariadicNullableTypedArray(Float32Array?... arg); - Uint8Array receiveUint8Array(); - attribute Uint8Array uint8ArrayAttr; - Promise receivePromise(); -}; - -callback interface TestSingleOperationCallbackInterface { - TestInterface doSomething(short arg, sequence anotherArg); -}; - -enum TestEnum { - "1", - "a", - "b" -}; - -callback TestCallback = void(); -[TreatNonCallableAsNull] callback TestTreatAsNullCallback = void(); - -// Callback return value tests -callback TestIntegerReturn = long(); -callback TestNullableIntegerReturn = long?(); -callback TestBooleanReturn = boolean(); -callback TestFloatReturn = float(); -callback TestStringReturn = DOMString(long arg); -callback TestEnumReturn = TestEnum(); -callback TestInterfaceReturn = TestInterface(); -callback TestNullableInterfaceReturn = TestInterface?(); -callback TestExternalInterfaceReturn = TestExternalInterface(); -callback TestNullableExternalInterfaceReturn = TestExternalInterface?(); -callback TestCallbackInterfaceReturn = TestCallbackInterface(); -callback TestNullableCallbackInterfaceReturn = TestCallbackInterface?(); -callback TestCallbackReturn = TestCallback(); -callback TestNullableCallbackReturn = TestCallback?(); -callback TestObjectReturn = object(); -callback TestNullableObjectReturn = object?(); -callback TestTypedArrayReturn = ArrayBuffer(); -callback TestNullableTypedArrayReturn = ArrayBuffer?(); -callback TestSequenceReturn = sequence(); -callback TestNullableSequenceReturn = sequence?(); -// Callback argument tests -callback TestIntegerArguments = sequence(long arg1, long? arg2, - sequence arg3, - sequence? arg4); -callback TestInterfaceArguments = void(TestInterface arg1, TestInterface? arg2, - TestExternalInterface arg3, - TestExternalInterface? arg4, - TestCallbackInterface arg5, - TestCallbackInterface? arg6, - sequence arg7, - sequence? arg8, - sequence arg9, - sequence? arg10, - sequence arg11, - sequence? arg12); -callback TestStringEnumArguments = void(DOMString myString, DOMString? nullString, - TestEnum myEnum); -callback TestObjectArguments = void(object anObj, object? anotherObj, - ArrayBuffer buf, ArrayBuffer? buf2); -callback TestOptionalArguments = void(optional DOMString aString, - optional object something, - optional sequence aSeq, - optional TestInterface? anInterface, - optional TestInterface anotherInterface, - optional long aLong); -// If you add a new test callback, add it to the forceCallbackGeneration -// method on TestInterface so it actually gets tested. - -TestInterface implements ImplementedInterface; - -// This interface is only for use in the constructor below -interface OnlyForUseInConstructor { -}; - -[Constructor, - Constructor(DOMString str), - Constructor(unsigned long num, boolean? boolArg), - Constructor(TestInterface? iface), - Constructor(long arg1, IndirectlyImplementedInterface iface), - Constructor(Date arg1), - Constructor(ArrayBuffer arrayBuf), - Constructor(Uint8Array typedArr), - // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3), - NamedConstructor=Test, - NamedConstructor=Test(DOMString str), - NamedConstructor=Test2(DictForConstructor dict, any any1, object obj1, - object? obj2, sequence seq, optional any any2, - optional object obj3, optional object? obj4), - NamedConstructor=Test3((long or MozMap) arg1) - ] -interface TestInterface { - // Integer types - // XXXbz add tests for throwing versions of all the integer stuff - readonly attribute byte readonlyByte; - attribute byte writableByte; - void passByte(byte arg); - byte receiveByte(); - void passOptionalByte(optional byte arg); - void passOptionalByteBeforeRequired(optional byte arg1, byte arg2); - void passOptionalByteWithDefault(optional byte arg = 0); - void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); - void passNullableByte(byte? arg); - void passOptionalNullableByte(optional byte? arg); - void passVariadicByte(byte... arg); - [StoreInSlot, Pure] - readonly attribute byte cachedByte; - [StoreInSlot, Constant] - readonly attribute byte cachedConstantByte; - [StoreInSlot, Pure] - attribute byte cachedWritableByte; - [Affects=Nothing] - attribute byte sideEffectFreeByte; - [Affects=Nothing, DependsOn=DOMState] - attribute byte domDependentByte; - [Affects=Nothing, DependsOn=Nothing] - readonly attribute byte constantByte; - [DependsOn=DeviceState, Affects=Nothing] - readonly attribute byte deviceStateDependentByte; - [Affects=Nothing] - byte returnByteSideEffectFree(); - [Affects=Nothing, DependsOn=DOMState] - byte returnDOMDependentByte(); - [Affects=Nothing, DependsOn=Nothing] - byte returnConstantByte(); - [DependsOn=DeviceState, Affects=Nothing] - byte returnDeviceStateDependentByte(); - - [UnsafeInPrerendering] - void unsafePrerenderMethod(); - [UnsafeInPrerendering] - attribute long unsafePrerenderWritable; - [UnsafeInPrerendering] - readonly attribute long unsafePrerenderReadonly; - readonly attribute short readonlyShort; - attribute short writableShort; - void passShort(short arg); - short receiveShort(); - void passOptionalShort(optional short arg); - void passOptionalShortWithDefault(optional short arg = 5); - - readonly attribute long readonlyLong; - attribute long writableLong; - void passLong(long arg); - long receiveLong(); - void passOptionalLong(optional long arg); - void passOptionalLongWithDefault(optional long arg = 7); - - readonly attribute long long readonlyLongLong; - attribute long long writableLongLong; - void passLongLong(long long arg); - long long receiveLongLong(); - void passOptionalLongLong(optional long long arg); - void passOptionalLongLongWithDefault(optional long long arg = -12); - - readonly attribute octet readonlyOctet; - attribute octet writableOctet; - void passOctet(octet arg); - octet receiveOctet(); - void passOptionalOctet(optional octet arg); - void passOptionalOctetWithDefault(optional octet arg = 19); - - readonly attribute unsigned short readonlyUnsignedShort; - attribute unsigned short writableUnsignedShort; - void passUnsignedShort(unsigned short arg); - unsigned short receiveUnsignedShort(); - void passOptionalUnsignedShort(optional unsigned short arg); - void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); - - readonly attribute unsigned long readonlyUnsignedLong; - attribute unsigned long writableUnsignedLong; - void passUnsignedLong(unsigned long arg); - unsigned long receiveUnsignedLong(); - void passOptionalUnsignedLong(optional unsigned long arg); - void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); - - readonly attribute unsigned long long readonlyUnsignedLongLong; - attribute unsigned long long writableUnsignedLongLong; - void passUnsignedLongLong(unsigned long long arg); - unsigned long long receiveUnsignedLongLong(); - void passOptionalUnsignedLongLong(optional unsigned long long arg); - void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); - - attribute float writableFloat; - attribute unrestricted float writableUnrestrictedFloat; - attribute float? writableNullableFloat; - attribute unrestricted float? writableNullableUnrestrictedFloat; - attribute double writableDouble; - attribute unrestricted double writableUnrestrictedDouble; - attribute double? writableNullableDouble; - attribute unrestricted double? writableNullableUnrestrictedDouble; - void passFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, sequence arg10, - sequence arg11, sequence arg12, - sequence arg13, sequence arg14, - sequence arg15, sequence arg16); - [LenientFloat] - void passLenientFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, - sequence arg10, - sequence arg11, - sequence arg12, - sequence arg13, - sequence arg14, - sequence arg15, - sequence arg16); - [LenientFloat] - attribute float lenientFloatAttr; - [LenientFloat] - attribute double lenientDoubleAttr; - - void passUnrestricted(optional unrestricted float arg1 = 0, - optional unrestricted float arg2 = Infinity, - optional unrestricted float arg3 = -Infinity, - optional unrestricted float arg4 = NaN, - optional unrestricted double arg5 = 0, - optional unrestricted double arg6 = Infinity, - optional unrestricted double arg7 = -Infinity, - optional unrestricted double arg8 = NaN); - - // Castable interface types - // XXXbz add tests for throwing versions of all the castable interface stuff - TestInterface receiveSelf(); - TestInterface? receiveNullableSelf(); - TestInterface receiveWeakSelf(); - TestInterface? receiveWeakNullableSelf(); - void passSelf(TestInterface arg); - void passNullableSelf(TestInterface? arg); - attribute TestInterface nonNullSelf; - attribute TestInterface? nullableSelf; - [Cached, Pure] - readonly attribute TestInterface cachedSelf; - // Optional arguments - void passOptionalSelf(optional TestInterface? arg); - void passOptionalNonNullSelf(optional TestInterface arg); - void passOptionalSelfWithDefault(optional TestInterface? arg = null); - - // Non-wrapper-cache interface types - [NewObject] - TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); - [NewObject] - TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); - [NewObject] - sequence receiveNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence receiveNullableNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence? receiveNonWrapperCacheInterfaceNullableSequence(); - [NewObject] - sequence? receiveNullableNonWrapperCacheInterfaceNullableSequence(); - - // Non-castable interface types - IndirectlyImplementedInterface receiveOther(); - IndirectlyImplementedInterface? receiveNullableOther(); - IndirectlyImplementedInterface receiveWeakOther(); - IndirectlyImplementedInterface? receiveWeakNullableOther(); - void passOther(IndirectlyImplementedInterface arg); - void passNullableOther(IndirectlyImplementedInterface? arg); - attribute IndirectlyImplementedInterface nonNullOther; - attribute IndirectlyImplementedInterface? nullableOther; - // Optional arguments - void passOptionalOther(optional IndirectlyImplementedInterface? arg); - void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg); - void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null); - - // External interface types - TestExternalInterface receiveExternal(); - TestExternalInterface? receiveNullableExternal(); - TestExternalInterface receiveWeakExternal(); - TestExternalInterface? receiveWeakNullableExternal(); - void passExternal(TestExternalInterface arg); - void passNullableExternal(TestExternalInterface? arg); - attribute TestExternalInterface nonNullExternal; - attribute TestExternalInterface? nullableExternal; - // Optional arguments - void passOptionalExternal(optional TestExternalInterface? arg); - void passOptionalNonNullExternal(optional TestExternalInterface arg); - void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); - - // Callback interface types - TestCallbackInterface receiveCallbackInterface(); - TestCallbackInterface? receiveNullableCallbackInterface(); - TestCallbackInterface receiveWeakCallbackInterface(); - TestCallbackInterface? receiveWeakNullableCallbackInterface(); - void passCallbackInterface(TestCallbackInterface arg); - void passNullableCallbackInterface(TestCallbackInterface? arg); - attribute TestCallbackInterface nonNullCallbackInterface; - attribute TestCallbackInterface? nullableCallbackInterface; - // Optional arguments - void passOptionalCallbackInterface(optional TestCallbackInterface? arg); - void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); - void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); - - // Miscellaneous interface tests - IndirectlyImplementedInterface receiveConsequentialInterface(); - void passConsequentialInterface(IndirectlyImplementedInterface arg); - - // Sequence types - [Cached, Pure] - readonly attribute sequence readonlySequence; - [Cached, Pure] - readonly attribute sequence readonlySequenceOfDictionaries; - [Cached, Pure] - readonly attribute sequence? readonlyNullableSequenceOfDictionaries; - [Cached, Pure, Frozen] - readonly attribute sequence readonlyFrozenSequence; - [Cached, Pure, Frozen] - readonly attribute sequence? readonlyFrozenNullableSequence; - sequence receiveSequence(); - sequence? receiveNullableSequence(); - sequence receiveSequenceOfNullableInts(); - sequence? receiveNullableSequenceOfNullableInts(); - void passSequence(sequence arg); - void passNullableSequence(sequence? arg); - void passSequenceOfNullableInts(sequence arg); - void passOptionalSequenceOfNullableInts(optional sequence arg); - void passOptionalNullableSequenceOfNullableInts(optional sequence? arg); - sequence receiveCastableObjectSequence(); - sequence receiveCallbackObjectSequence(); - sequence receiveNullableCastableObjectSequence(); - sequence receiveNullableCallbackObjectSequence(); - sequence? receiveCastableObjectNullableSequence(); - sequence? receiveNullableCastableObjectNullableSequence(); - sequence receiveWeakCastableObjectSequence(); - sequence receiveWeakNullableCastableObjectSequence(); - sequence? receiveWeakCastableObjectNullableSequence(); - sequence? receiveWeakNullableCastableObjectNullableSequence(); - void passCastableObjectSequence(sequence arg); - void passNullableCastableObjectSequence(sequence arg); - void passCastableObjectNullableSequence(sequence? arg); - void passNullableCastableObjectNullableSequence(sequence? arg); - void passOptionalSequence(optional sequence arg); - void passOptionalSequenceWithDefaultValue(optional sequence arg = []); - void passOptionalNullableSequence(optional sequence? arg); - void passOptionalNullableSequenceWithDefaultValue(optional sequence? arg = null); - void passOptionalNullableSequenceWithDefaultValue2(optional sequence? arg = []); - void passOptionalObjectSequence(optional sequence arg); - void passExternalInterfaceSequence(sequence arg); - void passNullableExternalInterfaceSequence(sequence arg); - - sequence receiveStringSequence(); - void passStringSequence(sequence arg); - - sequence receiveByteStringSequence(); - void passByteStringSequence(sequence arg); - - sequence receiveAnySequence(); - sequence? receiveNullableAnySequence(); - sequence> receiveAnySequenceSequence(); - - sequence receiveObjectSequence(); - sequence receiveNullableObjectSequence(); - - void passSequenceOfSequences(sequence> arg); - void passSequenceOfSequencesOfSequences(sequence>> arg); - sequence> receiveSequenceOfSequences(); - sequence>> receiveSequenceOfSequencesOfSequences(); - - // MozMap types - void passMozMap(MozMap arg); - void passNullableMozMap(MozMap? arg); - void passMozMapOfNullableInts(MozMap arg); - void passOptionalMozMapOfNullableInts(optional MozMap arg); - void passOptionalNullableMozMapOfNullableInts(optional MozMap? arg); - void passCastableObjectMozMap(MozMap arg); - void passNullableCastableObjectMozMap(MozMap arg); - void passCastableObjectNullableMozMap(MozMap? arg); - void passNullableCastableObjectNullableMozMap(MozMap? arg); - void passOptionalMozMap(optional MozMap arg); - void passOptionalNullableMozMap(optional MozMap? arg); - void passOptionalNullableMozMapWithDefaultValue(optional MozMap? arg = null); - void passOptionalObjectMozMap(optional MozMap arg); - void passExternalInterfaceMozMap(MozMap arg); - void passNullableExternalInterfaceMozMap(MozMap arg); - void passStringMozMap(MozMap arg); - void passByteStringMozMap(MozMap arg); - void passMozMapOfMozMaps(MozMap> arg); - MozMap receiveMozMap(); - MozMap? receiveNullableMozMap(); - MozMap receiveMozMapOfNullableInts(); - MozMap? receiveNullableMozMapOfNullableInts(); - MozMap> receiveMozMapOfMozMaps(); - MozMap receiveAnyMozMap(); - - // Typed array types - void passArrayBuffer(ArrayBuffer arg); - void passNullableArrayBuffer(ArrayBuffer? arg); - void passOptionalArrayBuffer(optional ArrayBuffer arg); - void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); - void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); - void passArrayBufferView(ArrayBufferView arg); - void passInt8Array(Int8Array arg); - void passInt16Array(Int16Array arg); - void passInt32Array(Int32Array arg); - void passUint8Array(Uint8Array arg); - void passUint16Array(Uint16Array arg); - void passUint32Array(Uint32Array arg); - void passUint8ClampedArray(Uint8ClampedArray arg); - void passFloat32Array(Float32Array arg); - void passFloat64Array(Float64Array arg); - void passSequenceOfArrayBuffers(sequence arg); - void passSequenceOfNullableArrayBuffers(sequence arg); - void passMozMapOfArrayBuffers(MozMap arg); - void passMozMapOfNullableArrayBuffers(MozMap arg); - void passVariadicTypedArray(Float32Array... arg); - void passVariadicNullableTypedArray(Float32Array?... arg); - Uint8Array receiveUint8Array(); - attribute Uint8Array uint8ArrayAttr; - - // DOMString types - void passString(DOMString arg); - void passNullableString(DOMString? arg); - void passOptionalString(optional DOMString arg); - void passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); - void passOptionalNullableString(optional DOMString? arg); - void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); - void passVariadicString(DOMString... arg); - DOMString receiveString(); - - // ByteString types - void passByteString(ByteString arg); - void passNullableByteString(ByteString? arg); - void passOptionalByteString(optional ByteString arg); - void passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); - void passOptionalNullableByteString(optional ByteString? arg); - void passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); - void passVariadicByteString(ByteString... arg); - void passOptionalUnionByteString(optional (ByteString or long) arg); - void passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); - - // USVString types - void passUSVS(USVString arg); - void passNullableUSVS(USVString? arg); - void passOptionalUSVS(optional USVString arg); - void passOptionalUSVSWithDefaultValue(optional USVString arg = "abc"); - void passOptionalNullableUSVS(optional USVString? arg); - void passOptionalNullableUSVSWithDefaultValue(optional USVString? arg = null); - void passVariadicUSVS(USVString... arg); - USVString receiveUSVS(); - - // Enumerated types - void passEnum(TestEnum arg); - void passNullableEnum(TestEnum? arg); - void passOptionalEnum(optional TestEnum arg); - void passEnumWithDefault(optional TestEnum arg = "a"); - void passOptionalNullableEnum(optional TestEnum? arg); - void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null); - void passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a"); - TestEnum receiveEnum(); - TestEnum? receiveNullableEnum(); - attribute TestEnum enumAttribute; - readonly attribute TestEnum readonlyEnumAttribute; - - // Callback types - void passCallback(TestCallback arg); - void passNullableCallback(TestCallback? arg); - void passOptionalCallback(optional TestCallback arg); - void passOptionalNullableCallback(optional TestCallback? arg); - void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null); - TestCallback receiveCallback(); - TestCallback? receiveNullableCallback(); - void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); - void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); - void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); - attribute TestTreatAsNullCallback treatAsNullCallback; - attribute TestTreatAsNullCallback? nullableTreatAsNullCallback; - - // Force code generation of the various test callbacks we have. - void forceCallbackGeneration(TestIntegerReturn arg1, - TestNullableIntegerReturn arg2, - TestBooleanReturn arg3, - TestFloatReturn arg4, - TestStringReturn arg5, - TestEnumReturn arg6, - TestInterfaceReturn arg7, - TestNullableInterfaceReturn arg8, - TestExternalInterfaceReturn arg9, - TestNullableExternalInterfaceReturn arg10, - TestCallbackInterfaceReturn arg11, - TestNullableCallbackInterfaceReturn arg12, - TestCallbackReturn arg13, - TestNullableCallbackReturn arg14, - TestObjectReturn arg15, - TestNullableObjectReturn arg16, - TestTypedArrayReturn arg17, - TestNullableTypedArrayReturn arg18, - TestSequenceReturn arg19, - TestNullableSequenceReturn arg20, - TestIntegerArguments arg21, - TestInterfaceArguments arg22, - TestStringEnumArguments arg23, - TestObjectArguments arg24, - TestOptionalArguments arg25); - - // Any types - void passAny(any arg); - void passVariadicAny(any... arg); - void passOptionalAny(optional any arg); - void passAnyDefaultNull(optional any arg = null); - void passSequenceOfAny(sequence arg); - void passNullableSequenceOfAny(sequence? arg); - void passOptionalSequenceOfAny(optional sequence arg); - void passOptionalNullableSequenceOfAny(optional sequence? arg); - void passOptionalSequenceOfAnyWithDefaultValue(optional sequence? arg = null); - void passSequenceOfSequenceOfAny(sequence> arg); - void passSequenceOfNullableSequenceOfAny(sequence?> arg); - void passNullableSequenceOfNullableSequenceOfAny(sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence?>? arg); - void passMozMapOfAny(MozMap arg); - void passNullableMozMapOfAny(MozMap? arg); - void passOptionalMozMapOfAny(optional MozMap arg); - void passOptionalNullableMozMapOfAny(optional MozMap? arg); - void passOptionalMozMapOfAnyWithDefaultValue(optional MozMap? arg = null); - void passMozMapOfMozMapOfAny(MozMap> arg); - void passMozMapOfNullableMozMapOfAny(MozMap?> arg); - void passNullableMozMapOfNullableMozMapOfAny(MozMap?>? arg); - void passOptionalNullableMozMapOfNullableMozMapOfAny(optional MozMap?>? arg); - void passOptionalNullableMozMapOfNullableSequenceOfAny(optional MozMap?>? arg); - void passOptionalNullableSequenceOfNullableMozMapOfAny(optional sequence?>? arg); - any receiveAny(); - - // object types - void passObject(object arg); - void passVariadicObject(object... arg); - void passNullableObject(object? arg); - void passVariadicNullableObject(object... arg); - void passOptionalObject(optional object arg); - void passOptionalNullableObject(optional object? arg); - void passOptionalNullableObjectWithDefaultValue(optional object? arg = null); - void passSequenceOfObject(sequence arg); - void passSequenceOfNullableObject(sequence arg); - void passNullableSequenceOfObject(sequence? arg); - void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence?>? arg); - void passMozMapOfObject(MozMap arg); - object receiveObject(); - object? receiveNullableObject(); - - // Union types - void passUnion((object or long) arg); - // Some union tests are debug-only to avoid creating all those - // unused union types in opt builds. -#ifdef DEBUG - void passUnion2((long or boolean) arg); - void passUnion3((object or long or boolean) arg); - void passUnion4((Node or long or boolean) arg); - void passUnion5((object or boolean) arg); - void passUnion6((object or DOMString) arg); - void passUnion7((object or DOMString or long) arg); - void passUnion8((object or DOMString or boolean) arg); - void passUnion9((object or DOMString or long or boolean) arg); - void passUnion10(optional (EventInit or long) arg); - void passUnion11(optional (CustomEventInit or long) arg); - void passUnion12(optional (EventInit or long) arg = 5); - void passUnion13(optional (object or long?) arg = null); - void passUnion14(optional (object or long?) arg = 5); - void passUnion15((sequence or long) arg); - void passUnion16(optional (sequence or long) arg); - void passUnion17(optional (sequence? or long) arg = 5); - void passUnion18((sequence or long) arg); - void passUnion19(optional (sequence or long) arg); - void passUnion20(optional (sequence or long) arg = []); - void passUnion21((MozMap or long) arg); - void passUnion22((MozMap or long) arg); - void passUnion23((sequence or long) arg); - void passUnion24((sequence or long) arg); - void passUnion25((sequence> or long) arg); - void passUnion26((sequence> or long) arg); - void passUnion27(optional (sequence or EventInit) arg); - void passUnion28(optional (EventInit or sequence) arg); - void passUnionWithCallback((EventHandler or long) arg); - void passUnionWithByteString((ByteString or long) arg); - void passUnionWithMozMap((MozMap or DOMString) arg); - void passUnionWithMozMapAndSequence((MozMap or sequence) arg); - void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithUSVS((USVString or long) arg); -#endif - void passUnionWithNullable((object? or long) arg); - void passNullableUnion((object or long)? arg); - void passOptionalUnion(optional (object or long) arg); - void passOptionalNullableUnion(optional (object or long)? arg); - void passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); - //void passUnionWithInterfaces((TestInterface or TestExternalInterface) arg); - //void passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg); - //void passUnionWithSequence((sequence or long) arg); - void passUnionWithArrayBuffer((ArrayBuffer or long) arg); - void passUnionWithString((DOMString or object) arg); - // Using an enum in a union. Note that we use some enum not declared in our - // binding file, because UnionTypes.h will need to include the binding header - // for this enum. Pick an enum from an interface that won't drag in too much - // stuff. - void passUnionWithEnum((SupportedType or object) arg); - - // Trying to use a callback in a union won't include the test - // headers, unfortunately, so won't compile. - //void passUnionWithCallback((TestCallback or long) arg); - void passUnionWithObject((object or long) arg); - //void passUnionWithDict((Dict or long) arg); - - void passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); - void passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); - void passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); - void passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); - void passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); - void passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); - void passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); - void passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); - void passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); - void passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); - void passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); - void passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); - void passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); - void passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); - void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); - void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); - void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); - void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); - void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); - - void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); - void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); - void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); - void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); - void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); - void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); - void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); - void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); - - void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); - void passSequenceOfUnions2(sequence<(object or long)> arg); - void passVariadicUnion((CanvasPattern or CanvasGradient)... arg); - - void passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); - void passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); - void passMozMapOfUnions(MozMap<(CanvasPattern or CanvasGradient)> arg); - // XXXbz no move constructor on some unions - // void passMozMapOfUnions2(MozMap<(object or long)> arg); - - (CanvasPattern or CanvasGradient) receiveUnion(); - (object or long) receiveUnion2(); - (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); - (CanvasPattern or CanvasGradient)? receiveNullableUnion(); - (object or long)? receiveNullableUnion2(); - - attribute (CanvasPattern or CanvasGradient) writableUnion; - attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; - attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; - - // Date types - void passDate(Date arg); - void passNullableDate(Date? arg); - void passOptionalDate(optional Date arg); - void passOptionalNullableDate(optional Date? arg); - void passOptionalNullableDateWithDefaultValue(optional Date? arg = null); - void passDateSequence(sequence arg); - void passNullableDateSequence(sequence arg); - void passDateMozMap(MozMap arg); - Date receiveDate(); - Date? receiveNullableDate(); - - // Promise types - void passPromise(Promise arg); - void passNullablePromise(Promise? arg); - void passOptionalPromise(optional Promise arg); - void passOptionalNullablePromise(optional Promise? arg); - void passOptionalNullablePromiseWithDefaultValue(optional Promise? arg = null); - void passPromiseSequence(sequence> arg); - void passNullablePromiseSequence(sequence?> arg); - Promise receivePromise(); - Promise receiveAddrefedPromise(); - - // binaryNames tests - void methodRenamedFrom(); - [BinaryName="otherMethodRenamedTo"] - void otherMethodRenamedFrom(); - void methodRenamedFrom(byte argument); - readonly attribute byte attributeGetterRenamedFrom; - attribute byte attributeRenamedFrom; - [BinaryName="otherAttributeRenamedTo"] - attribute byte otherAttributeRenamedFrom; - - void passDictionary(optional Dict x); - void passDictionary2(Dict x); - [Cached, Pure] - readonly attribute Dict readonlyDictionary; - [Cached, Pure] - readonly attribute Dict? readonlyNullableDictionary; - [Cached, Pure] - attribute Dict writableDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict readonlyFrozenDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict? readonlyFrozenNullableDictionary; - [Cached, Pure, Frozen] - attribute Dict writableFrozenDictionary; - Dict receiveDictionary(); - Dict? receiveNullableDictionary(); - void passOtherDictionary(optional GrandparentDict x); - void passSequenceOfDictionaries(sequence x); - void passMozMapOfDictionaries(MozMap x); - // No support for nullable dictionaries inside a sequence (nor should there be) - // void passSequenceOfNullableDictionaries(sequence x); - void passDictionaryOrLong(optional Dict x); - void passDictionaryOrLong(long x); - - void passDictContainingDict(optional DictContainingDict arg); - void passDictContainingSequence(optional DictContainingSequence arg); - DictContainingSequence receiveDictContainingSequence(); - void passVariadicDictionary(Dict... arg); - - // EnforceRange/Clamp tests - void dontEnforceRangeOrClamp(byte arg); - void doEnforceRange([EnforceRange] byte arg); - void doClamp([Clamp] byte arg); - [EnforceRange] attribute byte enforcedByte; - [Clamp] attribute byte clampedByte; - - // Typedefs - const myLong myLongConstant = 5; - void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg); - AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg); - void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg); - - // Deprecated methods and attributes - [Deprecated="GetAttributeNode"] - attribute byte deprecatedAttribute; - [Deprecated="GetAttributeNode"] - byte deprecatedMethod(); - [Deprecated="GetAttributeNode"] - byte deprecatedMethodWithContext(any arg); - - // Static methods and attributes - static attribute boolean staticAttribute; - static void staticMethod(boolean arg); - static void staticMethodWithContext(any arg); - - // Testing static method with a reserved C++ keyword as the name - static void assert(boolean arg); - - // Deprecated static methods and attributes - [Deprecated="GetAttributeNode"] - static attribute byte staticDeprecatedAttribute; - [Deprecated="GetAttributeNode"] - static void staticDeprecatedMethod(); - [Deprecated="GetAttributeNode"] - static void staticDeprecatedMethodWithContext(any arg); - - // Overload resolution tests - //void overload1(DOMString... strs); - boolean overload1(TestInterface arg); - TestInterface overload1(DOMString strs, TestInterface arg); - void overload2(TestInterface arg); - void overload2(optional Dict arg); - void overload2(boolean arg); - void overload2(DOMString arg); - void overload2(Date arg); - void overload3(TestInterface arg); - void overload3(TestCallback arg); - void overload3(boolean arg); - void overload4(TestInterface arg); - void overload4(TestCallbackInterface arg); - void overload4(DOMString arg); - void overload5(long arg); - void overload5(TestEnum arg); - void overload6(long arg); - void overload6(boolean arg); - void overload7(long arg); - void overload7(boolean arg); - void overload7(ByteString arg); - void overload8(long arg); - void overload8(TestInterface arg); - void overload9(long? arg); - void overload9(DOMString arg); - void overload10(long? arg); - void overload10(object arg); - void overload11(long arg); - void overload11(DOMString? arg); - void overload12(long arg); - void overload12(boolean? arg); - void overload13(long? arg); - void overload13(boolean arg); - void overload14(optional long arg); - void overload14(TestInterface arg); - void overload15(long arg); - void overload15(optional TestInterface arg); - void overload16(long arg); - void overload16(optional TestInterface? arg); - void overload17(sequence arg); - void overload17(MozMap arg); - void overload18(MozMap arg); - void overload18(sequence arg); - void overload19(sequence arg); - void overload19(optional Dict arg); - void overload20(optional Dict arg); - void overload20(sequence arg); - - // Variadic handling - void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); - - // Conditionally exposed methods/attributes - [Pref="abc.def"] - readonly attribute boolean prefable1; - [Pref="abc.def"] - readonly attribute boolean prefable2; - [Pref="ghi.jkl"] - readonly attribute boolean prefable3; - [Pref="ghi.jkl"] - readonly attribute boolean prefable4; - [Pref="abc.def"] - readonly attribute boolean prefable5; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable6; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable7; - [Pref="ghi.jkl", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable8; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable9; - [Pref="abc.def"] - void prefable10(); - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable11(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable12; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable13(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable14; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable15; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable16; - [Pref="abc.def", Func="TestFuncControlledMember"] - void prefable17(); - [Func="TestFuncControlledMember"] - void prefable18(); - [Func="TestFuncControlledMember"] - void prefable19(); - [Pref="abc.def", Func="TestFuncControlledMember", ChromeOnly] - void prefable20(); - - // Conditionally exposed methods/attributes involving [SecureContext] - [SecureContext] - readonly attribute boolean conditionalOnSecureContext1; - [SecureContext, Pref="abc.def"] - readonly attribute boolean conditionalOnSecureContext2; - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean conditionalOnSecureContext3; - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean conditionalOnSecureContext4; - [SecureContext] - void conditionalOnSecureContext5(); - [SecureContext, Pref="abc.def"] - void conditionalOnSecureContext6(); - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void conditionalOnSecureContext7(); - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - void conditionalOnSecureContext8(); - - // Miscellania - [LenientThis] attribute long attrWithLenientThis; - [Unforgeable] readonly attribute long unforgeableAttr; - [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; - [Unforgeable] long unforgeableMethod(); - [Unforgeable, ChromeOnly] long unforgeableMethod2(); - stringifier; - void passRenamedInterface(TestRenamedInterface arg); - [PutForwards=writableByte] readonly attribute TestInterface putForwardsAttr; - [PutForwards=writableByte, LenientThis] readonly attribute TestInterface putForwardsAttr2; - [PutForwards=writableByte, ChromeOnly] readonly attribute TestInterface putForwardsAttr3; - [Throws] void throwingMethod(); - [Throws] attribute boolean throwingAttr; - [GetterThrows] attribute boolean throwingGetterAttr; - [SetterThrows] attribute boolean throwingSetterAttr; - [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod(); - [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; - [NeedsCallerType] void needsCallerTypeMethod(); - [NeedsCallerType] attribute boolean needsCallerTypeAttr; - [CEReactions] void ceReactionsMethod(); - [CEReactions] void ceReactionsMethodOverload(); - [CEReactions] void ceReactionsMethodOverload(DOMString bar); - [CEReactions] attribute boolean ceReactionsAttr; - legacycaller short(unsigned long arg1, TestInterface arg2); - void passArgsWithDefaults(optional long arg1, - optional TestInterface? arg2 = null, - optional Dict arg3, optional double arg4 = 5.0, - optional float arg5); - - attribute any jsonifierShouldSkipThis; - attribute TestParentInterface jsonifierShouldSkipThis2; - attribute TestCallbackInterface jsonifierShouldSkipThis3; - jsonifier; - - attribute byte dashed-attribute; - void dashed-method(); - - // If you add things here, add them to TestExampleGen and TestJSImplGen as well -}; - -interface TestParentInterface { -}; - -interface TestChildInterface : TestParentInterface { -}; - -interface TestNonWrapperCacheInterface { -}; - -[NoInterfaceObject] -interface ImplementedInterfaceParent { - void implementedParentMethod(); - attribute boolean implementedParentProperty; - - const long implementedParentConstant = 8; -}; - -ImplementedInterfaceParent implements IndirectlyImplementedInterface; - -[NoInterfaceObject] -interface IndirectlyImplementedInterface { - void indirectlyImplementedMethod(); - attribute boolean indirectlyImplementedProperty; - - const long indirectlyImplementedConstant = 9; -}; - -[NoInterfaceObject] -interface ImplementedInterface : ImplementedInterfaceParent { - void implementedMethod(); - attribute boolean implementedProperty; - - const long implementedConstant = 5; -}; - -[NoInterfaceObject] -interface DiamondImplements { - readonly attribute long diamondImplementedProperty; -}; -[NoInterfaceObject] -interface DiamondBranch1A { -}; -[NoInterfaceObject] -interface DiamondBranch1B { -}; -[NoInterfaceObject] -interface DiamondBranch2A : DiamondImplements { -}; -[NoInterfaceObject] -interface DiamondBranch2B : DiamondImplements { -}; -TestInterface implements DiamondBranch1A; -TestInterface implements DiamondBranch1B; -TestInterface implements DiamondBranch2A; -TestInterface implements DiamondBranch2B; -DiamondBranch1A implements DiamondImplements; -DiamondBranch1B implements DiamondImplements; - -dictionary Dict : ParentDict { - TestEnum someEnum; - long x; - long a; - long b = 8; - long z = 9; - [EnforceRange] unsigned long enforcedUnsignedLong; - [Clamp] unsigned long clampedUnsignedLong; - DOMString str; - DOMString empty = ""; - TestEnum otherEnum = "b"; - DOMString otherStr = "def"; - DOMString? yetAnotherStr = null; - DOMString template; - ByteString byteStr; - ByteString emptyByteStr = ""; - ByteString otherByteStr = "def"; - object someObj; - boolean prototype; - object? anotherObj = null; - TestCallback? someCallback = null; - any someAny; - any anotherAny = null; - - unrestricted float urFloat = 0; - unrestricted float urFloat2 = 1.1; - unrestricted float urFloat3 = -1.1; - unrestricted float? urFloat4 = null; - unrestricted float infUrFloat = Infinity; - unrestricted float negativeInfUrFloat = -Infinity; - unrestricted float nanUrFloat = NaN; - - unrestricted double urDouble = 0; - unrestricted double urDouble2 = 1.1; - unrestricted double urDouble3 = -1.1; - unrestricted double? urDouble4 = null; - unrestricted double infUrDouble = Infinity; - unrestricted double negativeInfUrDouble = -Infinity; - unrestricted double nanUrDouble = NaN; - - (float or DOMString) floatOrString = "str"; - (float or DOMString)? nullableFloatOrString = "str"; - (object or long) objectOrLong; -#ifdef DEBUG - (EventInit or long) eventInitOrLong; - (EventInit or long)? nullableEventInitOrLong; - (HTMLElement or long)? nullableHTMLElementOrLong; - // CustomEventInit is useful to test because it needs rooting. - (CustomEventInit or long) eventInitOrLong2; - (CustomEventInit or long)? nullableEventInitOrLong2; - (EventInit or long) eventInitOrLongWithDefaultValue = null; - (CustomEventInit or long) eventInitOrLongWithDefaultValue2 = null; - (EventInit or long) eventInitOrLongWithDefaultValue3 = 5; - (CustomEventInit or long) eventInitOrLongWithDefaultValue4 = 5; - (EventInit or long)? nullableEventInitOrLongWithDefaultValue = null; - (CustomEventInit or long)? nullableEventInitOrLongWithDefaultValue2 = null; - (EventInit or long)? nullableEventInitOrLongWithDefaultValue3 = 5; - (CustomEventInit or long)? nullableEventInitOrLongWithDefaultValue4 = 5; - (sequence or long) objectSequenceOrLong; - (sequence or long) objectSequenceOrLongWithDefaultValue1 = 1; - (sequence or long) objectSequenceOrLongWithDefaultValue2 = []; - (sequence or long)? nullableObjectSequenceOrLong; - (sequence or long)? nullableObjectSequenceOrLongWithDefaultValue1 = 1; - (sequence or long)? nullableObjectSequenceOrLongWithDefaultValue2 = []; -#endif - - ArrayBuffer arrayBuffer; - ArrayBuffer? nullableArrayBuffer; - Uint8Array uint8Array; - Float64Array? float64Array = null; - - sequence seq1; - sequence seq2 = []; - sequence? seq3; - sequence? seq4 = null; - sequence? seq5 = []; - - long dashed-name; - - required long requiredLong; - required object requiredObject; - - CustomEventInit customEventInit; - TestDictionaryTypedef dictionaryTypedef; - - Promise promise; - sequence> promiseSequence; -}; - -dictionary ParentDict : GrandparentDict { - long c = 5; - TestInterface someInterface; - TestInterface? someNullableInterface = null; - TestExternalInterface someExternalInterface; - any parentAny; -}; - -dictionary DictContainingDict { - Dict memberDict; -}; - -dictionary DictContainingSequence { - sequence ourSequence; - sequence ourSequence2; - sequence ourSequence3; - sequence ourSequence4; - sequence ourSequence5; - sequence? ourSequence6; - sequence? ourSequence7; - sequence? ourSequence8 = null; - sequence? ourSequence9 = null; - sequence<(float or DOMString)> ourSequence10; -}; - -dictionary DictForConstructor { - Dict dict; - DictContainingDict dict2; - sequence seq1; - sequence>? seq2; - sequence?> seq3; - sequence seq4; - sequence seq5; - sequence seq6; - object obj1; - object? obj2; - any any1 = null; -}; - -dictionary DictWithConditionalMembers { - [ChromeOnly] - long chromeOnlyMember; - [Func="TestFuncControlledMember"] - long funcControlledMember; - [ChromeOnly, Func="nsGenericHTMLElement::TouchEventsEnabled"] - long chromeOnlyFuncControlledMember; -}; - -interface TestIndexedGetterInterface { - getter long item(unsigned long idx); - readonly attribute unsigned long length; - legacycaller void(); -}; - -interface TestNamedGetterInterface { - getter DOMString (DOMString name); -}; - -interface TestIndexedGetterAndSetterAndNamedGetterInterface { - getter DOMString (DOMString myName); - getter long (unsigned long index); - setter creator void (unsigned long index, long arg); -}; - -interface TestIndexedAndNamedGetterInterface { - getter long (unsigned long index); - getter DOMString namedItem(DOMString name); - readonly attribute unsigned long length; -}; - -interface TestIndexedSetterInterface { - setter creator void setItem(unsigned long idx, DOMString item); - getter DOMString (unsigned long idx); -}; - -interface TestNamedSetterInterface { - setter creator void (DOMString myName, TestIndexedSetterInterface item); - getter TestIndexedSetterInterface (DOMString name); -}; - -interface TestIndexedAndNamedSetterInterface { - setter creator void (unsigned long index, TestIndexedSetterInterface item); - getter TestIndexedSetterInterface (unsigned long index); - setter creator void setNamedItem(DOMString name, TestIndexedSetterInterface item); - getter TestIndexedSetterInterface (DOMString name); -}; - -interface TestIndexedAndNamedGetterAndSetterInterface : TestIndexedSetterInterface { - getter long item(unsigned long index); - getter DOMString namedItem(DOMString name); - setter creator void (unsigned long index, long item); - setter creator void (DOMString name, DOMString item); - stringifier DOMString (); - readonly attribute unsigned long length; -}; - -interface TestNamedDeleterInterface { - deleter void (DOMString name); - getter long (DOMString name); -}; - -interface TestNamedDeleterWithRetvalInterface { - deleter boolean delNamedItem(DOMString name); - getter long (DOMString name); -}; - -interface TestCppKeywordNamedMethodsInterface { - boolean continue(); - boolean delete(); - long volatile(); -}; - -[Deprecated="GetAttributeNode", Constructor()] -interface TestDeprecatedInterface { - static void alsoDeprecated(); -}; - - -[Constructor(Promise promise)] -interface TestInterfaceWithPromiseConstructorArg { -}; - -namespace TestNamespace { - readonly attribute boolean foo; - long bar(); -}; - -partial namespace TestNamespace { - void baz(); -}; - -[ClassString="RenamedNamespaceClassName"] -namespace TestRenamedNamespace { -}; - -[ProtoObjectHack] -namespace TestProtoObjectHackedNamespace { -}; - -[SecureContext] -interface TestSecureContextInterface { - static void alsoSecureContext(); -}; - -[Exposed=(Window,Worker)] -interface TestWorkerExposedInterface { - [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod(); - [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; - [NeedsCallerType] void needsCallerTypeMethod(); - [NeedsCallerType] attribute boolean needsCallerTypeAttr; -}; - -[HTMLConstructor] -interface TestHTMLConstructorInterface { -}; - -interface TestCEReactionsInterface { - [CEReactions] setter creator void (unsigned long index, long item); - [CEReactions] setter creator void (DOMString name, DOMString item); - [CEReactions] deleter void (DOMString name); - getter long item(unsigned long index); - getter DOMString (DOMString name); - readonly attribute unsigned long length; -}; diff --git a/dom/bindings/test/TestDictionary.webidl b/dom/bindings/test/TestDictionary.webidl deleted file mode 100644 index 3dd91bd650..0000000000 --- a/dom/bindings/test/TestDictionary.webidl +++ /dev/null @@ -1,9 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -dictionary GrandparentDict { - double someNum; -}; \ No newline at end of file diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl deleted file mode 100644 index a2183c0026..0000000000 --- a/dom/bindings/test/TestExampleGen.webidl +++ /dev/null @@ -1,815 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ -[Constructor, - Constructor(DOMString str), - Constructor(unsigned long num, boolean? boolArg), - Constructor(TestInterface? iface), - Constructor(long arg1, IndirectlyImplementedInterface iface), - Constructor(Date arg1), - Constructor(ArrayBuffer arrayBuf), - Constructor(Uint8Array typedArr), - // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3), - NamedConstructor=Example, - NamedConstructor=Example(DOMString str), - NamedConstructor=Example2(DictForConstructor dict, any any1, object obj1, - object? obj2, sequence seq, optional any any2, - optional object obj3, optional object? obj4), - NamedConstructor=Example2((long or MozMap) arg1) - ] -interface TestExampleInterface { - // Integer types - // XXXbz add tests for throwing versions of all the integer stuff - readonly attribute byte readonlyByte; - attribute byte writableByte; - void passByte(byte arg); - byte receiveByte(); - void passOptionalByte(optional byte arg); - void passOptionalByteBeforeRequired(optional byte arg1, byte arg2); - void passOptionalByteWithDefault(optional byte arg = 0); - void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); - void passNullableByte(byte? arg); - void passOptionalNullableByte(optional byte? arg); - void passVariadicByte(byte... arg); - [Cached, Pure] - readonly attribute byte cachedByte; - [StoreInSlot, Constant] - readonly attribute byte cachedConstantByte; - [Cached, Pure] - attribute byte cachedWritableByte; - [Affects=Nothing] - attribute byte sideEffectFreeByte; - [Affects=Nothing, DependsOn=DOMState] - attribute byte domDependentByte; - [Affects=Nothing, DependsOn=Nothing] - readonly attribute byte constantByte; - [DependsOn=DeviceState, Affects=Nothing] - readonly attribute byte deviceStateDependentByte; - [Affects=Nothing] - byte returnByteSideEffectFree(); - [Affects=Nothing, DependsOn=DOMState] - byte returnDOMDependentByte(); - [Affects=Nothing, DependsOn=Nothing] - byte returnConstantByte(); - [DependsOn=DeviceState, Affects=Nothing] - byte returnDeviceStateDependentByte(); - - readonly attribute short readonlyShort; - attribute short writableShort; - void passShort(short arg); - short receiveShort(); - void passOptionalShort(optional short arg); - void passOptionalShortWithDefault(optional short arg = 5); - - readonly attribute long readonlyLong; - attribute long writableLong; - void passLong(long arg); - long receiveLong(); - void passOptionalLong(optional long arg); - void passOptionalLongWithDefault(optional long arg = 7); - - readonly attribute long long readonlyLongLong; - attribute long long writableLongLong; - void passLongLong(long long arg); - long long receiveLongLong(); - void passOptionalLongLong(optional long long arg); - void passOptionalLongLongWithDefault(optional long long arg = -12); - - readonly attribute octet readonlyOctet; - attribute octet writableOctet; - void passOctet(octet arg); - octet receiveOctet(); - void passOptionalOctet(optional octet arg); - void passOptionalOctetWithDefault(optional octet arg = 19); - - readonly attribute unsigned short readonlyUnsignedShort; - attribute unsigned short writableUnsignedShort; - void passUnsignedShort(unsigned short arg); - unsigned short receiveUnsignedShort(); - void passOptionalUnsignedShort(optional unsigned short arg); - void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); - - readonly attribute unsigned long readonlyUnsignedLong; - attribute unsigned long writableUnsignedLong; - void passUnsignedLong(unsigned long arg); - unsigned long receiveUnsignedLong(); - void passOptionalUnsignedLong(optional unsigned long arg); - void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); - - readonly attribute unsigned long long readonlyUnsignedLongLong; - attribute unsigned long long writableUnsignedLongLong; - void passUnsignedLongLong(unsigned long long arg); - unsigned long long receiveUnsignedLongLong(); - void passOptionalUnsignedLongLong(optional unsigned long long arg); - void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); - - attribute float writableFloat; - attribute unrestricted float writableUnrestrictedFloat; - attribute float? writableNullableFloat; - attribute unrestricted float? writableNullableUnrestrictedFloat; - attribute double writableDouble; - attribute unrestricted double writableUnrestrictedDouble; - attribute double? writableNullableDouble; - attribute unrestricted double? writableNullableUnrestrictedDouble; - void passFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, sequence arg10, - sequence arg11, sequence arg12, - sequence arg13, sequence arg14, - sequence arg15, sequence arg16); - [LenientFloat] - void passLenientFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, - sequence arg10, - sequence arg11, - sequence arg12, - sequence arg13, - sequence arg14, - sequence arg15, - sequence arg16); - [LenientFloat] - attribute float lenientFloatAttr; - [LenientFloat] - attribute double lenientDoubleAttr; - - // Castable interface types - // XXXbz add tests for throwing versions of all the castable interface stuff - TestInterface receiveSelf(); - TestInterface? receiveNullableSelf(); - TestInterface receiveWeakSelf(); - TestInterface? receiveWeakNullableSelf(); - void passSelf(TestInterface arg); - void passNullableSelf(TestInterface? arg); - attribute TestInterface nonNullSelf; - attribute TestInterface? nullableSelf; - [Cached, Pure] - readonly attribute TestInterface cachedSelf; - // Optional arguments - void passOptionalSelf(optional TestInterface? arg); - void passOptionalNonNullSelf(optional TestInterface arg); - void passOptionalSelfWithDefault(optional TestInterface? arg = null); - - // Non-wrapper-cache interface types - [NewObject] - TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); - [NewObject] - TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); - [NewObject] - sequence receiveNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence receiveNullableNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence? receiveNonWrapperCacheInterfaceNullableSequence(); - [NewObject] - sequence? receiveNullableNonWrapperCacheInterfaceNullableSequence(); - - // Non-castable interface types - IndirectlyImplementedInterface receiveOther(); - IndirectlyImplementedInterface? receiveNullableOther(); - IndirectlyImplementedInterface receiveWeakOther(); - IndirectlyImplementedInterface? receiveWeakNullableOther(); - void passOther(IndirectlyImplementedInterface arg); - void passNullableOther(IndirectlyImplementedInterface? arg); - attribute IndirectlyImplementedInterface nonNullOther; - attribute IndirectlyImplementedInterface? nullableOther; - // Optional arguments - void passOptionalOther(optional IndirectlyImplementedInterface? arg); - void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg); - void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null); - - // External interface types - TestExternalInterface receiveExternal(); - TestExternalInterface? receiveNullableExternal(); - TestExternalInterface receiveWeakExternal(); - TestExternalInterface? receiveWeakNullableExternal(); - void passExternal(TestExternalInterface arg); - void passNullableExternal(TestExternalInterface? arg); - attribute TestExternalInterface nonNullExternal; - attribute TestExternalInterface? nullableExternal; - // Optional arguments - void passOptionalExternal(optional TestExternalInterface? arg); - void passOptionalNonNullExternal(optional TestExternalInterface arg); - void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); - - // Callback interface types - TestCallbackInterface receiveCallbackInterface(); - TestCallbackInterface? receiveNullableCallbackInterface(); - TestCallbackInterface receiveWeakCallbackInterface(); - TestCallbackInterface? receiveWeakNullableCallbackInterface(); - void passCallbackInterface(TestCallbackInterface arg); - void passNullableCallbackInterface(TestCallbackInterface? arg); - attribute TestCallbackInterface nonNullCallbackInterface; - attribute TestCallbackInterface? nullableCallbackInterface; - // Optional arguments - void passOptionalCallbackInterface(optional TestCallbackInterface? arg); - void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); - void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); - - // Miscellaneous interface tests - IndirectlyImplementedInterface receiveConsequentialInterface(); - void passConsequentialInterface(IndirectlyImplementedInterface arg); - - // Sequence types - [Cached, Pure] - readonly attribute sequence readonlySequence; - [Cached, Pure] - readonly attribute sequence readonlySequenceOfDictionaries; - [Cached, Pure] - readonly attribute sequence? readonlyNullableSequenceOfDictionaries; - [Cached, Pure, Frozen] - readonly attribute sequence readonlyFrozenSequence; - [Cached, Pure, Frozen] - readonly attribute sequence? readonlyFrozenNullableSequence; - sequence receiveSequence(); - sequence? receiveNullableSequence(); - sequence receiveSequenceOfNullableInts(); - sequence? receiveNullableSequenceOfNullableInts(); - void passSequence(sequence arg); - void passNullableSequence(sequence? arg); - void passSequenceOfNullableInts(sequence arg); - void passOptionalSequenceOfNullableInts(optional sequence arg); - void passOptionalNullableSequenceOfNullableInts(optional sequence? arg); - sequence receiveCastableObjectSequence(); - sequence receiveCallbackObjectSequence(); - sequence receiveNullableCastableObjectSequence(); - sequence receiveNullableCallbackObjectSequence(); - sequence? receiveCastableObjectNullableSequence(); - sequence? receiveNullableCastableObjectNullableSequence(); - sequence receiveWeakCastableObjectSequence(); - sequence receiveWeakNullableCastableObjectSequence(); - sequence? receiveWeakCastableObjectNullableSequence(); - sequence? receiveWeakNullableCastableObjectNullableSequence(); - void passCastableObjectSequence(sequence arg); - void passNullableCastableObjectSequence(sequence arg); - void passCastableObjectNullableSequence(sequence? arg); - void passNullableCastableObjectNullableSequence(sequence? arg); - void passOptionalSequence(optional sequence arg); - void passOptionalSequenceWithDefaultValue(optional sequence arg = []); - void passOptionalNullableSequence(optional sequence? arg); - void passOptionalNullableSequenceWithDefaultValue(optional sequence? arg = null); - void passOptionalNullableSequenceWithDefaultValue2(optional sequence? arg = []); - void passOptionalObjectSequence(optional sequence arg); - void passExternalInterfaceSequence(sequence arg); - void passNullableExternalInterfaceSequence(sequence arg); - - sequence receiveStringSequence(); - void passStringSequence(sequence arg); - - sequence receiveByteStringSequence(); - void passByteStringSequence(sequence arg); - - sequence receiveAnySequence(); - sequence? receiveNullableAnySequence(); - //XXXbz No support for sequence of sequence return values yet. - //sequence> receiveAnySequenceSequence(); - - sequence receiveObjectSequence(); - sequence receiveNullableObjectSequence(); - - void passSequenceOfSequences(sequence> arg); - void passSequenceOfSequencesOfSequences(sequence>> arg); - //XXXbz No support for sequence of sequence return values yet. - //sequence> receiveSequenceOfSequences(); - - // MozMap types - void passMozMap(MozMap arg); - void passNullableMozMap(MozMap? arg); - void passMozMapOfNullableInts(MozMap arg); - void passOptionalMozMapOfNullableInts(optional MozMap arg); - void passOptionalNullableMozMapOfNullableInts(optional MozMap? arg); - void passCastableObjectMozMap(MozMap arg); - void passNullableCastableObjectMozMap(MozMap arg); - void passCastableObjectNullableMozMap(MozMap? arg); - void passNullableCastableObjectNullableMozMap(MozMap? arg); - void passOptionalMozMap(optional MozMap arg); - void passOptionalNullableMozMap(optional MozMap? arg); - void passOptionalNullableMozMapWithDefaultValue(optional MozMap? arg = null); - void passOptionalObjectMozMap(optional MozMap arg); - void passExternalInterfaceMozMap(MozMap arg); - void passNullableExternalInterfaceMozMap(MozMap arg); - void passStringMozMap(MozMap arg); - void passByteStringMozMap(MozMap arg); - void passMozMapOfMozMaps(MozMap> arg); - MozMap receiveMozMap(); - MozMap? receiveNullableMozMap(); - MozMap receiveMozMapOfNullableInts(); - MozMap? receiveNullableMozMapOfNullableInts(); - //XXXbz No support for MozMap of MozMaps return values yet. - //MozMap> receiveMozMapOfMozMaps(); - MozMap receiveAnyMozMap(); - - // Typed array types - void passArrayBuffer(ArrayBuffer arg); - void passNullableArrayBuffer(ArrayBuffer? arg); - void passOptionalArrayBuffer(optional ArrayBuffer arg); - void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); - void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); - void passArrayBufferView(ArrayBufferView arg); - void passInt8Array(Int8Array arg); - void passInt16Array(Int16Array arg); - void passInt32Array(Int32Array arg); - void passUint8Array(Uint8Array arg); - void passUint16Array(Uint16Array arg); - void passUint32Array(Uint32Array arg); - void passUint8ClampedArray(Uint8ClampedArray arg); - void passFloat32Array(Float32Array arg); - void passFloat64Array(Float64Array arg); - void passSequenceOfArrayBuffers(sequence arg); - void passSequenceOfNullableArrayBuffers(sequence arg); - void passMozMapOfArrayBuffers(MozMap arg); - void passMozMapOfNullableArrayBuffers(MozMap arg); - void passVariadicTypedArray(Float32Array... arg); - void passVariadicNullableTypedArray(Float32Array?... arg); - Uint8Array receiveUint8Array(); - attribute Uint8Array uint8ArrayAttr; - - // DOMString types - void passString(DOMString arg); - void passNullableString(DOMString? arg); - void passOptionalString(optional DOMString arg); - void passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); - void passOptionalNullableString(optional DOMString? arg); - void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); - void passVariadicString(DOMString... arg); - - // ByteString types - void passByteString(ByteString arg); - void passNullableByteString(ByteString? arg); - void passOptionalByteString(optional ByteString arg); - void passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); - void passOptionalNullableByteString(optional ByteString? arg); - void passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); - void passVariadicByteString(ByteString... arg); - void passUnionByteString((ByteString or long) arg); - void passOptionalUnionByteString(optional (ByteString or long) arg); - void passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); - - // USVString types - void passSVS(USVString arg); - void passNullableSVS(USVString? arg); - void passOptionalSVS(optional USVString arg); - void passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); - void passOptionalNullableSVS(optional USVString? arg); - void passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); - void passVariadicSVS(USVString... arg); - USVString receiveSVS(); - - // Enumerated types - void passEnum(TestEnum arg); - void passNullableEnum(TestEnum? arg); - void passOptionalEnum(optional TestEnum arg); - void passEnumWithDefault(optional TestEnum arg = "a"); - void passOptionalNullableEnum(optional TestEnum? arg); - void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null); - void passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a"); - TestEnum receiveEnum(); - TestEnum? receiveNullableEnum(); - attribute TestEnum enumAttribute; - readonly attribute TestEnum readonlyEnumAttribute; - - // Callback types - void passCallback(TestCallback arg); - void passNullableCallback(TestCallback? arg); - void passOptionalCallback(optional TestCallback arg); - void passOptionalNullableCallback(optional TestCallback? arg); - void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null); - TestCallback receiveCallback(); - TestCallback? receiveNullableCallback(); - void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); - void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); - void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); - - // Any types - void passAny(any arg); - void passVariadicAny(any... arg); - void passOptionalAny(optional any arg); - void passAnyDefaultNull(optional any arg = null); - void passSequenceOfAny(sequence arg); - void passNullableSequenceOfAny(sequence? arg); - void passOptionalSequenceOfAny(optional sequence arg); - void passOptionalNullableSequenceOfAny(optional sequence? arg); - void passOptionalSequenceOfAnyWithDefaultValue(optional sequence? arg = null); - void passSequenceOfSequenceOfAny(sequence> arg); - void passSequenceOfNullableSequenceOfAny(sequence?> arg); - void passNullableSequenceOfNullableSequenceOfAny(sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence?>? arg); - void passMozMapOfAny(MozMap arg); - void passNullableMozMapOfAny(MozMap? arg); - void passOptionalMozMapOfAny(optional MozMap arg); - void passOptionalNullableMozMapOfAny(optional MozMap? arg); - void passOptionalMozMapOfAnyWithDefaultValue(optional MozMap? arg = null); - void passMozMapOfMozMapOfAny(MozMap> arg); - void passMozMapOfNullableMozMapOfAny(MozMap?> arg); - void passNullableMozMapOfNullableMozMapOfAny(MozMap?>? arg); - void passOptionalNullableMozMapOfNullableMozMapOfAny(optional MozMap?>? arg); - void passOptionalNullableMozMapOfNullableSequenceOfAny(optional MozMap?>? arg); - void passOptionalNullableSequenceOfNullableMozMapOfAny(optional sequence?>? arg); - any receiveAny(); - - // object types - void passObject(object arg); - void passVariadicObject(object... arg); - void passNullableObject(object? arg); - void passVariadicNullableObject(object... arg); - void passOptionalObject(optional object arg); - void passOptionalNullableObject(optional object? arg); - void passOptionalNullableObjectWithDefaultValue(optional object? arg = null); - void passSequenceOfObject(sequence arg); - void passSequenceOfNullableObject(sequence arg); - void passNullableSequenceOfObject(sequence? arg); - void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence?>? arg); - void passMozMapOfObject(MozMap arg); - object receiveObject(); - object? receiveNullableObject(); - - // Union types - void passUnion((object or long) arg); - // Some union tests are debug-only to avoid creating all those - // unused union types in opt builds. -#ifdef DEBUG - void passUnion2((long or boolean) arg); - void passUnion3((object or long or boolean) arg); - void passUnion4((Node or long or boolean) arg); - void passUnion5((object or boolean) arg); - void passUnion6((object or DOMString) arg); - void passUnion7((object or DOMString or long) arg); - void passUnion8((object or DOMString or boolean) arg); - void passUnion9((object or DOMString or long or boolean) arg); - void passUnion10(optional (EventInit or long) arg); - void passUnion11(optional (CustomEventInit or long) arg); - void passUnion12(optional (EventInit or long) arg = 5); - void passUnion13(optional (object or long?) arg = null); - void passUnion14(optional (object or long?) arg = 5); - void passUnion15((sequence or long) arg); - void passUnion16(optional (sequence or long) arg); - void passUnion17(optional (sequence? or long) arg = 5); - void passUnion18((sequence or long) arg); - void passUnion19(optional (sequence or long) arg); - void passUnion20(optional (sequence or long) arg = []); - void passUnion21((MozMap or long) arg); - void passUnion22((MozMap or long) arg); - void passUnion23((sequence or long) arg); - void passUnion24((sequence or long) arg); - void passUnion25((sequence> or long) arg); - void passUnion26((sequence> or long) arg); - void passUnion27(optional (sequence or EventInit) arg); - void passUnion28(optional (EventInit or sequence) arg); - void passUnionWithCallback((EventHandler or long) arg); - void passUnionWithByteString((ByteString or long) arg); - void passUnionWithMozMap((MozMap or DOMString) arg); - void passUnionWithMozMapAndSequence((MozMap or sequence) arg); - void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithSVS((USVString or long) arg); -#endif - void passUnionWithNullable((object? or long) arg); - void passNullableUnion((object or long)? arg); - void passOptionalUnion(optional (object or long) arg); - void passOptionalNullableUnion(optional (object or long)? arg); - void passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); - //void passUnionWithInterfaces((TestInterface or TestExternalInterface) arg); - //void passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg); - //void passUnionWithSequence((sequence or long) arg); - void passUnionWithArrayBuffer((ArrayBuffer or long) arg); - void passUnionWithString((DOMString or object) arg); - // Using an enum in a union. Note that we use some enum not declared in our - // binding file, because UnionTypes.h will need to include the binding header - // for this enum. Pick an enum from an interface that won't drag in too much - // stuff. - void passUnionWithEnum((SupportedType or object) arg); - - // Trying to use a callback in a union won't include the test - // headers, unfortunately, so won't compile. - // void passUnionWithCallback((TestCallback or long) arg); - void passUnionWithObject((object or long) arg); - //void passUnionWithDict((Dict or long) arg); - - void passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); - void passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); - void passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); - void passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); - void passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); - void passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); - void passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); - void passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); - void passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); - void passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); - void passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); - void passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); - void passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); - void passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); - void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); - void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); - void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); - void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); - void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); - - void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); - void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); - void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); - void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); - void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); - void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); - void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); - void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); - - void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); - void passSequenceOfUnions2(sequence<(object or long)> arg); - void passVariadicUnion((CanvasPattern or CanvasGradient)... arg); - - void passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); - void passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); - void passMozMapOfUnions(MozMap<(CanvasPattern or CanvasGradient)> arg); - // XXXbz no move constructor on some unions - // void passMozMapOfUnions2(MozMap<(object or long)> arg); - - (CanvasPattern or CanvasGradient) receiveUnion(); - (object or long) receiveUnion2(); - (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); - (CanvasPattern or CanvasGradient)? receiveNullableUnion(); - (object or long)? receiveNullableUnion2(); - - attribute (CanvasPattern or CanvasGradient) writableUnion; - attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; - attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; - - // Date types - void passDate(Date arg); - void passNullableDate(Date? arg); - void passOptionalDate(optional Date arg); - void passOptionalNullableDate(optional Date? arg); - void passOptionalNullableDateWithDefaultValue(optional Date? arg = null); - void passDateSequence(sequence arg); - void passNullableDateSequence(sequence arg); - void passDateMozMap(MozMap arg); - Date receiveDate(); - Date? receiveNullableDate(); - - // Promise types - void passPromise(Promise arg); - void passNullablePromise(Promise? arg); - void passOptionalPromise(optional Promise arg); - void passOptionalNullablePromise(optional Promise? arg); - void passOptionalNullablePromiseWithDefaultValue(optional Promise? arg = null); - void passPromiseSequence(sequence> arg); - void passNullablePromiseSequence(sequence?> arg); - Promise receivePromise(); - Promise receiveAddrefedPromise(); - - // binaryNames tests - void methodRenamedFrom(); - [BinaryName="otherMethodRenamedTo"] - void otherMethodRenamedFrom(); - void methodRenamedFrom(byte argument); - readonly attribute byte attributeGetterRenamedFrom; - attribute byte attributeRenamedFrom; - [BinaryName="otherAttributeRenamedTo"] - attribute byte otherAttributeRenamedFrom; - - void passDictionary(optional Dict x); - void passDictionary2(Dict x); - [Cached, Pure] - readonly attribute Dict readonlyDictionary; - [Cached, Pure] - readonly attribute Dict? readonlyNullableDictionary; - [Cached, Pure] - attribute Dict writableDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict readonlyFrozenDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict? readonlyFrozenNullableDictionary; - [Cached, Pure, Frozen] - attribute Dict writableFrozenDictionary; - Dict receiveDictionary(); - Dict? receiveNullableDictionary(); - void passOtherDictionary(optional GrandparentDict x); - void passSequenceOfDictionaries(sequence x); - void passMozMapOfDictionaries(MozMap x); - // No support for nullable dictionaries inside a sequence (nor should there be) - // void passSequenceOfNullableDictionaries(sequence x); - void passDictionaryOrLong(optional Dict x); - void passDictionaryOrLong(long x); - - void passDictContainingDict(optional DictContainingDict arg); - void passDictContainingSequence(optional DictContainingSequence arg); - DictContainingSequence receiveDictContainingSequence(); - void passVariadicDictionary(Dict... arg); - - // EnforceRange/Clamp tests - void dontEnforceRangeOrClamp(byte arg); - void doEnforceRange([EnforceRange] byte arg); - void doClamp([Clamp] byte arg); - [EnforceRange] attribute byte enforcedByte; - [Clamp] attribute byte clampedByte; - - // Typedefs - const myLong myLongConstant = 5; - void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg); - AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg); - void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg); - - // Deprecated methods and attributes - [Deprecated="GetAttributeNode"] - attribute boolean deprecatedAttribute; - [Deprecated="GetAttributeNode"] - void deprecatedMethod(boolean arg); - [Deprecated="GetAttributeNode"] - void deprecatedMethodWithContext(any arg); - - // Static methods and attributes - static attribute boolean staticAttribute; - static void staticMethod(boolean arg); - static void staticMethodWithContext(any arg); - - // Deprecated methods and attributes; - [Deprecated="GetAttributeNode"] - static attribute boolean staticDeprecatedAttribute; - [Deprecated="GetAttributeNode"] - static void staticDeprecatedMethod(boolean arg); - [Deprecated="GetAttributeNode"] - static void staticDeprecatedMethodWithContext(any arg); - - // Overload resolution tests - //void overload1(DOMString... strs); - boolean overload1(TestInterface arg); - TestInterface overload1(DOMString strs, TestInterface arg); - void overload2(TestInterface arg); - void overload2(optional Dict arg); - void overload2(boolean arg); - void overload2(DOMString arg); - void overload2(Date arg); - void overload3(TestInterface arg); - void overload3(TestCallback arg); - void overload3(boolean arg); - void overload4(TestInterface arg); - void overload4(TestCallbackInterface arg); - void overload4(DOMString arg); - void overload5(long arg); - void overload5(TestEnum arg); - void overload6(long arg); - void overload6(boolean arg); - void overload7(long arg); - void overload7(boolean arg); - void overload7(ByteString arg); - void overload8(long arg); - void overload8(TestInterface arg); - void overload9(long? arg); - void overload9(DOMString arg); - void overload10(long? arg); - void overload10(object arg); - void overload11(long arg); - void overload11(DOMString? arg); - void overload12(long arg); - void overload12(boolean? arg); - void overload13(long? arg); - void overload13(boolean arg); - void overload14(optional long arg); - void overload14(TestInterface arg); - void overload15(long arg); - void overload15(optional TestInterface arg); - void overload16(long arg); - void overload16(optional TestInterface? arg); - void overload17(sequence arg); - void overload17(MozMap arg); - void overload18(MozMap arg); - void overload18(sequence arg); - void overload19(sequence arg); - void overload19(optional Dict arg); - void overload20(optional Dict arg); - void overload20(sequence arg); - - // Variadic handling - void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); - - // Conditionally exposed methods/attributes - [Pref="abc.def"] - readonly attribute boolean prefable1; - [Pref="abc.def"] - readonly attribute boolean prefable2; - [Pref="ghi.jkl"] - readonly attribute boolean prefable3; - [Pref="ghi.jkl"] - readonly attribute boolean prefable4; - [Pref="abc.def"] - readonly attribute boolean prefable5; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable6; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable7; - [Pref="ghi.jkl", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable8; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable9; - [Pref="abc.def"] - void prefable10(); - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable11(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable12; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable13(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable14; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable15; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable16; - [Pref="abc.def", Func="TestFuncControlledMember"] - void prefable17(); - [Func="TestFuncControlledMember"] - void prefable18(); - [Func="TestFuncControlledMember"] - void prefable19(); - - // Conditionally exposed methods/attributes involving [SecureContext] - [SecureContext] - readonly attribute boolean conditionalOnSecureContext1; - [SecureContext, Pref="abc.def"] - readonly attribute boolean conditionalOnSecureContext2; - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean conditionalOnSecureContext3; - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean conditionalOnSecureContext4; - [SecureContext] - void conditionalOnSecureContext5(); - [SecureContext, Pref="abc.def"] - void conditionalOnSecureContext6(); - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void conditionalOnSecureContext7(); - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - void conditionalOnSecureContext8(); - - // Miscellania - [LenientThis] attribute long attrWithLenientThis; - [Unforgeable] readonly attribute long unforgeableAttr; - [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; - [Unforgeable] long unforgeableMethod(); - [Unforgeable, ChromeOnly] long unforgeableMethod2(); - stringifier; - void passRenamedInterface(TestRenamedInterface arg); - [PutForwards=writableByte] readonly attribute TestExampleInterface putForwardsAttr; - [PutForwards=writableByte, LenientThis] readonly attribute TestExampleInterface putForwardsAttr2; - [PutForwards=writableByte, ChromeOnly] readonly attribute TestExampleInterface putForwardsAttr3; - [Throws] void throwingMethod(); - [Throws] attribute boolean throwingAttr; - [GetterThrows] attribute boolean throwingGetterAttr; - [SetterThrows] attribute boolean throwingSetterAttr; - [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod(); - [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; - [NeedsCallerType] void needsCallerTypeMethod(); - [NeedsCallerType] attribute boolean needsCallerTypeAttr; - [CEReactions] void ceReactionsMethod(); - [CEReactions] void ceReactionsMethodOverload(); - [CEReactions] void ceReactionsMethodOverload(DOMString bar); - [CEReactions] attribute boolean ceReactionsAttr; - legacycaller short(unsigned long arg1, TestInterface arg2); - void passArgsWithDefaults(optional long arg1, - optional TestInterface? arg2 = null, - optional Dict arg3, optional double arg4 = 5.0, - optional float arg5); - attribute any jsonifierShouldSkipThis; - attribute TestParentInterface jsonifierShouldSkipThis2; - attribute TestCallbackInterface jsonifierShouldSkipThis3; - jsonifier; - - attribute byte dashed-attribute; - void dashed-method(); - - // If you add things here, add them to TestCodeGen and TestJSImplGen as well -}; - -interface TestExampleProxyInterface { - getter long longIndexedGetter(unsigned long ix); - setter creator void longIndexedSetter(unsigned long y, long z); - stringifier DOMString myStringifier(); - getter short shortNameGetter(DOMString nom); - deleter void (DOMString nomnom); - setter creator void shortNamedSetter(DOMString me, short value); -}; - -[Exposed=(Window,Worker)] -interface TestExampleWorkerInterface { - [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod(); - [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; - [NeedsCallerType] void needsCallerTypeMethod(); - [NeedsCallerType] attribute boolean needsCallerTypeAttr; -}; diff --git a/dom/bindings/test/TestFunctions.cpp b/dom/bindings/test/TestFunctions.cpp deleted file mode 100644 index f05c92b48d..0000000000 --- a/dom/bindings/test/TestFunctions.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/TestFunctions.h" -#include "mozilla/dom/TestFunctionsBinding.h" -#include "nsStringBuffer.h" - -namespace mozilla { -namespace dom { - -/* static */ TestFunctions* -TestFunctions::Constructor(GlobalObject& aGlobal, ErrorResult& aRv) -{ - return new TestFunctions; -} - -/* static */ void -TestFunctions::ThrowUncatchableException(GlobalObject& aGlobal, - ErrorResult& aRv) -{ - aRv.ThrowUncatchableException(); -} - -/* static */ Promise* -TestFunctions::PassThroughPromise(GlobalObject& aGlobal, Promise& aPromise) -{ - return &aPromise; -} - -/* static */ already_AddRefed -TestFunctions::PassThroughCallbackPromise(GlobalObject& aGlobal, - PromiseReturner& aCallback, - ErrorResult& aRv) -{ - return aCallback.Call(aRv); -} - -void -TestFunctions::SetStringData(const nsAString& aString) -{ - mStringData = aString; -} - -void -TestFunctions::GetStringDataAsAString(nsAString& aString) -{ - aString = mStringData; -} - -void -TestFunctions::GetStringDataAsAString(uint32_t aLength, nsAString& aString) -{ - MOZ_RELEASE_ASSERT(aLength <= mStringData.Length(), - "Bogus test passing in a too-big length"); - aString.Assign(mStringData.BeginReading(), aLength); -} - -void -TestFunctions::GetStringDataAsDOMString(const Optional& aLength, - DOMString& aString) -{ - uint32_t length; - if (aLength.WasPassed()) { - length = aLength.Value(); - MOZ_RELEASE_ASSERT(length <= mStringData.Length(), - "Bogus test passing in a too-big length"); - } else { - length = mStringData.Length(); - } - - nsStringBuffer* buf = nsStringBuffer::FromString(mStringData); - if (buf) { - aString.SetStringBuffer(buf, length); - return; - } - - // We better have an empty mStringData; otherwise why did we not have a string - // buffer? - MOZ_RELEASE_ASSERT(length == 0, "Why no stringbuffer?"); - // No need to do anything here; aString is already empty. -} - -bool -TestFunctions::WrapObject(JSContext* aCx, JS::Handle aGivenProto, - JS::MutableHandle aWrapper) -{ - return TestFunctionsBinding::Wrap(aCx, this, aGivenProto, aWrapper); -} - -} -} diff --git a/dom/bindings/test/TestFunctions.h b/dom/bindings/test/TestFunctions.h deleted file mode 100644 index b35464824a..0000000000 --- a/dom/bindings/test/TestFunctions.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TestFunctions_h -#define mozilla_dom_TestFunctions_h - -#include "mozilla/ErrorResult.h" -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/NonRefcountedDOMObject.h" -#include "nsString.h" - -namespace mozilla { -namespace dom { - -class Promise; -class PromiseReturner; - -class TestFunctions : public NonRefcountedDOMObject { -public: - static TestFunctions* Constructor(GlobalObject& aGlobal, ErrorResult& aRv); - - static void - ThrowUncatchableException(GlobalObject& aGlobal, ErrorResult& aRv); - - static Promise* - PassThroughPromise(GlobalObject& aGlobal, Promise& aPromise); - - static already_AddRefed - PassThroughCallbackPromise(GlobalObject& aGlobal, - PromiseReturner& aCallback, - ErrorResult& aRv); - - void SetStringData(const nsAString& aString); - - void GetStringDataAsAString(nsAString& aString); - void GetStringDataAsAString(uint32_t aLength, nsAString& aString); - void GetStringDataAsDOMString(const Optional& aLength, - DOMString& aString); - - bool WrapObject(JSContext* aCx, JS::Handle aGivenProto, - JS::MutableHandle aWrapper); -private: - nsString mStringData; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestFunctions_h diff --git a/dom/bindings/test/TestInterfaceIterableDouble.cpp b/dom/bindings/test/TestInterfaceIterableDouble.cpp deleted file mode 100644 index 33a4c97d1f..0000000000 --- a/dom/bindings/test/TestInterfaceIterableDouble.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceIterableDouble.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableDouble, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableDouble) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableDouble) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableDouble) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceIterableDouble::TestInterfaceIterableDouble(nsPIDOMWindowInner* aParent) - : mParent(aParent) -{ - mValues.AppendElement(std::pair(NS_LITERAL_STRING("a"), - NS_LITERAL_STRING("b"))); - mValues.AppendElement(std::pair(NS_LITERAL_STRING("c"), - NS_LITERAL_STRING("d"))); - mValues.AppendElement(std::pair(NS_LITERAL_STRING("e"), - NS_LITERAL_STRING("f"))); -} - -//static -already_AddRefed -TestInterfaceIterableDouble::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceIterableDouble(window); - return r.forget(); -} - -JSObject* -TestInterfaceIterableDouble::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TestInterfaceIterableDoubleBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceIterableDouble::GetParentObject() const -{ - return mParent; -} - -size_t -TestInterfaceIterableDouble::GetIterableLength() -{ - return mValues.Length(); -} - -nsAString& -TestInterfaceIterableDouble::GetKeyAtIndex(uint32_t aIndex) -{ - MOZ_ASSERT(aIndex < mValues.Length()); - return mValues.ElementAt(aIndex).first; -} - -nsAString& -TestInterfaceIterableDouble::GetValueAtIndex(uint32_t aIndex) -{ - MOZ_ASSERT(aIndex < mValues.Length()); - return mValues.ElementAt(aIndex).second; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceIterableDouble.h b/dom/bindings/test/TestInterfaceIterableDouble.h deleted file mode 100644 index 1e9ff7acd3..0000000000 --- a/dom/bindings/test/TestInterfaceIterableDouble.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceIterableDouble_h -#define mozilla_dom_TestInterfaceIterableDouble_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl iterable interfaces, using -// primitives for value type -class TestInterfaceIterableDouble final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceIterableDouble) - - explicit TestInterfaceIterableDouble(nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); - - size_t GetIterableLength(); - nsAString& GetKeyAtIndex(uint32_t aIndex); - nsAString& GetValueAtIndex(uint32_t aIndex); -private: - virtual ~TestInterfaceIterableDouble() {} - nsCOMPtr mParent; - nsTArray> mValues; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceIterableDouble_h diff --git a/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp b/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp deleted file mode 100644 index 29151a4c56..0000000000 --- a/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceIterableDoubleUnion.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableDoubleUnion, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableDoubleUnion) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableDoubleUnion) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableDoubleUnion) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceIterableDoubleUnion::TestInterfaceIterableDoubleUnion(nsPIDOMWindowInner* aParent) - : mParent(aParent) -{ - OwningStringOrLong a; - a.SetAsLong() = 1; - mValues.AppendElement(std::pair(NS_LITERAL_STRING("long"), - a)); - a.SetAsString() = NS_LITERAL_STRING("a"); - mValues.AppendElement(std::pair(NS_LITERAL_STRING("string"), - a)); -} - -//static -already_AddRefed -TestInterfaceIterableDoubleUnion::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceIterableDoubleUnion(window); - return r.forget(); -} - -JSObject* -TestInterfaceIterableDoubleUnion::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TestInterfaceIterableDoubleUnionBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceIterableDoubleUnion::GetParentObject() const -{ - return mParent; -} - -size_t -TestInterfaceIterableDoubleUnion::GetIterableLength() -{ - return mValues.Length(); -} - -nsAString& -TestInterfaceIterableDoubleUnion::GetKeyAtIndex(uint32_t aIndex) -{ - MOZ_ASSERT(aIndex < mValues.Length()); - return mValues.ElementAt(aIndex).first; -} - -OwningStringOrLong& -TestInterfaceIterableDoubleUnion::GetValueAtIndex(uint32_t aIndex) -{ - MOZ_ASSERT(aIndex < mValues.Length()); - return mValues.ElementAt(aIndex).second; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceIterableDoubleUnion.h b/dom/bindings/test/TestInterfaceIterableDoubleUnion.h deleted file mode 100644 index ff6ea21752..0000000000 --- a/dom/bindings/test/TestInterfaceIterableDoubleUnion.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceIterableDoubleUnion_h -#define mozilla_dom_TestInterfaceIterableDoubleUnion_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl iterable interfaces, using -// primitives for value type -class TestInterfaceIterableDoubleUnion final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceIterableDoubleUnion) - - explicit TestInterfaceIterableDoubleUnion(nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); - - size_t GetIterableLength(); - nsAString& GetKeyAtIndex(uint32_t aIndex); - OwningStringOrLong& GetValueAtIndex(uint32_t aIndex); -private: - virtual ~TestInterfaceIterableDoubleUnion() {} - nsCOMPtr mParent; - nsTArray> mValues; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceIterableDoubleUnion_h diff --git a/dom/bindings/test/TestInterfaceIterableSingle.cpp b/dom/bindings/test/TestInterfaceIterableSingle.cpp deleted file mode 100644 index 5f8d6c640f..0000000000 --- a/dom/bindings/test/TestInterfaceIterableSingle.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceIterableSingle.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableSingle, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableSingle) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableSingle) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableSingle) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceIterableSingle::TestInterfaceIterableSingle(nsPIDOMWindowInner* aParent) - : mParent(aParent) -{ - for (int i = 0; i < 3; ++i) { - mValues.AppendElement(i); - } -} - -//static -already_AddRefed -TestInterfaceIterableSingle::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceIterableSingle(window); - return r.forget(); -} - -JSObject* -TestInterfaceIterableSingle::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TestInterfaceIterableSingleBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceIterableSingle::GetParentObject() const -{ - return mParent; -} - -uint32_t -TestInterfaceIterableSingle::Length() const -{ - return mValues.Length(); -} - -int32_t -TestInterfaceIterableSingle::IndexedGetter(uint32_t aIndex, bool& aFound) const -{ - if (aIndex >= mValues.Length()) { - aFound = false; - return 0; - } - - aFound = true; - return mValues[aIndex]; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceIterableSingle.h b/dom/bindings/test/TestInterfaceIterableSingle.h deleted file mode 100644 index a071ada8b0..0000000000 --- a/dom/bindings/test/TestInterfaceIterableSingle.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceIterableSingle_h -#define mozilla_dom_TestInterfaceIterableSingle_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl iterable interfaces, using -// primitives for value type -class TestInterfaceIterableSingle final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceIterableSingle) - - explicit TestInterfaceIterableSingle(nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); - - uint32_t Length() const; - int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const; - -private: - virtual ~TestInterfaceIterableSingle() {} - nsCOMPtr mParent; - nsTArray mValues; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceIterableSingle_h diff --git a/dom/bindings/test/TestInterfaceJS.js b/dom/bindings/test/TestInterfaceJS.js deleted file mode 100644 index 1a5bf8e61d..0000000000 --- a/dom/bindings/test/TestInterfaceJS.js +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: JavaScript; 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/. */ - -"use strict"; -const Cu = Components.utils; -const Ci = Components.interfaces; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -function TestInterfaceJS(anyArg, objectArg) {} - -TestInterfaceJS.prototype = { - classID: Components.ID("{2ac4e026-cf25-47d5-b067-78d553c3cad8}"), - contractID: "@mozilla.org/dom/test-interface-js;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, - Ci.nsIDOMGlobalPropertyInitializer]), - - init: function(win) { this._win = win; }, - - __init: function (anyArg, objectArg, dictionaryArg) { - this._anyAttr = undefined; - this._objectAttr = null; - this._anyArg = anyArg; - this._objectArg = objectArg; - this._dictionaryArg = dictionaryArg; - this._cachedAttr = 15; - }, - - get anyArg() { return this._anyArg; }, - get objectArg() { return this._objectArg; }, - get dictionaryArg() { return this._dictionaryArg; }, - get anyAttr() { return this._anyAttr; }, - set anyAttr(val) { this._anyAttr = val; }, - get objectAttr() { return this._objectAttr; }, - set objectAttr(val) { this._objectAttr = val; }, - get dictionaryAttr() { return this._dictionaryAttr; }, - set dictionaryAttr(val) { this._dictionaryAttr = val; }, - pingPongAny: function(any) { return any; }, - pingPongObject: function(obj) { return obj; }, - pingPongObjectOrString: function(objectOrString) { return objectOrString; }, - pingPongDictionary: function(dict) { return dict; }, - pingPongDictionaryOrLong: function(dictOrLong) { return dictOrLong.anyMember || dictOrLong; }, - pingPongMap: function(map) { return JSON.stringify(map); }, - objectSequenceLength: function(seq) { return seq.length; }, - anySequenceLength: function(seq) { return seq.length; }, - - - getCallerPrincipal: function() { return Cu.getWebIDLCallerPrincipal().origin; }, - - convertSVS: function(svs) { return svs; }, - - pingPongUnion: function(x) { return x; }, - pingPongUnionContainingNull: function(x) { return x; }, - pingPongNullableUnion: function(x) { return x; }, - returnBadUnion: function(x) { return 3; }, - - get cachedAttr() { return this._cachedAttr; }, - setCachedAttr: function(n) { this._cachedAttr = n; }, - clearCachedAttrCache: function () { this.__DOM_IMPL__._clearCachedCachedAttrValue(); }, - - testSequenceOverload: function(arg) {}, - testSequenceUnion: function(arg) {}, - - testThrowError: function() { - throw new this._win.Error("We are an Error"); - }, - - testThrowDOMException: function() { - throw new this._win.DOMException("We are a DOMException", - "NotSupportedError"); - }, - - testThrowTypeError: function() { - throw new this._win.TypeError("We are a TypeError"); - }, - - testThrowCallbackError: function(callback) { - callback(); - }, - - testThrowXraySelfHosted: function() { - this._win.Array.indexOf(); - }, - - testThrowSelfHosted: function() { - Array.indexOf(); - }, - - testPromiseWithThrowingChromePromiseInit: function() { - return new this._win.Promise(function() { - noSuchMethodExistsYo1(); - }) - }, - - testPromiseWithThrowingContentPromiseInit: function(func) { - return new this._win.Promise(func); - }, - - testPromiseWithDOMExceptionThrowingPromiseInit: function() { - return new this._win.Promise(() => { - throw new this._win.DOMException("We are a second DOMException", - "NotFoundError"); - }) - }, - - testPromiseWithThrowingChromeThenFunction: function() { - return this._win.Promise.resolve(5).then(function() { - noSuchMethodExistsYo2(); - }); - }, - - testPromiseWithThrowingContentThenFunction: function(func) { - return this._win.Promise.resolve(10).then(func); - }, - - testPromiseWithDOMExceptionThrowingThenFunction: function() { - return this._win.Promise.resolve(5).then(() => { - throw new this._win.DOMException("We are a third DOMException", - "NetworkError"); - }); - }, - - testPromiseWithThrowingChromeThenable: function() { - var thenable = { - then: function() { - noSuchMethodExistsYo3() - } - }; - return new this._win.Promise(function(resolve) { - resolve(thenable) - }); - }, - - testPromiseWithThrowingContentThenable: function(thenable) { - // Waive Xrays on the thenable, because we're calling resolve() in the - // chrome compartment, so that's the compartment the "then" property get - // will happen in, and if we leave the Xray in place the function-valued - // property won't return the function. - return this._win.Promise.resolve(Cu.waiveXrays(thenable)); - }, - - testPromiseWithDOMExceptionThrowingThenable: function() { - var thenable = { - then: () => { - throw new this._win.DOMException("We are a fourth DOMException", - "TypeMismatchError"); - } - }; - return new this._win.Promise(function(resolve) { - resolve(thenable) - }); - }, - - get onsomething() { - return this.__DOM_IMPL__.getEventHandler("onsomething"); - }, - - set onsomething(val) { - this.__DOM_IMPL__.setEventHandler("onsomething", val); - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJS]) diff --git a/dom/bindings/test/TestInterfaceJS.manifest b/dom/bindings/test/TestInterfaceJS.manifest deleted file mode 100644 index 161a421560..0000000000 --- a/dom/bindings/test/TestInterfaceJS.manifest +++ /dev/null @@ -1,4 +0,0 @@ -component {2ac4e026-cf25-47d5-b067-78d553c3cad8} TestInterfaceJS.js -contract @mozilla.org/dom/test-interface-js;1 {2ac4e026-cf25-47d5-b067-78d553c3cad8} -component {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a} TestInterfaceJSMaplike.js -contract @mozilla.org/dom/test-interface-js-maplike;1 {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a} diff --git a/dom/bindings/test/TestInterfaceJSMaplike.js b/dom/bindings/test/TestInterfaceJSMaplike.js deleted file mode 100644 index b108ef5b61..0000000000 --- a/dom/bindings/test/TestInterfaceJSMaplike.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: JavaScript; 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/. */ - -"use strict"; -const Cu = Components.utils; -const Ci = Components.interfaces; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -function TestInterfaceJSMaplike() {} - -TestInterfaceJSMaplike.prototype = { - classID: Components.ID("{4bc6f6f3-e005-4f0a-b42d-4d1663a9013a}"), - contractID: "@mozilla.org/dom/test-interface-js-maplike;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, - Ci.nsIDOMGlobalPropertyInitializer]), - - init: function(win) { this._win = win; }, - - __init: function () {}, - - setInternal: function(aKey, aValue) { - return this.__DOM_IMPL__.__set(aKey, aValue); - }, - - deleteInternal: function(aKey) { - return this.__DOM_IMPL__.__delete(aKey); - }, - - clearInternal: function() { - return this.__DOM_IMPL__.__clear(); - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJSMaplike]) diff --git a/dom/bindings/test/TestInterfaceMaplike.cpp b/dom/bindings/test/TestInterfaceMaplike.cpp deleted file mode 100644 index 4abace83c1..0000000000 --- a/dom/bindings/test/TestInterfaceMaplike.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceMaplike.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplike, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplike) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplike) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplike) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceMaplike::TestInterfaceMaplike(nsPIDOMWindowInner* aParent) -: mParent(aParent) -{ -} - -//static -already_AddRefed -TestInterfaceMaplike::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceMaplike(window); - return r.forget(); -} - -JSObject* -TestInterfaceMaplike::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TestInterfaceMaplikeBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceMaplike::GetParentObject() const -{ - return mParent; -} - -void -TestInterfaceMaplike::SetInternal(const nsAString& aKey, int32_t aValue) -{ - ErrorResult rv; - TestInterfaceMaplikeBinding::MaplikeHelpers::Set(this, aKey, aValue, rv); -} - -void -TestInterfaceMaplike::ClearInternal() -{ - ErrorResult rv; - TestInterfaceMaplikeBinding::MaplikeHelpers::Clear(this, rv); -} - -bool -TestInterfaceMaplike::DeleteInternal(const nsAString& aKey) -{ - ErrorResult rv; - return TestInterfaceMaplikeBinding::MaplikeHelpers::Delete(this, aKey, rv); -} - -bool -TestInterfaceMaplike::HasInternal(const nsAString& aKey) -{ - ErrorResult rv; - return TestInterfaceMaplikeBinding::MaplikeHelpers::Has(this, aKey, rv); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceMaplike.h b/dom/bindings/test/TestInterfaceMaplike.h deleted file mode 100644 index c012a7a214..0000000000 --- a/dom/bindings/test/TestInterfaceMaplike.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceMaplike_h -#define mozilla_dom_TestInterfaceMaplike_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl maplike interfaces, using -// primitives for key and value types. -class TestInterfaceMaplike final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceMaplike) - - explicit TestInterfaceMaplike(nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); - - // External access for testing internal convenience functions. - void SetInternal(const nsAString& aKey, int32_t aValue); - void ClearInternal(); - bool DeleteInternal(const nsAString& aKey); - bool HasInternal(const nsAString& aKey); -private: - virtual ~TestInterfaceMaplike() {} - nsCOMPtr mParent; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceMaplike_h diff --git a/dom/bindings/test/TestInterfaceMaplikeObject.cpp b/dom/bindings/test/TestInterfaceMaplikeObject.cpp deleted file mode 100644 index 3dc1ffdc43..0000000000 --- a/dom/bindings/test/TestInterfaceMaplikeObject.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceMaplikeObject.h" -#include "mozilla/dom/TestInterfaceMaplike.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplikeObject, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplikeObject) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplikeObject) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplikeObject) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceMaplikeObject::TestInterfaceMaplikeObject(nsPIDOMWindowInner* aParent) -: mParent(aParent) -{ -} - -//static -already_AddRefed -TestInterfaceMaplikeObject::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = - new TestInterfaceMaplikeObject(window); - return r.forget(); -} - -JSObject* -TestInterfaceMaplikeObject::WrapObject(JSContext* aCx, - JS::Handle aGivenProto) -{ - return TestInterfaceMaplikeObjectBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceMaplikeObject::GetParentObject() const -{ - return mParent; -} - -void -TestInterfaceMaplikeObject::SetInternal(const nsAString& aKey) -{ - RefPtr p(new TestInterfaceMaplike(mParent)); - ErrorResult rv; - TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Set(this, aKey, *p, rv); -} - -void -TestInterfaceMaplikeObject::ClearInternal() -{ - ErrorResult rv; - TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Clear(this, rv); -} - -bool -TestInterfaceMaplikeObject::DeleteInternal(const nsAString& aKey) -{ - ErrorResult rv; - return TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Delete(this, aKey, rv); -} - -bool -TestInterfaceMaplikeObject::HasInternal(const nsAString& aKey) -{ - ErrorResult rv; - return TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Has(this, aKey, rv); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceMaplikeObject.h b/dom/bindings/test/TestInterfaceMaplikeObject.h deleted file mode 100644 index af4660c0d3..0000000000 --- a/dom/bindings/test/TestInterfaceMaplikeObject.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceMaplikeObject_h -#define mozilla_dom_TestInterfaceMaplikeObject_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl maplike interfaces, using -// primitives for key types and objects for value types. -class TestInterfaceMaplikeObject final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceMaplikeObject) - - explicit TestInterfaceMaplikeObject(nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal,ErrorResult& rv); - - // External access for testing internal convenience functions. - void SetInternal(const nsAString& aKey); - void ClearInternal(); - bool DeleteInternal(const nsAString& aKey); - bool HasInternal(const nsAString& aKey); -private: - virtual ~TestInterfaceMaplikeObject() {} - nsCOMPtr mParent; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceMaplikeObject_h diff --git a/dom/bindings/test/TestInterfaceSetlike.cpp b/dom/bindings/test/TestInterfaceSetlike.cpp deleted file mode 100644 index c9f5560760..0000000000 --- a/dom/bindings/test/TestInterfaceSetlike.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceSetlike.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlike, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlike) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlike) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlike) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceSetlike::TestInterfaceSetlike(JSContext* aCx, - nsPIDOMWindowInner* aParent) -: mParent(aParent) -{ -} - -//static -already_AddRefed -TestInterfaceSetlike::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceSetlike(nullptr, window); - return r.forget(); -} - -JSObject* -TestInterfaceSetlike::WrapObject(JSContext* aCx, - JS::Handle aGivenProto) -{ - return TestInterfaceSetlikeBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceSetlike::GetParentObject() const -{ - return mParent; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceSetlike.h b/dom/bindings/test/TestInterfaceSetlike.h deleted file mode 100644 index c9f4649605..0000000000 --- a/dom/bindings/test/TestInterfaceSetlike.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceSetlike_h -#define mozilla_dom_TestInterfaceSetlike_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl setlike interfaces, using -// primitives for key type. -class TestInterfaceSetlike final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceSetlike) - explicit TestInterfaceSetlike(JSContext* aCx, - nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); -private: - virtual ~TestInterfaceSetlike() {} - nsCOMPtr mParent; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceSetlike_h diff --git a/dom/bindings/test/TestInterfaceSetlikeNode.cpp b/dom/bindings/test/TestInterfaceSetlikeNode.cpp deleted file mode 100644 index 5499553fa5..0000000000 --- a/dom/bindings/test/TestInterfaceSetlikeNode.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* 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 "mozilla/dom/TestInterfaceSetlikeNode.h" -#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlikeNode, mParent) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlikeNode) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlikeNode) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlikeNode) -NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY -NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -TestInterfaceSetlikeNode::TestInterfaceSetlikeNode(JSContext* aCx, - nsPIDOMWindowInner* aParent) -: mParent(aParent) -{ -} - -//static -already_AddRefed -TestInterfaceSetlikeNode::Constructor(const GlobalObject& aGlobal, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr r = new TestInterfaceSetlikeNode(nullptr, window); - return r.forget(); -} - -JSObject* -TestInterfaceSetlikeNode::WrapObject(JSContext* aCx, - JS::Handle aGivenProto) -{ - return TestInterfaceSetlikeNodeBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -TestInterfaceSetlikeNode::GetParentObject() const -{ - return mParent; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/bindings/test/TestInterfaceSetlikeNode.h b/dom/bindings/test/TestInterfaceSetlikeNode.h deleted file mode 100644 index 05b14190e0..0000000000 --- a/dom/bindings/test/TestInterfaceSetlikeNode.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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_TestInterfaceSetlikeNode_h -#define mozilla_dom_TestInterfaceSetlikeNode_h - -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" - -class nsPIDOMWindowInner; - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class GlobalObject; - -// Implementation of test binding for webidl setlike interfaces, using -// primitives for key type. -class TestInterfaceSetlikeNode final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceSetlikeNode) - explicit TestInterfaceSetlikeNode(JSContext* aCx, - nsPIDOMWindowInner* aParent); - nsPIDOMWindowInner* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, - JS::Handle aGivenProto) override; - static already_AddRefed - Constructor(const GlobalObject& aGlobal, ErrorResult& rv); -private: - virtual ~TestInterfaceSetlikeNode() {} - nsCOMPtr mParent; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TestInterfaceSetlikeNode_h diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl deleted file mode 100644 index a133b9981a..0000000000 --- a/dom/bindings/test/TestJSImplGen.webidl +++ /dev/null @@ -1,840 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -typedef TestJSImplInterface AnotherNameForTestJSImplInterface; -typedef TestJSImplInterface YetAnotherNameForTestJSImplInterface; -typedef TestJSImplInterface? NullableTestJSImplInterface; - -callback MyTestCallback = void(); - -enum MyTestEnum { - "a", - "b" -}; - -// We don't support multiple constructors (bug 869268) or named constructors -// for JS-implemented WebIDL. -[Constructor(DOMString str, unsigned long num, boolean? boolArg, - TestInterface? iface, long arg1, - DictForConstructor dict, any any1, - object obj1, - object? obj2, sequence seq, optional any any2, - optional object obj3, - optional object? obj4, - Uint8Array typedArr, - ArrayBuffer arrayBuf), - JSImplementation="@mozilla.org/test-js-impl-interface;1"] -interface TestJSImplInterface { - // Integer types - // XXXbz add tests for throwing versions of all the integer stuff - readonly attribute byte readonlyByte; - attribute byte writableByte; - void passByte(byte arg); - byte receiveByte(); - void passOptionalByte(optional byte arg); - void passOptionalByteBeforeRequired(optional byte arg1, byte arg2); - void passOptionalByteWithDefault(optional byte arg = 0); - void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); - void passNullableByte(byte? arg); - void passOptionalNullableByte(optional byte? arg); - void passVariadicByte(byte... arg); - [Cached, Pure] - readonly attribute byte cachedByte; - [Cached, Constant] - readonly attribute byte cachedConstantByte; - [Cached, Pure] - attribute byte cachedWritableByte; - [Affects=Nothing] - attribute byte sideEffectFreeByte; - [Affects=Nothing, DependsOn=DOMState] - attribute byte domDependentByte; - [Affects=Nothing, DependsOn=Nothing] - readonly attribute byte constantByte; - [DependsOn=DeviceState, Affects=Nothing] - readonly attribute byte deviceStateDependentByte; - [Affects=Nothing] - byte returnByteSideEffectFree(); - [Affects=Nothing, DependsOn=DOMState] - byte returnDOMDependentByte(); - [Affects=Nothing, DependsOn=Nothing] - byte returnConstantByte(); - [DependsOn=DeviceState, Affects=Nothing] - byte returnDeviceStateDependentByte(); - - readonly attribute short readonlyShort; - attribute short writableShort; - void passShort(short arg); - short receiveShort(); - void passOptionalShort(optional short arg); - void passOptionalShortWithDefault(optional short arg = 5); - - readonly attribute long readonlyLong; - attribute long writableLong; - void passLong(long arg); - long receiveLong(); - void passOptionalLong(optional long arg); - void passOptionalLongWithDefault(optional long arg = 7); - - readonly attribute long long readonlyLongLong; - attribute long long writableLongLong; - void passLongLong(long long arg); - long long receiveLongLong(); - void passOptionalLongLong(optional long long arg); - void passOptionalLongLongWithDefault(optional long long arg = -12); - - readonly attribute octet readonlyOctet; - attribute octet writableOctet; - void passOctet(octet arg); - octet receiveOctet(); - void passOptionalOctet(optional octet arg); - void passOptionalOctetWithDefault(optional octet arg = 19); - - readonly attribute unsigned short readonlyUnsignedShort; - attribute unsigned short writableUnsignedShort; - void passUnsignedShort(unsigned short arg); - unsigned short receiveUnsignedShort(); - void passOptionalUnsignedShort(optional unsigned short arg); - void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); - - readonly attribute unsigned long readonlyUnsignedLong; - attribute unsigned long writableUnsignedLong; - void passUnsignedLong(unsigned long arg); - unsigned long receiveUnsignedLong(); - void passOptionalUnsignedLong(optional unsigned long arg); - void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); - - readonly attribute unsigned long long readonlyUnsignedLongLong; - attribute unsigned long long writableUnsignedLongLong; - void passUnsignedLongLong(unsigned long long arg); - unsigned long long receiveUnsignedLongLong(); - void passOptionalUnsignedLongLong(optional unsigned long long arg); - void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); - - attribute float writableFloat; - attribute unrestricted float writableUnrestrictedFloat; - attribute float? writableNullableFloat; - attribute unrestricted float? writableNullableUnrestrictedFloat; - attribute double writableDouble; - attribute unrestricted double writableUnrestrictedDouble; - attribute double? writableNullableDouble; - attribute unrestricted double? writableNullableUnrestrictedDouble; - void passFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, sequence arg10, - sequence arg11, sequence arg12, - sequence arg13, sequence arg14, - sequence arg15, sequence arg16); - [LenientFloat] - void passLenientFloat(float arg1, unrestricted float arg2, - float? arg3, unrestricted float? arg4, - double arg5, unrestricted double arg6, - double? arg7, unrestricted double? arg8, - sequence arg9, - sequence arg10, - sequence arg11, - sequence arg12, - sequence arg13, - sequence arg14, - sequence arg15, - sequence arg16); - [LenientFloat] - attribute float lenientFloatAttr; - [LenientFloat] - attribute double lenientDoubleAttr; - - // Castable interface types - // XXXbz add tests for throwing versions of all the castable interface stuff - TestJSImplInterface receiveSelf(); - TestJSImplInterface? receiveNullableSelf(); - - TestJSImplInterface receiveWeakSelf(); - TestJSImplInterface? receiveWeakNullableSelf(); - - // A version to test for casting to TestJSImplInterface& - void passSelf(TestJSImplInterface arg); - void passNullableSelf(TestJSImplInterface? arg); - attribute TestJSImplInterface nonNullSelf; - attribute TestJSImplInterface? nullableSelf; - [Cached, Pure] - readonly attribute TestJSImplInterface cachedSelf; - // Optional arguments - void passOptionalSelf(optional TestJSImplInterface? arg); - void passOptionalNonNullSelf(optional TestJSImplInterface arg); - void passOptionalSelfWithDefault(optional TestJSImplInterface? arg = null); - - // Non-wrapper-cache interface types - [NewObject] - TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); - [NewObject] - TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); - - [NewObject] - sequence receiveNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence receiveNullableNonWrapperCacheInterfaceSequence(); - [NewObject] - sequence? receiveNonWrapperCacheInterfaceNullableSequence(); - [NewObject] - sequence? receiveNullableNonWrapperCacheInterfaceNullableSequence(); - - // Non-castable interface types - IndirectlyImplementedInterface receiveOther(); - IndirectlyImplementedInterface? receiveNullableOther(); - IndirectlyImplementedInterface receiveWeakOther(); - IndirectlyImplementedInterface? receiveWeakNullableOther(); - - void passOther(IndirectlyImplementedInterface arg); - void passNullableOther(IndirectlyImplementedInterface? arg); - attribute IndirectlyImplementedInterface nonNullOther; - attribute IndirectlyImplementedInterface? nullableOther; - // Optional arguments - void passOptionalOther(optional IndirectlyImplementedInterface? arg); - void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg); - void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null); - - // External interface types - TestExternalInterface receiveExternal(); - TestExternalInterface? receiveNullableExternal(); - TestExternalInterface receiveWeakExternal(); - TestExternalInterface? receiveWeakNullableExternal(); - void passExternal(TestExternalInterface arg); - void passNullableExternal(TestExternalInterface? arg); - attribute TestExternalInterface nonNullExternal; - attribute TestExternalInterface? nullableExternal; - // Optional arguments - void passOptionalExternal(optional TestExternalInterface? arg); - void passOptionalNonNullExternal(optional TestExternalInterface arg); - void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); - - // Callback interface types - TestCallbackInterface receiveCallbackInterface(); - TestCallbackInterface? receiveNullableCallbackInterface(); - TestCallbackInterface receiveWeakCallbackInterface(); - TestCallbackInterface? receiveWeakNullableCallbackInterface(); - void passCallbackInterface(TestCallbackInterface arg); - void passNullableCallbackInterface(TestCallbackInterface? arg); - attribute TestCallbackInterface nonNullCallbackInterface; - attribute TestCallbackInterface? nullableCallbackInterface; - // Optional arguments - void passOptionalCallbackInterface(optional TestCallbackInterface? arg); - void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); - void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); - - // Miscellaneous interface tests - IndirectlyImplementedInterface receiveConsequentialInterface(); - void passConsequentialInterface(IndirectlyImplementedInterface arg); - - // Sequence types - [Cached, Pure] - readonly attribute sequence readonlySequence; - [Cached, Pure] - readonly attribute sequence readonlySequenceOfDictionaries; - [Cached, Pure] - readonly attribute sequence? readonlyNullableSequenceOfDictionaries; - [Cached, Pure, Frozen] - readonly attribute sequence readonlyFrozenSequence; - [Cached, Pure, Frozen] - readonly attribute sequence? readonlyFrozenNullableSequence; - sequence receiveSequence(); - sequence? receiveNullableSequence(); - sequence receiveSequenceOfNullableInts(); - sequence? receiveNullableSequenceOfNullableInts(); - void passSequence(sequence arg); - void passNullableSequence(sequence? arg); - void passSequenceOfNullableInts(sequence arg); - void passOptionalSequenceOfNullableInts(optional sequence arg); - void passOptionalNullableSequenceOfNullableInts(optional sequence? arg); - sequence receiveCastableObjectSequence(); - sequence receiveCallbackObjectSequence(); - sequence receiveNullableCastableObjectSequence(); - sequence receiveNullableCallbackObjectSequence(); - sequence? receiveCastableObjectNullableSequence(); - sequence? receiveNullableCastableObjectNullableSequence(); - sequence receiveWeakCastableObjectSequence(); - sequence receiveWeakNullableCastableObjectSequence(); - sequence? receiveWeakCastableObjectNullableSequence(); - sequence? receiveWeakNullableCastableObjectNullableSequence(); - void passCastableObjectSequence(sequence arg); - void passNullableCastableObjectSequence(sequence arg); - void passCastableObjectNullableSequence(sequence? arg); - void passNullableCastableObjectNullableSequence(sequence? arg); - void passOptionalSequence(optional sequence arg); - void passOptionalSequenceWithDefaultValue(optional sequence arg = []); - void passOptionalNullableSequence(optional sequence? arg); - void passOptionalNullableSequenceWithDefaultValue(optional sequence? arg = null); - void passOptionalNullableSequenceWithDefaultValue2(optional sequence? arg = []); - void passOptionalObjectSequence(optional sequence arg); - void passExternalInterfaceSequence(sequence arg); - void passNullableExternalInterfaceSequence(sequence arg); - - sequence receiveStringSequence(); - sequence receiveByteStringSequence(); - // Callback interface problem. See bug 843261. - //void passStringSequence(sequence arg); - sequence receiveAnySequence(); - sequence? receiveNullableAnySequence(); - //XXXbz No support for sequence of sequence return values yet. - //sequence> receiveAnySequenceSequence(); - - sequence receiveObjectSequence(); - sequence receiveNullableObjectSequence(); - - void passSequenceOfSequences(sequence> arg); - void passSequenceOfSequencesOfSequences(sequence>> arg); - //XXXbz No support for sequence of sequence return values yet. - //sequence> receiveSequenceOfSequences(); - - // MozMap types - void passMozMap(MozMap arg); - void passNullableMozMap(MozMap? arg); - void passMozMapOfNullableInts(MozMap arg); - void passOptionalMozMapOfNullableInts(optional MozMap arg); - void passOptionalNullableMozMapOfNullableInts(optional MozMap? arg); - void passCastableObjectMozMap(MozMap arg); - void passNullableCastableObjectMozMap(MozMap arg); - void passCastableObjectNullableMozMap(MozMap? arg); - void passNullableCastableObjectNullableMozMap(MozMap? arg); - void passOptionalMozMap(optional MozMap arg); - void passOptionalNullableMozMap(optional MozMap? arg); - void passOptionalNullableMozMapWithDefaultValue(optional MozMap? arg = null); - void passOptionalObjectMozMap(optional MozMap arg); - void passExternalInterfaceMozMap(MozMap arg); - void passNullableExternalInterfaceMozMap(MozMap arg); - void passStringMozMap(MozMap arg); - void passByteStringMozMap(MozMap arg); - void passMozMapOfMozMaps(MozMap> arg); - MozMap receiveMozMap(); - MozMap? receiveNullableMozMap(); - MozMap receiveMozMapOfNullableInts(); - MozMap? receiveNullableMozMapOfNullableInts(); - //XXXbz No support for MozMap of MozMaps return values yet. - //MozMap> receiveMozMapOfMozMaps(); - MozMap receiveAnyMozMap(); - - // Typed array types - void passArrayBuffer(ArrayBuffer arg); - void passNullableArrayBuffer(ArrayBuffer? arg); - void passOptionalArrayBuffer(optional ArrayBuffer arg); - void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); - void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); - void passArrayBufferView(ArrayBufferView arg); - void passInt8Array(Int8Array arg); - void passInt16Array(Int16Array arg); - void passInt32Array(Int32Array arg); - void passUint8Array(Uint8Array arg); - void passUint16Array(Uint16Array arg); - void passUint32Array(Uint32Array arg); - void passUint8ClampedArray(Uint8ClampedArray arg); - void passFloat32Array(Float32Array arg); - void passFloat64Array(Float64Array arg); - void passSequenceOfArrayBuffers(sequence arg); - void passSequenceOfNullableArrayBuffers(sequence arg); - void passMozMapOfArrayBuffers(MozMap arg); - void passMozMapOfNullableArrayBuffers(MozMap arg); - void passVariadicTypedArray(Float32Array... arg); - void passVariadicNullableTypedArray(Float32Array?... arg); - Uint8Array receiveUint8Array(); - attribute Uint8Array uint8ArrayAttr; - - // DOMString types - void passString(DOMString arg); - void passNullableString(DOMString? arg); - void passOptionalString(optional DOMString arg); - void passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); - void passOptionalNullableString(optional DOMString? arg); - void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); - void passVariadicString(DOMString... arg); - - // ByteString types - void passByteString(ByteString arg); - void passNullableByteString(ByteString? arg); - void passOptionalByteString(optional ByteString arg); - void passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); - void passOptionalNullableByteString(optional ByteString? arg); - void passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); - void passVariadicByteString(ByteString... arg); - void passUnionByteString((ByteString or long) arg); - void passOptionalUnionByteString(optional (ByteString or long) arg); - void passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); - - // USVString types - void passSVS(USVString arg); - void passNullableSVS(USVString? arg); - void passOptionalSVS(optional USVString arg); - void passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); - void passOptionalNullableSVS(optional USVString? arg); - void passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); - void passVariadicSVS(USVString... arg); - USVString receiveSVS(); - - // Enumerated types - void passEnum(MyTestEnum arg); - void passNullableEnum(MyTestEnum? arg); - void passOptionalEnum(optional MyTestEnum arg); - void passEnumWithDefault(optional MyTestEnum arg = "a"); - void passOptionalNullableEnum(optional MyTestEnum? arg); - void passOptionalNullableEnumWithDefaultValue(optional MyTestEnum? arg = null); - void passOptionalNullableEnumWithDefaultValue2(optional MyTestEnum? arg = "a"); - MyTestEnum receiveEnum(); - MyTestEnum? receiveNullableEnum(); - attribute MyTestEnum enumAttribute; - readonly attribute MyTestEnum readonlyEnumAttribute; - - // Callback types - void passCallback(MyTestCallback arg); - void passNullableCallback(MyTestCallback? arg); - void passOptionalCallback(optional MyTestCallback arg); - void passOptionalNullableCallback(optional MyTestCallback? arg); - void passOptionalNullableCallbackWithDefaultValue(optional MyTestCallback? arg = null); - MyTestCallback receiveCallback(); - MyTestCallback? receiveNullableCallback(); - // Hmm. These two don't work, I think because I need a locally modified version of TestTreatAsNullCallback. - //void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); - //void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); - void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); - - // Any types - void passAny(any arg); - void passVariadicAny(any... arg); - void passOptionalAny(optional any arg); - void passAnyDefaultNull(optional any arg = null); - void passSequenceOfAny(sequence arg); - void passNullableSequenceOfAny(sequence? arg); - void passOptionalSequenceOfAny(optional sequence arg); - void passOptionalNullableSequenceOfAny(optional sequence? arg); - void passOptionalSequenceOfAnyWithDefaultValue(optional sequence? arg = null); - void passSequenceOfSequenceOfAny(sequence> arg); - void passSequenceOfNullableSequenceOfAny(sequence?> arg); - void passNullableSequenceOfNullableSequenceOfAny(sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence?>? arg); - void passMozMapOfAny(MozMap arg); - void passNullableMozMapOfAny(MozMap? arg); - void passOptionalMozMapOfAny(optional MozMap arg); - void passOptionalNullableMozMapOfAny(optional MozMap? arg); - void passOptionalMozMapOfAnyWithDefaultValue(optional MozMap? arg = null); - void passMozMapOfMozMapOfAny(MozMap> arg); - void passMozMapOfNullableMozMapOfAny(MozMap?> arg); - void passNullableMozMapOfNullableMozMapOfAny(MozMap?>? arg); - void passOptionalNullableMozMapOfNullableMozMapOfAny(optional MozMap?>? arg); - void passOptionalNullableMozMapOfNullableSequenceOfAny(optional MozMap?>? arg); - void passOptionalNullableSequenceOfNullableMozMapOfAny(optional sequence?>? arg); - any receiveAny(); - - // object types - void passObject(object arg); - void passVariadicObject(object... arg); - void passNullableObject(object? arg); - void passVariadicNullableObject(object... arg); - void passOptionalObject(optional object arg); - void passOptionalNullableObject(optional object? arg); - void passOptionalNullableObjectWithDefaultValue(optional object? arg = null); - void passSequenceOfObject(sequence arg); - void passSequenceOfNullableObject(sequence arg); - void passNullableSequenceOfObject(sequence? arg); - void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence?>? arg); - void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence?>? arg); - void passMozMapOfObject(MozMap arg); - object receiveObject(); - object? receiveNullableObject(); - - // Union types - void passUnion((object or long) arg); - // Some union tests are debug-only to avoid creating all those - // unused union types in opt builds. -#ifdef DEBUG - void passUnion2((long or boolean) arg); - void passUnion3((object or long or boolean) arg); - void passUnion4((Node or long or boolean) arg); - void passUnion5((object or boolean) arg); - void passUnion6((object or DOMString) arg); - void passUnion7((object or DOMString or long) arg); - void passUnion8((object or DOMString or boolean) arg); - void passUnion9((object or DOMString or long or boolean) arg); - void passUnion10(optional (EventInit or long) arg); - void passUnion11(optional (CustomEventInit or long) arg); - void passUnion12(optional (EventInit or long) arg = 5); - void passUnion13(optional (object or long?) arg = null); - void passUnion14(optional (object or long?) arg = 5); - void passUnion15((sequence or long) arg); - void passUnion16(optional (sequence or long) arg); - void passUnion17(optional (sequence? or long) arg = 5); - void passUnion18((sequence or long) arg); - void passUnion19(optional (sequence or long) arg); - void passUnion20(optional (sequence or long) arg = []); - void passUnion21((MozMap or long) arg); - void passUnion22((MozMap or long) arg); - void passUnion23((sequence or long) arg); - void passUnion24((sequence or long) arg); - void passUnion25((sequence> or long) arg); - void passUnion26((sequence> or long) arg); - void passUnion27(optional (sequence or EventInit) arg); - void passUnion28(optional (EventInit or sequence) arg); - void passUnionWithCallback((EventHandler or long) arg); - void passUnionWithByteString((ByteString or long) arg); - void passUnionWithMozMap((MozMap or DOMString) arg); - void passUnionWithMozMapAndSequence((MozMap or sequence) arg); - void passUnionWithSequenceAndMozMap((sequence or MozMap) arg); - void passUnionWithSVS((USVString or long) arg); -#endif - void passUnionWithNullable((object? or long) arg); - void passNullableUnion((object or long)? arg); - void passOptionalUnion(optional (object or long) arg); - void passOptionalNullableUnion(optional (object or long)? arg); - void passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); - //void passUnionWithInterfaces((TestJSImplInterface or TestExternalInterface) arg); - //void passUnionWithInterfacesAndNullable((TestJSImplInterface? or TestExternalInterface) arg); - //void passUnionWithSequence((sequence or long) arg); - void passUnionWithArrayBuffer((ArrayBuffer or long) arg); - void passUnionWithString((DOMString or object) arg); - // Using an enum in a union. Note that we use some enum not declared in our - // binding file, because UnionTypes.h will need to include the binding header - // for this enum. Pick an enum from an interface that won't drag in too much - // stuff. - void passUnionWithEnum((SupportedType or object) arg); - - // Trying to use a callback in a union won't include the test - // headers, unfortunately, so won't compile. - // void passUnionWithCallback((MyTestCallback or long) arg); - void passUnionWithObject((object or long) arg); - //void passUnionWithDict((Dict or long) arg); - - void passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); - void passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); - void passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); - void passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); - void passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); - void passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); - void passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); - void passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); - void passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); - void passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); - void passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); - void passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); - void passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); - void passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); - void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); - void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); - void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); - void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); - void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); - - void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); - void passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); - void passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); - void passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); - void passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); - void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); - void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); - void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); - void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); - void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); - void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); - void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); - - void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); - void passSequenceOfUnions2(sequence<(object or long)> arg); - void passVariadicUnion((CanvasPattern or CanvasGradient)... arg); - - void passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); - void passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); - void passMozMapOfUnions(MozMap<(CanvasPattern or CanvasGradient)> arg); - // XXXbz no move constructor on some unions - // void passMozMapOfUnions2(MozMap<(object or long)> arg); - - (CanvasPattern or CanvasGradient) receiveUnion(); - (object or long) receiveUnion2(); - (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); - (CanvasPattern or CanvasGradient)? receiveNullableUnion(); - (object or long)? receiveNullableUnion2(); - - attribute (CanvasPattern or CanvasGradient) writableUnion; - attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; - attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; - - // Date types - void passDate(Date arg); - void passNullableDate(Date? arg); - void passOptionalDate(optional Date arg); - void passOptionalNullableDate(optional Date? arg); - void passOptionalNullableDateWithDefaultValue(optional Date? arg = null); - void passDateSequence(sequence arg); - void passNullableDateSequence(sequence arg); - void passDateMozMap(MozMap arg); - Date receiveDate(); - Date? receiveNullableDate(); - - // Promise types - void passPromise(Promise arg); - void passNullablePromise(Promise? arg); - void passOptionalPromise(optional Promise arg); - void passOptionalNullablePromise(optional Promise? arg); - void passOptionalNullablePromiseWithDefaultValue(optional Promise? arg = null); - void passPromiseSequence(sequence> arg); - void passNullablePromiseSequence(sequence?> arg); - Promise receivePromise(); - Promise receiveAddrefedPromise(); - - // binaryNames tests - void methodRenamedFrom(); - [BinaryName="otherMethodRenamedTo"] - void otherMethodRenamedFrom(); - void methodRenamedFrom(byte argument); - readonly attribute byte attributeGetterRenamedFrom; - attribute byte attributeRenamedFrom; - [BinaryName="otherAttributeRenamedTo"] - attribute byte otherAttributeRenamedFrom; - - void passDictionary(optional Dict x); - void passDictionary2(Dict x); - [Cached, Pure] - readonly attribute Dict readonlyDictionary; - [Cached, Pure] - readonly attribute Dict? readonlyNullableDictionary; - [Cached, Pure] - attribute Dict writableDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict readonlyFrozenDictionary; - [Cached, Pure, Frozen] - readonly attribute Dict? readonlyFrozenNullableDictionary; - [Cached, Pure, Frozen] - attribute Dict writableFrozenDictionary; - Dict receiveDictionary(); - Dict? receiveNullableDictionary(); - void passOtherDictionary(optional GrandparentDict x); - void passSequenceOfDictionaries(sequence x); - void passMozMapOfDictionaries(MozMap x); - // No support for nullable dictionaries inside a sequence (nor should there be) - // void passSequenceOfNullableDictionaries(sequence x); - void passDictionaryOrLong(optional Dict x); - void passDictionaryOrLong(long x); - - void passDictContainingDict(optional DictContainingDict arg); - void passDictContainingSequence(optional DictContainingSequence arg); - DictContainingSequence receiveDictContainingSequence(); - void passVariadicDictionary(Dict... arg); - - // EnforceRange/Clamp tests - void dontEnforceRangeOrClamp(byte arg); - void doEnforceRange([EnforceRange] byte arg); - void doClamp([Clamp] byte arg); - [EnforceRange] attribute byte enforcedByte; - [Clamp] attribute byte clampedByte; - - // Typedefs - const myLong myLongConstant = 5; - void exerciseTypedefInterfaces1(AnotherNameForTestJSImplInterface arg); - AnotherNameForTestJSImplInterface exerciseTypedefInterfaces2(NullableTestJSImplInterface arg); - void exerciseTypedefInterfaces3(YetAnotherNameForTestJSImplInterface arg); - - // Deprecated methods and attributes - [Deprecated="GetAttributeNode"] - attribute byte deprecatedAttribute; - [Deprecated="GetAttributeNode"] - byte deprecatedMethod(); - [Deprecated="GetAttributeNode"] - void deprecatedMethodWithContext(any arg); - - // Static methods and attributes - // FIXME: Bug 863952 Static things are not supported yet - /* - static attribute boolean staticAttribute; - static void staticMethod(boolean arg); - static void staticMethodWithContext(any arg); - - // Deprecated static methods and attributes - [Deprecated="GetAttributeNode"] - static attribute byte staticDeprecatedAttribute; - [Deprecated="GetAttributeNode"] - static byte staticDeprecatedMethod(); - [Deprecated="GetAttributeNode"] - static byte staticDeprecatedMethodWithContext(); - */ - - // Overload resolution tests - //void overload1(DOMString... strs); - boolean overload1(TestJSImplInterface arg); - TestJSImplInterface overload1(DOMString strs, TestJSImplInterface arg); - void overload2(TestJSImplInterface arg); - void overload2(optional Dict arg); - void overload2(boolean arg); - void overload2(DOMString arg); - void overload2(Date arg); - void overload3(TestJSImplInterface arg); - void overload3(MyTestCallback arg); - void overload3(boolean arg); - void overload4(TestJSImplInterface arg); - void overload4(TestCallbackInterface arg); - void overload4(DOMString arg); - void overload5(long arg); - void overload5(MyTestEnum arg); - void overload6(long arg); - void overload6(boolean arg); - void overload7(long arg); - void overload7(boolean arg); - void overload7(ByteString arg); - void overload8(long arg); - void overload8(TestJSImplInterface arg); - void overload9(long? arg); - void overload9(DOMString arg); - void overload10(long? arg); - void overload10(object arg); - void overload11(long arg); - void overload11(DOMString? arg); - void overload12(long arg); - void overload12(boolean? arg); - void overload13(long? arg); - void overload13(boolean arg); - void overload14(optional long arg); - void overload14(TestInterface arg); - void overload15(long arg); - void overload15(optional TestInterface arg); - void overload16(long arg); - void overload16(optional TestInterface? arg); - void overload17(sequence arg); - void overload17(MozMap arg); - void overload18(MozMap arg); - void overload18(sequence arg); - void overload19(sequence arg); - void overload19(optional Dict arg); - void overload20(optional Dict arg); - void overload20(sequence arg); - - // Variadic handling - void passVariadicThirdArg(DOMString arg1, long arg2, TestJSImplInterface... arg3); - - // Conditionally exposed methods/attributes - [Pref="abc.def"] - readonly attribute boolean prefable1; - [Pref="abc.def"] - readonly attribute boolean prefable2; - [Pref="ghi.jkl"] - readonly attribute boolean prefable3; - [Pref="ghi.jkl"] - readonly attribute boolean prefable4; - [Pref="abc.def"] - readonly attribute boolean prefable5; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable6; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable7; - [Pref="ghi.jkl", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable8; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean prefable9; - [Pref="abc.def"] - void prefable10(); - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable11(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable12; - [Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void prefable13(); - [Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean prefable14; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable15; - [Func="TestFuncControlledMember"] - readonly attribute boolean prefable16; - [Pref="abc.def", Func="TestFuncControlledMember"] - void prefable17(); - [Func="TestFuncControlledMember"] - void prefable18(); - [Func="TestFuncControlledMember"] - void prefable19(); - [Pref="abc.def", Func="TestFuncControlledMember", ChromeOnly] - void prefable20(); - - // Conditionally exposed methods/attributes involving [SecureContext] - [SecureContext] - readonly attribute boolean conditionalOnSecureContext1; - [SecureContext, Pref="abc.def"] - readonly attribute boolean conditionalOnSecureContext2; - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - readonly attribute boolean conditionalOnSecureContext3; - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - readonly attribute boolean conditionalOnSecureContext4; - [SecureContext] - void conditionalOnSecureContext5(); - [SecureContext, Pref="abc.def"] - void conditionalOnSecureContext6(); - [SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::TouchEventsEnabled"] - void conditionalOnSecureContext7(); - [SecureContext, Pref="abc.def", Func="TestFuncControlledMember"] - void conditionalOnSecureContext8(); - - // Miscellania - [LenientThis] attribute long attrWithLenientThis; - // FIXME: Bug 863954 Unforgeable things get all confused when - // non-JS-implemented interfaces inherit from JS-implemented ones or vice - // versa. - // [Unforgeable] readonly attribute long unforgeableAttr; - // [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; - // [Unforgeable] long unforgeableMethod(); - // [Unforgeable, ChromeOnly] long unforgeableMethod2(); - // FIXME: Bug 863955 No stringifiers yet - // stringifier; - void passRenamedInterface(TestRenamedInterface arg); - [PutForwards=writableByte] readonly attribute TestJSImplInterface putForwardsAttr; - [PutForwards=writableByte, LenientThis] readonly attribute TestJSImplInterface putForwardsAttr2; - [PutForwards=writableByte, ChromeOnly] readonly attribute TestJSImplInterface putForwardsAttr3; - [Throws] void throwingMethod(); - [Throws] attribute boolean throwingAttr; - [GetterThrows] attribute boolean throwingGetterAttr; - [SetterThrows] attribute boolean throwingSetterAttr; - [CEReactions] void ceReactionsMethod(); - [CEReactions] void ceReactionsMethodOverload(); - [CEReactions] void ceReactionsMethodOverload(DOMString bar); - [CEReactions] attribute boolean ceReactionsAttr; - // NeedsSubjectPrincipal not supported on JS-implemented things for - // now, because we always pass in the caller principal anyway. - // [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod(); - // [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; - // legacycaller short(unsigned long arg1, TestInterface arg2); - void passArgsWithDefaults(optional long arg1, - optional TestInterface? arg2 = null, - optional Dict arg3, optional double arg4 = 5.0, - optional float arg5); - attribute any jsonifierShouldSkipThis; - attribute TestParentInterface jsonifierShouldSkipThis2; - attribute TestCallbackInterface jsonifierShouldSkipThis3; - jsonifier; - - attribute byte dashed-attribute; - void dashed-method(); - - // If you add things here, add them to TestCodeGen as well -}; - -[NavigatorProperty="TestNavigator", JSImplementation="@mozilla.org/test;1"] -interface TestNavigator { -}; - -[Constructor, NavigatorProperty="TestNavigatorWithConstructor", JSImplementation="@mozilla.org/test;1"] -interface TestNavigatorWithConstructor { -}; - -interface TestCImplementedInterface : TestJSImplInterface { -}; - -interface TestCImplementedInterface2 { -}; - -[NoInterfaceObject, - JSImplementation="@mozilla.org/test-js-impl-interface;2"] -interface TestJSImplNoInterfaceObject { - [Cached, Pure] - readonly attribute byte cachedByte; -}; diff --git a/dom/bindings/test/TestJSImplInheritanceGen.webidl b/dom/bindings/test/TestJSImplInheritanceGen.webidl deleted file mode 100644 index e62dbd10be..0000000000 --- a/dom/bindings/test/TestJSImplInheritanceGen.webidl +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface2;1"] -interface TestJSImplInterface2 : TestCImplementedInterface { -}; - -[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface3;1"] -interface TestJSImplInterface3 : TestCImplementedInterface2 { -}; - -// Important: TestJSImplInterface5 needs to come before TestJSImplInterface6 in -// this file to test what it's trying to test. -[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface5;1"] -interface TestJSImplInterface5 : TestJSImplInterface6 { -}; - -// Important: TestJSImplInterface6 needs to come after TestJSImplInterface3 in -// this file to test what it's trying to test. -[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface6;1"] -interface TestJSImplInterface6 : TestJSImplInterface3 { -}; - -[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface4;1"] -interface TestJSImplInterface4 : EventTarget { -}; diff --git a/dom/bindings/test/TestTypedef.webidl b/dom/bindings/test/TestTypedef.webidl deleted file mode 100644 index 7f758c79e8..0000000000 --- a/dom/bindings/test/TestTypedef.webidl +++ /dev/null @@ -1,7 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -typedef TestInterface YetAnotherNameForTestInterface; diff --git a/dom/bindings/test/chrome.ini b/dom/bindings/test/chrome.ini deleted file mode 100644 index 9fdbd7fd30..0000000000 --- a/dom/bindings/test/chrome.ini +++ /dev/null @@ -1,22 +0,0 @@ -[DEFAULT] -support-files = - !/dom/bindings/test/file_bug775543.html - !/dom/bindings/test/file_document_location_set_via_xray.html - !/dom/bindings/test/file_dom_xrays.html - !/dom/bindings/test/file_proxies_via_xray.html - -[test_bug775543.html] -[test_document_location_set_via_xray.html] -[test_dom_xrays.html] -[test_proxies_via_xray.html] -[test_document_location_via_xray_cached.html] -[test_blacklisted_prerendering_function.xul] -support-files = - file_focuser.html - file_fullScreenPropertyAccessor.html -skip-if = e10s # prerendering doesn't work in e10s yet -[test_kill_longrunning_prerendered_content.xul] -skip-if = e10s # prerendering doesn't work in e10s yet -[test_bug1123516_maplikesetlikechrome.xul] -skip-if = debug == false -[test_bug1287912.html] diff --git a/dom/bindings/test/file_InstanceOf.html b/dom/bindings/test/file_InstanceOf.html deleted file mode 100644 index 487010fa42..0000000000 --- a/dom/bindings/test/file_InstanceOf.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/dom/bindings/test/file_bug775543.html b/dom/bindings/test/file_bug775543.html deleted file mode 100644 index ee8c14c4d9..0000000000 --- a/dom/bindings/test/file_bug775543.html +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/dom/bindings/test/file_document_location_set_via_xray.html b/dom/bindings/test/file_document_location_set_via_xray.html deleted file mode 100644 index 323acba666..0000000000 --- a/dom/bindings/test/file_document_location_set_via_xray.html +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/dom/bindings/test/file_dom_xrays.html b/dom/bindings/test/file_dom_xrays.html deleted file mode 100644 index 36b3f8a300..0000000000 --- a/dom/bindings/test/file_dom_xrays.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - diff --git a/dom/bindings/test/file_focuser.html b/dom/bindings/test/file_focuser.html deleted file mode 100644 index 0d5240f95b..0000000000 --- a/dom/bindings/test/file_focuser.html +++ /dev/null @@ -1,24 +0,0 @@ - -
- diff --git a/dom/bindings/test/file_fullScreenPropertyAccessor.html b/dom/bindings/test/file_fullScreenPropertyAccessor.html deleted file mode 100644 index 92a37e0bac..0000000000 --- a/dom/bindings/test/file_fullScreenPropertyAccessor.html +++ /dev/null @@ -1,24 +0,0 @@ - -
- diff --git a/dom/bindings/test/file_proxies_via_xray.html b/dom/bindings/test/file_proxies_via_xray.html deleted file mode 100644 index 2e9a318309..0000000000 --- a/dom/bindings/test/file_proxies_via_xray.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/dom/bindings/test/forOf_iframe.html b/dom/bindings/test/forOf_iframe.html deleted file mode 100644 index 91417aba0e..0000000000 --- a/dom/bindings/test/forOf_iframe.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - iframe content for test_forOf_iframe.html - - -
- - - -
- - diff --git a/dom/bindings/test/mochitest.ini b/dom/bindings/test/mochitest.ini deleted file mode 100644 index 2cd322e741..0000000000 --- a/dom/bindings/test/mochitest.ini +++ /dev/null @@ -1,79 +0,0 @@ -[DEFAULT] -support-files = - file_InstanceOf.html - file_bug775543.html - file_document_location_set_via_xray.html - file_dom_xrays.html - file_proxies_via_xray.html - forOf_iframe.html - !/js/xpconnect/tests/mochitest/file_empty.html - -[test_async_stacks.html] -[test_ByteString.html] -[test_InstanceOf.html] -[test_bug560072.html] -[test_bug742191.html] -[test_bug759621.html] -[test_bug773326.html] -[test_bug788369.html] -[test_bug852846.html] -[test_bug862092.html] -[test_bug1036214.html] -skip-if = debug == false -[test_bug963382.html] -skip-if = debug == false -[test_bug1041646.html] -[test_bug1123875.html] -[test_barewordGetsWindow.html] -[test_callback_across_document_open.html] -[test_callback_default_thisval.html] -[test_cloneAndImportNode.html] -[test_defineProperty.html] -[test_enums.html] -[test_exceptionThrowing.html] -[test_exception_messages.html] -[test_forOf.html] -[test_integers.html] -[test_interfaceName.html] -[test_interfaceToString.html] -[test_exceptions_from_jsimplemented.html] -tags = webrtc -[test_lenientThis.html] -[test_lookupGetter.html] -[test_namedNoIndexed.html] -[test_named_getter_enumerability.html] -[test_Object.prototype_props.html] -[test_queryInterface.html] -[test_returnUnion.html] -skip-if = debug == false -[test_usvstring.html] -skip-if = debug == false -[test_sequence_wrapping.html] -subsuite = gpu -[test_setWithNamedGetterNoNamedSetter.html] -[test_throwing_method_noDCE.html] -[test_treat_non_object_as_null.html] -[test_traceProtos.html] -[test_sequence_detection.html] -skip-if = debug == false -[test_exception_options_from_jsimplemented.html] -skip-if = debug == false -[test_promise_rejections_from_jsimplemented.html] -skip-if = debug == false -[test_worker_UnwrapArg.html] -[test_unforgeablesonexpando.html] -[test_crossOriginWindowSymbolAccess.html] -[test_primitive_this.html] -[test_callback_exceptions.html] -[test_bug1123516_maplikesetlike.html] -skip-if = debug == false -[test_jsimplemented_eventhandler.html] -skip-if = debug == false -[test_iterable.html] -skip-if = debug == false -[test_oom_reporting.html] -[test_domProxyArrayLengthGetter.html] -[test_exceptionSanitization.html] -skip-if = os == "android" -[test_stringBindings.html] -skip-if = debug == false diff --git a/dom/bindings/test/moz.build b/dom/bindings/test/moz.build deleted file mode 100644 index 7d0cb6c212..0000000000 --- a/dom/bindings/test/moz.build +++ /dev/null @@ -1,58 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DEFINES.update({ - 'IMPL_LIBXUL': True, - 'MOZILLA_INTERNAL_API': True, -}) - -# Do NOT export this library. We don't actually want our test code -# being added to libxul or anything. - -Library('dombindings_test_s') - -EXTRA_COMPONENTS += [ - 'TestInterfaceJS.js', - 'TestInterfaceJS.manifest', - 'TestInterfaceJSMaplike.js' -] - -MOCHITEST_MANIFESTS += ['mochitest.ini'] - -MOCHITEST_CHROME_MANIFESTS += ['chrome.ini'] - -TEST_WEBIDL_FILES += [ - 'TestDictionary.webidl', - 'TestJSImplInheritanceGen.webidl', - 'TestTypedef.webidl', -] - -PREPROCESSED_TEST_WEBIDL_FILES += [ - 'TestCodeGen.webidl', - 'TestExampleGen.webidl', - 'TestJSImplGen.webidl', -] - -WEBIDL_EXAMPLE_INTERFACES += [ - 'TestExampleInterface', - 'TestExampleProxyInterface', - 'TestExampleWorkerInterface', -] - -# Bug 932082 tracks having bindings use namespaced includes. -LOCAL_INCLUDES += [ - '!/dist/include/mozilla/dom', -] - -LOCAL_INCLUDES += [ - '!..', - '/dom/bindings', - '/js/xpconnect/src', - '/js/xpconnect/wrappers', -] - -if CONFIG['GNU_CXX']: - CXXFLAGS += ['-Wno-error=shadow'] diff --git a/dom/bindings/test/test_ByteString.html b/dom/bindings/test/test_ByteString.html deleted file mode 100644 index c7e6321173..0000000000 --- a/dom/bindings/test/test_ByteString.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - Test for ByteString support - - - - -Mozilla Bug 796850 -

-
-
-
- - diff --git a/dom/bindings/test/test_InstanceOf.html b/dom/bindings/test/test_InstanceOf.html deleted file mode 100644 index 514ec1b2aa..0000000000 --- a/dom/bindings/test/test_InstanceOf.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Test for Bug 748983 - - - - -Mozilla Bug 748983 -

- -
-
-
- - - diff --git a/dom/bindings/test/test_Object.prototype_props.html b/dom/bindings/test/test_Object.prototype_props.html deleted file mode 100644 index 3ab27c5e4a..0000000000 --- a/dom/bindings/test/test_Object.prototype_props.html +++ /dev/null @@ -1,20 +0,0 @@ - - -Test for bug 987110 - - -
- diff --git a/dom/bindings/test/test_async_stacks.html b/dom/bindings/test/test_async_stacks.html deleted file mode 100644 index 8b655a14d7..0000000000 --- a/dom/bindings/test/test_async_stacks.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - Test for Bug 1148593 - - - - - -Mozilla Bug 1148593 -

- -
-
- - diff --git a/dom/bindings/test/test_barewordGetsWindow.html b/dom/bindings/test/test_barewordGetsWindow.html deleted file mode 100644 index e098eea539..0000000000 --- a/dom/bindings/test/test_barewordGetsWindow.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - Test for Bug 936056 - - - - - -Mozilla Bug 936056 -

- -
-
- - diff --git a/dom/bindings/test/test_blacklisted_prerendering_function.xul b/dom/bindings/test/test_blacklisted_prerendering_function.xul deleted file mode 100644 index 02a76d88d9..0000000000 --- a/dom/bindings/test/test_blacklisted_prerendering_function.xul +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - -Mozilla Bug 1069719 -

- -
-
- - - -
diff --git a/dom/bindings/test/test_bug1036214.html b/dom/bindings/test/test_bug1036214.html deleted file mode 100644 index dd98eb482f..0000000000 --- a/dom/bindings/test/test_bug1036214.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - Test for Bug 1036214 - - - - - -Mozilla Bug 1036214 -

- -
-
- - - diff --git a/dom/bindings/test/test_bug1041646.html b/dom/bindings/test/test_bug1041646.html deleted file mode 100644 index 22baed454e..0000000000 --- a/dom/bindings/test/test_bug1041646.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - Test for Bug 1041646 - - - - - -Mozilla Bug 1041646 -

- -
-
- - diff --git a/dom/bindings/test/test_bug1123516_maplikesetlike.html b/dom/bindings/test/test_bug1123516_maplikesetlike.html deleted file mode 100644 index 18ede38ace..0000000000 --- a/dom/bindings/test/test_bug1123516_maplikesetlike.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - Test Maplike Interface - - - - - - - diff --git a/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xul b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xul deleted file mode 100644 index 4bc45cdddc..0000000000 --- a/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xul +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - Mozilla Bug 1123516 - - - - - diff --git a/dom/bindings/test/test_bug1123875.html b/dom/bindings/test/test_bug1123875.html deleted file mode 100644 index 5658091c44..0000000000 --- a/dom/bindings/test/test_bug1123875.html +++ /dev/null @@ -1,14 +0,0 @@ - - -Test for Bug 1123875 - - -
- diff --git a/dom/bindings/test/test_bug1287912.html b/dom/bindings/test/test_bug1287912.html deleted file mode 100644 index ae72b23165..0000000000 --- a/dom/bindings/test/test_bug1287912.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Test for Bug 1287912 - - - - -Mozilla Bug 1287912 -

- -
-
-
- - diff --git a/dom/bindings/test/test_bug560072.html b/dom/bindings/test/test_bug560072.html deleted file mode 100644 index 0eebff1160..0000000000 --- a/dom/bindings/test/test_bug560072.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Test for Bug 560072 - - - - -Mozilla Bug 560072 -

- -
-
-
- - diff --git a/dom/bindings/test/test_bug742191.html b/dom/bindings/test/test_bug742191.html deleted file mode 100644 index b4b3151d77..0000000000 --- a/dom/bindings/test/test_bug742191.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Test for invalid argument object - - - - -Mozilla Bug 742191 -

-
-
-
- - diff --git a/dom/bindings/test/test_bug759621.html b/dom/bindings/test/test_bug759621.html deleted file mode 100644 index 602a0cd7cd..0000000000 --- a/dom/bindings/test/test_bug759621.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Test for Bug 759621 - - - - -Mozilla Bug 759621 -

- -
-
-
- - diff --git a/dom/bindings/test/test_bug773326.html b/dom/bindings/test/test_bug773326.html deleted file mode 100644 index 2e3b1ea304..0000000000 --- a/dom/bindings/test/test_bug773326.html +++ /dev/null @@ -1,11 +0,0 @@ - - -Test for Bug 773326 - - -
- diff --git a/dom/bindings/test/test_bug775543.html b/dom/bindings/test/test_bug775543.html deleted file mode 100644 index d8df05f630..0000000000 --- a/dom/bindings/test/test_bug775543.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Test for Bug 775543 - - - - -Mozilla Bug 775543 -

- -
-
-
- - diff --git a/dom/bindings/test/test_bug788369.html b/dom/bindings/test/test_bug788369.html deleted file mode 100644 index 787bd28fe3..0000000000 --- a/dom/bindings/test/test_bug788369.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - Test for Bug 788369 - - - - -Mozilla Bug 788369 -

- -
-
-
- - diff --git a/dom/bindings/test/test_bug852846.html b/dom/bindings/test/test_bug852846.html deleted file mode 100644 index 0ca2c7dad4..0000000000 --- a/dom/bindings/test/test_bug852846.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Test for Bug 852846 - - - - - -Mozilla Bug 852846 -

- -
-
- - diff --git a/dom/bindings/test/test_bug862092.html b/dom/bindings/test/test_bug862092.html deleted file mode 100644 index 4b06333281..0000000000 --- a/dom/bindings/test/test_bug862092.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Test for Bug 862092 - - - - - -Mozilla Bug 862092 -

- -
-
- - diff --git a/dom/bindings/test/test_bug963382.html b/dom/bindings/test/test_bug963382.html deleted file mode 100644 index f48d2e8b0f..0000000000 --- a/dom/bindings/test/test_bug963382.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - Test for Bug 963382 - - - - - -Mozilla Bug 963382 -

- -
-
- - diff --git a/dom/bindings/test/test_callback_across_document_open.html b/dom/bindings/test/test_callback_across_document_open.html deleted file mode 100644 index 2a505cefab..0000000000 --- a/dom/bindings/test/test_callback_across_document_open.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Test for callback invocation for a callback that comes from a - no-longer-current window that still has an active document. - - -
- - diff --git a/dom/bindings/test/test_callback_default_thisval.html b/dom/bindings/test/test_callback_default_thisval.html deleted file mode 100644 index d98ed87b25..0000000000 --- a/dom/bindings/test/test_callback_default_thisval.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Test for Bug 957929 - - - - - -Mozilla Bug 957929 -

- -
-
- - diff --git a/dom/bindings/test/test_callback_exceptions.html b/dom/bindings/test/test_callback_exceptions.html deleted file mode 100644 index a40b0b94fa..0000000000 --- a/dom/bindings/test/test_callback_exceptions.html +++ /dev/null @@ -1,17 +0,0 @@ - - -Test for ... - - -
- diff --git a/dom/bindings/test/test_cloneAndImportNode.html b/dom/bindings/test/test_cloneAndImportNode.html deleted file mode 100644 index fc53c87476..0000000000 --- a/dom/bindings/test/test_cloneAndImportNode.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - Test for Bug 882541 - - - - - -Mozilla Bug 882541 -

- -
-
- - diff --git a/dom/bindings/test/test_crossOriginWindowSymbolAccess.html b/dom/bindings/test/test_crossOriginWindowSymbolAccess.html deleted file mode 100644 index 7808631b6b..0000000000 --- a/dom/bindings/test/test_crossOriginWindowSymbolAccess.html +++ /dev/null @@ -1,23 +0,0 @@ - - -Test for accessing symbols on a cross-origin window - - -
- - diff --git a/dom/bindings/test/test_defineProperty.html b/dom/bindings/test/test_defineProperty.html deleted file mode 100644 index f8f5f6283e..0000000000 --- a/dom/bindings/test/test_defineProperty.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - Test for Bug 910220 - - - - -Mozilla Bug 910220 -

- -
-
- - - diff --git a/dom/bindings/test/test_document_location_set_via_xray.html b/dom/bindings/test/test_document_location_set_via_xray.html deleted file mode 100644 index cdadc50639..0000000000 --- a/dom/bindings/test/test_document_location_set_via_xray.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - Test for Bug 905493 - - - - -Mozilla Bug 905493 -

- -
-
-
- - diff --git a/dom/bindings/test/test_document_location_via_xray_cached.html b/dom/bindings/test/test_document_location_via_xray_cached.html deleted file mode 100644 index 20eef10fbe..0000000000 --- a/dom/bindings/test/test_document_location_via_xray_cached.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Test for Bug 1041731 - - - - -Mozilla Bug 1041731 -

- -
-
-
- - diff --git a/dom/bindings/test/test_domProxyArrayLengthGetter.html b/dom/bindings/test/test_domProxyArrayLengthGetter.html deleted file mode 100644 index a62adff2ed..0000000000 --- a/dom/bindings/test/test_domProxyArrayLengthGetter.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - Test for Bug 1221421 - - - - - - - Mozilla Bug 1221421 - - diff --git a/dom/bindings/test/test_dom_xrays.html b/dom/bindings/test/test_dom_xrays.html deleted file mode 100644 index 15d7013ade..0000000000 --- a/dom/bindings/test/test_dom_xrays.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - Test for Bug 787070 - - - - -Mozilla Bug 787070 -

- -
-
-
- - diff --git a/dom/bindings/test/test_enums.html b/dom/bindings/test/test_enums.html deleted file mode 100644 index e5dc519a0c..0000000000 --- a/dom/bindings/test/test_enums.html +++ /dev/null @@ -1,15 +0,0 @@ - - -Enums - - -
- diff --git a/dom/bindings/test/test_exceptionSanitization.html b/dom/bindings/test/test_exceptionSanitization.html deleted file mode 100644 index 9a6ab6088c..0000000000 --- a/dom/bindings/test/test_exceptionSanitization.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - Test for Bug 1295322 - - - - -Mozilla Bug 1295322 -

- -
-
- - - diff --git a/dom/bindings/test/test_exceptionThrowing.html b/dom/bindings/test/test_exceptionThrowing.html deleted file mode 100644 index 376c2bc578..0000000000 --- a/dom/bindings/test/test_exceptionThrowing.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - Test for Bug 847119 - - - - - -Mozilla Bug 847119 -

- -
-
- - diff --git a/dom/bindings/test/test_exception_messages.html b/dom/bindings/test/test_exception_messages.html deleted file mode 100644 index a0f0cabe63..0000000000 --- a/dom/bindings/test/test_exception_messages.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - Test for Bug 882653 - - - - - -Mozilla Bug 882653 -

- -
-
- - diff --git a/dom/bindings/test/test_exception_options_from_jsimplemented.html b/dom/bindings/test/test_exception_options_from_jsimplemented.html deleted file mode 100644 index 8a98a8fb63..0000000000 --- a/dom/bindings/test/test_exception_options_from_jsimplemented.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - Test for Bug 1107592 - - - - - -Mozilla Bug 1107592 -

- -
-
- - diff --git a/dom/bindings/test/test_exceptions_from_jsimplemented.html b/dom/bindings/test/test_exceptions_from_jsimplemented.html deleted file mode 100644 index d0f599353a..0000000000 --- a/dom/bindings/test/test_exceptions_from_jsimplemented.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - Test for Bug 923010 - - - - - -Mozilla Bug 923010 -

- -
-
- - diff --git a/dom/bindings/test/test_forOf.html b/dom/bindings/test/test_forOf.html deleted file mode 100644 index 53969a23e7..0000000000 --- a/dom/bindings/test/test_forOf.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Test for Bug 725907 - - - - -Mozilla Bug 725907 -

- -
- - - -
-
-
-
-
-
-
- - diff --git a/dom/bindings/test/test_integers.html b/dom/bindings/test/test_integers.html deleted file mode 100644 index c74b68216c..0000000000 --- a/dom/bindings/test/test_integers.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - -

- -
-
-
- - diff --git a/dom/bindings/test/test_interfaceName.html b/dom/bindings/test/test_interfaceName.html deleted file mode 100644 index 59828a2cf2..0000000000 --- a/dom/bindings/test/test_interfaceName.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - Test for Bug 1084001 - - - - - -Mozilla Bug 1084001 -

- -
-
- - diff --git a/dom/bindings/test/test_interfaceToString.html b/dom/bindings/test/test_interfaceToString.html deleted file mode 100644 index c97b2f63b5..0000000000 --- a/dom/bindings/test/test_interfaceToString.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Test for Bug 742156 - - - - -Mozilla Bug 742156 -

- -
-
-
- - diff --git a/dom/bindings/test/test_iterable.html b/dom/bindings/test/test_iterable.html deleted file mode 100644 index 8ce818e764..0000000000 --- a/dom/bindings/test/test_iterable.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - Test Iterable Interface - - - - - - - diff --git a/dom/bindings/test/test_jsimplemented_eventhandler.html b/dom/bindings/test/test_jsimplemented_eventhandler.html deleted file mode 100644 index 2854a31125..0000000000 --- a/dom/bindings/test/test_jsimplemented_eventhandler.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Test for Bug 1186696 - - - - - -Mozilla Bug 1186696 -

- -
-
- - diff --git a/dom/bindings/test/test_kill_longrunning_prerendered_content.xul b/dom/bindings/test/test_kill_longrunning_prerendered_content.xul deleted file mode 100644 index d86b15ad9f..0000000000 --- a/dom/bindings/test/test_kill_longrunning_prerendered_content.xul +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - -Mozilla Bug 1050456 -

- -
-
- - -
diff --git a/dom/bindings/test/test_lenientThis.html b/dom/bindings/test/test_lenientThis.html deleted file mode 100644 index cfbdcebcda..0000000000 --- a/dom/bindings/test/test_lenientThis.html +++ /dev/null @@ -1,27 +0,0 @@ - - -[LenientThis] - - -
- diff --git a/dom/bindings/test/test_lookupGetter.html b/dom/bindings/test/test_lookupGetter.html deleted file mode 100644 index 306ee4f643..0000000000 --- a/dom/bindings/test/test_lookupGetter.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - Test for Bug 462428 - - - - -Mozilla Bug 462428 -

- -
-
-
- - diff --git a/dom/bindings/test/test_namedNoIndexed.html b/dom/bindings/test/test_namedNoIndexed.html deleted file mode 100644 index 205ec89f95..0000000000 --- a/dom/bindings/test/test_namedNoIndexed.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Test for Bug 808991 - - - - -Mozilla Bug 808991 -

- -
-
-
- - diff --git a/dom/bindings/test/test_named_getter_enumerability.html b/dom/bindings/test/test_named_getter_enumerability.html deleted file mode 100644 index 641f78ab29..0000000000 --- a/dom/bindings/test/test_named_getter_enumerability.html +++ /dev/null @@ -1,40 +0,0 @@ - - -Test for named getter enumerability - - -
- diff --git a/dom/bindings/test/test_oom_reporting.html b/dom/bindings/test/test_oom_reporting.html deleted file mode 100644 index 7323736e50..0000000000 --- a/dom/bindings/test/test_oom_reporting.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - Test for Bug - - - - - -Mozilla Bug -

- -
-
- - diff --git a/dom/bindings/test/test_primitive_this.html b/dom/bindings/test/test_primitive_this.html deleted file mode 100644 index d2b733dffe..0000000000 --- a/dom/bindings/test/test_primitive_this.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - Test for Bug 603201 - - - - - -
Test
- - diff --git a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html deleted file mode 100644 index 68de079ed6..0000000000 --- a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - Test for Bug 1107592 - - - - - -Mozilla Bug 1107592 -

- -
-
- - diff --git a/dom/bindings/test/test_proxies_via_xray.html b/dom/bindings/test/test_proxies_via_xray.html deleted file mode 100644 index 59affe6c05..0000000000 --- a/dom/bindings/test/test_proxies_via_xray.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - Test for Bug 1021066 - - - - -Mozilla Bug 1021066 -

- -
-
-
- - diff --git a/dom/bindings/test/test_queryInterface.html b/dom/bindings/test/test_queryInterface.html deleted file mode 100644 index 076bf9e7db..0000000000 --- a/dom/bindings/test/test_queryInterface.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - Test for Bug 827546 - - - - - -Mozilla Bug 827546 -

- -
-
- - diff --git a/dom/bindings/test/test_returnUnion.html b/dom/bindings/test/test_returnUnion.html deleted file mode 100644 index 5be10ba3c6..0000000000 --- a/dom/bindings/test/test_returnUnion.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Test for Bug 1048659 - - - - - -Mozilla Bug 1048659 -

- -
-
- - diff --git a/dom/bindings/test/test_sequence_detection.html b/dom/bindings/test/test_sequence_detection.html deleted file mode 100644 index 80dfac4db9..0000000000 --- a/dom/bindings/test/test_sequence_detection.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Test for Bug 1066432 - - - - - -Mozilla Bug 1066432 -

- -
-
- - diff --git a/dom/bindings/test/test_sequence_wrapping.html b/dom/bindings/test/test_sequence_wrapping.html deleted file mode 100644 index 7132e56019..0000000000 --- a/dom/bindings/test/test_sequence_wrapping.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Test for Bug 775852 - - - - -Mozilla Bug 775852 -

- -
-
-
- - diff --git a/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html b/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html deleted file mode 100644 index 52f56151d4..0000000000 --- a/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - Test for Bug 1043690 - - - - -Mozilla Bug 1043690 -

- - -
-
- - diff --git a/dom/bindings/test/test_stringBindings.html b/dom/bindings/test/test_stringBindings.html deleted file mode 100644 index 1895b0342d..0000000000 --- a/dom/bindings/test/test_stringBindings.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Test for Bug 1334537 - - - - - -Mozilla Bug 1334537 -

- -
-
- - diff --git a/dom/bindings/test/test_throwing_method_noDCE.html b/dom/bindings/test/test_throwing_method_noDCE.html deleted file mode 100644 index e952819a8b..0000000000 --- a/dom/bindings/test/test_throwing_method_noDCE.html +++ /dev/null @@ -1,27 +0,0 @@ - - -Test that we don't DCE functions that can throw - - -
- diff --git a/dom/bindings/test/test_traceProtos.html b/dom/bindings/test/test_traceProtos.html deleted file mode 100644 index 17a5cb96d4..0000000000 --- a/dom/bindings/test/test_traceProtos.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Test for Bug 744772 - - - - -Mozilla Bug 744772 -

- -
-
-
- - diff --git a/dom/bindings/test/test_treat_non_object_as_null.html b/dom/bindings/test/test_treat_non_object_as_null.html deleted file mode 100644 index fbb6ceb66b..0000000000 --- a/dom/bindings/test/test_treat_non_object_as_null.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - Test for Bug 952365 - - - - - -Mozilla Bug 952365 -

- -
-
- - diff --git a/dom/bindings/test/test_unforgeablesonexpando.html b/dom/bindings/test/test_unforgeablesonexpando.html deleted file mode 100644 index 419e6ac7d5..0000000000 --- a/dom/bindings/test/test_unforgeablesonexpando.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Test for making sure named getters don't override the unforgeable location on HTMLDocument - - -
- - diff --git a/dom/bindings/test/test_usvstring.html b/dom/bindings/test/test_usvstring.html deleted file mode 100644 index cbb1e7971d..0000000000 --- a/dom/bindings/test/test_usvstring.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - Test USVString - - - - - - - diff --git a/dom/bindings/test/test_worker_UnwrapArg.html b/dom/bindings/test/test_worker_UnwrapArg.html deleted file mode 100644 index 1331a83f41..0000000000 --- a/dom/bindings/test/test_worker_UnwrapArg.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - Test for Bug 1127206 - - - - - -Mozilla Bug 1127206 -

- -
-
- - diff --git a/dom/media/gtest/moz.build b/dom/media/gtest/moz.build index ae059962c8..a7ea738073 100644 --- a/dom/media/gtest/moz.build +++ b/dom/media/gtest/moz.build @@ -28,11 +28,6 @@ UNIFIED_SOURCES += [ 'TestWebMBuffered.cpp', ] -if CONFIG['MOZ_EME']: - UNIFIED_SOURCES += [ - 'TestEME.cpp', - ] - if CONFIG['MOZ_WEBM_ENCODER']: UNIFIED_SOURCES += [ 'TestVideoTrackEncoder.cpp', diff --git a/dom/media/webaudio/gtest/TestAudioEventTimeline.cpp b/dom/media/webaudio/gtest/TestAudioEventTimeline.cpp index cc731d3e2b..661b6cbd26 100644 --- a/dom/media/webaudio/gtest/TestAudioEventTimeline.cpp +++ b/dom/media/webaudio/gtest/TestAudioEventTimeline.cpp @@ -9,17 +9,6 @@ #include #include "gtest/gtest.h" -// Mock the MediaStream class -namespace mozilla { -class MediaStream -{ - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStream) -private: - ~MediaStream() { - }; -}; -} - using namespace mozilla; using namespace mozilla::dom; using std::numeric_limits; diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini index 0e8587f34d..64aefcd12a 100644 --- a/dom/plugins/test/mochitest/mochitest.ini +++ b/dom/plugins/test/mochitest/mochitest.ini @@ -23,7 +23,6 @@ support-files = pluginstream.js post.sjs plugin-utils.js - !/toolkit/components/passwordmgr/test/authenticate.sjs [test_bug406541.html] [test_bug532208.html] diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini index 84322d21d0..428cc0e73f 100644 --- a/dom/tests/mochitest/webcomponents/mochitest.ini +++ b/dom/tests/mochitest/webcomponents/mochitest.ini @@ -22,19 +22,14 @@ skip-if = true || stylo # disabled - See bug 1390396 and 1293844 [test_custom_element_when_defined.html] [test_custom_element_uncatchable_exception.html] skip-if = !debug # TestFunctions only applied in debug builds -[test_custom_element_define.html] -[test_custom_element_define_parser.html] -[test_custom_element_template.html] [test_detached_style.html] [test_document_adoptnode.html] [test_document_importnode.html] [test_document_register.html] [test_document_register_lifecycle.html] skip-if = true # disabled - See bug 1390396 -[test_document_register_parser.html] [test_document_register_stack.html] skip-if = true # disabled - See bug 1390396 -[test_document_shared_registry.html] [test_event_retarget.html] [test_event_stopping.html] [test_template.html] diff --git a/image/moz.build b/image/moz.build index 7e7e0fe700..9eed46d31e 100644 --- a/image/moz.build +++ b/image/moz.build @@ -5,8 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DIRS += ['build', 'decoders', 'encoders'] -if CONFIG['ENABLE_TESTS']: - DIRS += ['test/gtest'] with Files('**'): BUG_COMPONENT = ('Core', 'ImageLib') diff --git a/image/test/gtest/Common.cpp b/image/test/gtest/Common.cpp deleted file mode 100644 index 5a24bbb145..0000000000 --- a/image/test/gtest/Common.cpp +++ /dev/null @@ -1,673 +0,0 @@ -/* -*- 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 "Common.h" - -#include - -#include "nsDirectoryServiceDefs.h" -#include "nsIDirectoryService.h" -#include "nsIFile.h" -#include "nsIInputStream.h" -#include "nsIProperties.h" -#include "nsNetUtil.h" -#include "mozilla/RefPtr.h" -#include "nsStreamUtils.h" -#include "nsString.h" - -namespace mozilla { -namespace image { - -using namespace gfx; - -using std::abs; -using std::vector; - -/////////////////////////////////////////////////////////////////////////////// -// General Helpers -/////////////////////////////////////////////////////////////////////////////// - -// These macros work like gtest's ASSERT_* macros, except that they can be used -// in functions that return values. -#define ASSERT_TRUE_OR_RETURN(e, rv) \ - EXPECT_TRUE(e); \ - if (!(e)) { \ - return rv; \ - } - -#define ASSERT_EQ_OR_RETURN(a, b, rv) \ - EXPECT_EQ(a, b); \ - if ((a) != (b)) { \ - return rv; \ - } - -#define ASSERT_GE_OR_RETURN(a, b, rv) \ - EXPECT_GE(a, b); \ - if (!((a) >= (b))) { \ - return rv; \ - } - -#define ASSERT_LE_OR_RETURN(a, b, rv) \ - EXPECT_LE(a, b); \ - if (!((a) <= (b))) { \ - return rv; \ - } - -#define ASSERT_LT_OR_RETURN(a, b, rv) \ - EXPECT_LT(a, b); \ - if (!((a) < (b))) { \ - return rv; \ - } - -already_AddRefed -LoadFile(const char* aRelativePath) -{ - nsresult rv; - - nsCOMPtr dirService = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); - ASSERT_TRUE_OR_RETURN(dirService != nullptr, nullptr); - - // Retrieve the current working directory. - nsCOMPtr file; - rv = dirService->Get(NS_OS_CURRENT_WORKING_DIR, - NS_GET_IID(nsIFile), getter_AddRefs(file)); - ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr); - - // Construct the final path by appending the working path to the current - // working directory. - file->AppendNative(nsDependentCString(aRelativePath)); - - // Construct an input stream for the requested file. - nsCOMPtr inputStream; - rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file); - ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr); - - // Ensure the resulting input stream is buffered. - if (!NS_InputStreamIsBuffered(inputStream)) { - nsCOMPtr bufStream; - rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), - inputStream, 1024); - ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr); - inputStream = bufStream; - } - - return inputStream.forget(); -} - -bool -IsSolidColor(SourceSurface* aSurface, - BGRAColor aColor, - uint8_t aFuzz /* = 0 */) -{ - IntSize size = aSurface->GetSize(); - return RectIsSolidColor(aSurface, IntRect(0, 0, size.width, size.height), - aColor, aFuzz); -} - -bool -IsSolidPalettedColor(Decoder* aDecoder, uint8_t aColor) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - return PalettedRectIsSolidColor(aDecoder, currentFrame->GetRect(), aColor); -} - -bool -RowsAreSolidColor(SourceSurface* aSurface, - int32_t aStartRow, - int32_t aRowCount, - BGRAColor aColor, - uint8_t aFuzz /* = 0 */) -{ - IntSize size = aSurface->GetSize(); - return RectIsSolidColor(aSurface, IntRect(0, aStartRow, size.width, aRowCount), - aColor, aFuzz); -} - -bool -PalettedRowsAreSolidColor(Decoder* aDecoder, - int32_t aStartRow, - int32_t aRowCount, - uint8_t aColor) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - IntRect frameRect = currentFrame->GetRect(); - IntRect solidColorRect(frameRect.x, aStartRow, frameRect.width, aRowCount); - return PalettedRectIsSolidColor(aDecoder, solidColorRect, aColor); -} - -bool -RectIsSolidColor(SourceSurface* aSurface, - const IntRect& aRect, - BGRAColor aColor, - uint8_t aFuzz /* = 0 */) -{ - IntSize surfaceSize = aSurface->GetSize(); - IntRect rect = - aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height)); - - RefPtr dataSurface = aSurface->GetDataSurface(); - ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false); - - ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false); - - DataSourceSurface::ScopedMap mapping(dataSurface, - DataSourceSurface::MapType::READ); - ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false); - - uint8_t* data = dataSurface->GetData(); - ASSERT_TRUE_OR_RETURN(data != nullptr, false); - - int32_t rowLength = dataSurface->Stride(); - for (int32_t row = rect.y; row < rect.YMost(); ++row) { - for (int32_t col = rect.x; col < rect.XMost(); ++col) { - int32_t i = row * rowLength + col * 4; - if (aFuzz != 0) { - ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), aFuzz, false); - ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), aFuzz, false); - ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), aFuzz, false); - ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), aFuzz, false); - } else { - ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false); - ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false); - ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false); - ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false); - } - } - } - - return true; -} - -bool -PalettedRectIsSolidColor(Decoder* aDecoder, const IntRect& aRect, uint8_t aColor) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - uint8_t* imageData; - uint32_t imageLength; - currentFrame->GetImageData(&imageData, &imageLength); - ASSERT_TRUE_OR_RETURN(imageData, false); - - // Clamp to the frame rect. If any pixels outside the frame rect are included, - // we immediately fail, because such pixels don't have any "color" in the - // sense this function measures - they're transparent, and that doesn't - // necessarily correspond to any color palette index at all. - IntRect frameRect = currentFrame->GetRect(); - ASSERT_EQ_OR_RETURN(imageLength, uint32_t(frameRect.Area()), false); - IntRect rect = aRect.Intersect(frameRect); - ASSERT_EQ_OR_RETURN(rect.Area(), aRect.Area(), false); - - // Translate |rect| by |frameRect.TopLeft()| to reflect the fact that the - // frame rect's offset doesn't actually mean anything in terms of the - // in-memory representation of the surface. The image data starts at the upper - // left corner of the frame rect, in other words. - rect -= frameRect.TopLeft(); - - // Walk through the image data and make sure that the entire rect has the - // palette index |aColor|. - int32_t rowLength = frameRect.width; - for (int32_t row = rect.y; row < rect.YMost(); ++row) { - for (int32_t col = rect.x; col < rect.XMost(); ++col) { - int32_t i = row * rowLength + col; - ASSERT_EQ_OR_RETURN(aColor, imageData[i], false); - } - } - - return true; -} - -bool -RowHasPixels(SourceSurface* aSurface, - int32_t aRow, - const vector& aPixels) -{ - ASSERT_GE_OR_RETURN(aRow, 0, false); - - IntSize surfaceSize = aSurface->GetSize(); - ASSERT_EQ_OR_RETURN(aPixels.size(), size_t(surfaceSize.width), false); - ASSERT_LT_OR_RETURN(aRow, surfaceSize.height, false); - - RefPtr dataSurface = aSurface->GetDataSurface(); - ASSERT_TRUE_OR_RETURN(dataSurface, false); - - ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false); - - DataSourceSurface::ScopedMap mapping(dataSurface, - DataSourceSurface::MapType::READ); - ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false); - - uint8_t* data = dataSurface->GetData(); - ASSERT_TRUE_OR_RETURN(data != nullptr, false); - - int32_t rowLength = dataSurface->Stride(); - for (int32_t col = 0; col < surfaceSize.width; ++col) { - int32_t i = aRow * rowLength + col * 4; - ASSERT_EQ_OR_RETURN(aPixels[col].mBlue, data[i + 0], false); - ASSERT_EQ_OR_RETURN(aPixels[col].mGreen, data[i + 1], false); - ASSERT_EQ_OR_RETURN(aPixels[col].mRed, data[i + 2], false); - ASSERT_EQ_OR_RETURN(aPixels[col].mAlpha, data[i + 3], false); - } - - return true; -} - - -/////////////////////////////////////////////////////////////////////////////// -// SurfacePipe Helpers -/////////////////////////////////////////////////////////////////////////////// - -already_AddRefed -CreateTrivialDecoder() -{ - gfxPrefs::GetSingleton(); - DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif"); - NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); - RefPtr decoder = - DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(), - DefaultSurfaceFlags()); - return decoder.forget(); -} - -void -AssertCorrectPipelineFinalState(SurfaceFilter* aFilter, - const gfx::IntRect& aInputSpaceRect, - const gfx::IntRect& aOutputSpaceRect) -{ - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect); - EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect); -} - -void -CheckGeneratedImage(Decoder* aDecoder, - const IntRect& aRect, - uint8_t aFuzz /* = 0 */) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - const IntSize surfaceSize = surface->GetSize(); - - // This diagram shows how the surface is divided into regions that the code - // below tests for the correct content. The output rect is the bounds of the - // region labeled 'C'. - // - // +---------------------------+ - // | A | - // +---------+--------+--------+ - // | B | C | D | - // +---------+--------+--------+ - // | E | - // +---------------------------+ - - // Check that the output rect itself is green. (Region 'C'.) - EXPECT_TRUE(RectIsSolidColor(surface, aRect, BGRAColor::Green(), aFuzz)); - - // Check that the area above the output rect is transparent. (Region 'A'.) - EXPECT_TRUE(RectIsSolidColor(surface, - IntRect(0, 0, surfaceSize.width, aRect.y), - BGRAColor::Transparent(), aFuzz)); - - // Check that the area to the left of the output rect is transparent. (Region 'B'.) - EXPECT_TRUE(RectIsSolidColor(surface, - IntRect(0, aRect.y, aRect.x, aRect.YMost()), - BGRAColor::Transparent(), aFuzz)); - - // Check that the area to the right of the output rect is transparent. (Region 'D'.) - const int32_t widthOnRight = surfaceSize.width - aRect.XMost(); - EXPECT_TRUE(RectIsSolidColor(surface, - IntRect(aRect.XMost(), aRect.y, widthOnRight, aRect.YMost()), - BGRAColor::Transparent(), aFuzz)); - - // Check that the area below the output rect is transparent. (Region 'E'.) - const int32_t heightBelow = surfaceSize.height - aRect.YMost(); - EXPECT_TRUE(RectIsSolidColor(surface, - IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow), - BGRAColor::Transparent(), aFuzz)); -} - -void -CheckGeneratedPalettedImage(Decoder* aDecoder, const IntRect& aRect) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - IntSize imageSize = currentFrame->GetImageSize(); - - // This diagram shows how the surface is divided into regions that the code - // below tests for the correct content. The output rect is the bounds of the - // region labeled 'C'. - // - // +---------------------------+ - // | A | - // +---------+--------+--------+ - // | B | C | D | - // +---------+--------+--------+ - // | E | - // +---------------------------+ - - // Check that the output rect itself is all 255's. (Region 'C'.) - EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, aRect, 255)); - - // Check that the area above the output rect is all 0's. (Region 'A'.) - EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, - IntRect(0, 0, imageSize.width, aRect.y), - 0)); - - // Check that the area to the left of the output rect is all 0's. (Region 'B'.) - EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, - IntRect(0, aRect.y, aRect.x, aRect.YMost()), - 0)); - - // Check that the area to the right of the output rect is all 0's. (Region 'D'.) - const int32_t widthOnRight = imageSize.width - aRect.XMost(); - EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, - IntRect(aRect.XMost(), aRect.y, widthOnRight, aRect.YMost()), - 0)); - - // Check that the area below the output rect is transparent. (Region 'E'.) - const int32_t heightBelow = imageSize.height - aRect.YMost(); - EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, - IntRect(0, aRect.YMost(), imageSize.width, heightBelow), - 0)); -} - -void -CheckWritePixels(Decoder* aDecoder, - SurfaceFilter* aFilter, - Maybe aOutputRect /* = Nothing() */, - Maybe aInputRect /* = Nothing() */, - Maybe aInputWriteRect /* = Nothing() */, - Maybe aOutputWriteRect /* = Nothing() */, - uint8_t aFuzz /* = 0 */) -{ - IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100)); - IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100)); - IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect); - IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect); - - // Fill the image. - int32_t count = 0; - auto result = aFilter->WritePixels([&] { - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count); - - AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect); - - // Attempt to write more data and make sure nothing changes. - const int32_t oldCount = count; - result = aFilter->WritePixels([&] { - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(oldCount, count); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Attempt to advance to the next row and make sure nothing changes. - aFilter->AdvanceRow(); - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the generated image is correct. - CheckGeneratedImage(aDecoder, outputWriteRect, aFuzz); -} - -void -CheckPalettedWritePixels(Decoder* aDecoder, - SurfaceFilter* aFilter, - Maybe aOutputRect /* = Nothing() */, - Maybe aInputRect /* = Nothing() */, - Maybe aInputWriteRect /* = Nothing() */, - Maybe aOutputWriteRect /* = Nothing() */, - uint8_t aFuzz /* = 0 */) -{ - IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100)); - IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100)); - IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect); - IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect); - - // Fill the image. - int32_t count = 0; - auto result = aFilter->WritePixels([&] { - ++count; - return AsVariant(uint8_t(255)); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count); - - AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect); - - // Attempt to write more data and make sure nothing changes. - const int32_t oldCount = count; - result = aFilter->WritePixels([&] { - ++count; - return AsVariant(uint8_t(255)); - }); - EXPECT_EQ(oldCount, count); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Attempt to advance to the next row and make sure nothing changes. - aFilter->AdvanceRow(); - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - uint8_t* imageData; - uint32_t imageLength; - currentFrame->GetImageData(&imageData, &imageLength); - ASSERT_TRUE(imageData != nullptr); - ASSERT_EQ(outputWriteRect.width * outputWriteRect.height, int32_t(imageLength)); - for (uint32_t i = 0; i < imageLength; ++i) { - ASSERT_EQ(uint8_t(255), imageData[i]); - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// Test Data -/////////////////////////////////////////////////////////////////////////////// - -ImageTestCase GreenPNGTestCase() -{ - return ImageTestCase("green.png", "image/png", IntSize(100, 100)); -} - -ImageTestCase GreenGIFTestCase() -{ - return ImageTestCase("green.gif", "image/gif", IntSize(100, 100)); -} - -ImageTestCase GreenJPGTestCase() -{ - return ImageTestCase("green.jpg", "image/jpeg", IntSize(100, 100), - TEST_CASE_IS_FUZZY); -} - -ImageTestCase GreenBMPTestCase() -{ - return ImageTestCase("green.bmp", "image/bmp", IntSize(100, 100)); -} - -ImageTestCase GreenICOTestCase() -{ - // This ICO contains a 32-bit BMP, and we use a BMP's alpha data by default - // when the BMP is embedded in an ICO, so it's transparent. - return ImageTestCase("green.ico", "image/x-icon", IntSize(100, 100), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase GreenIconTestCase() -{ - return ImageTestCase("green.icon", "image/icon", IntSize(100, 100), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase GreenFirstFrameAnimatedGIFTestCase() -{ - return ImageTestCase("first-frame-green.gif", "image/gif", IntSize(100, 100), - TEST_CASE_IS_ANIMATED); -} - -ImageTestCase GreenFirstFrameAnimatedPNGTestCase() -{ - return ImageTestCase("first-frame-green.png", "image/png", IntSize(100, 100), - TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED); -} - -ImageTestCase CorruptTestCase() -{ - return ImageTestCase("corrupt.jpg", "image/jpeg", IntSize(100, 100), - TEST_CASE_HAS_ERROR); -} - -ImageTestCase CorruptBMPWithTruncatedHeader() -{ - // This BMP has a header which is truncated right between the BIH and the - // bitfields, which is a particularly error-prone place w.r.t. the BMP decoder - // state machine. - return ImageTestCase("invalid-truncated-metadata.bmp", "image/bmp", - IntSize(100, 100), TEST_CASE_HAS_ERROR); -} - -ImageTestCase CorruptICOWithBadBMPWidthTestCase() -{ - // This ICO contains a BMP icon which has a width that doesn't match the size - // listed in the corresponding ICO directory entry. - return ImageTestCase("corrupt-with-bad-bmp-width.ico", "image/x-icon", - IntSize(100, 100), TEST_CASE_HAS_ERROR); -} - -ImageTestCase CorruptICOWithBadBMPHeightTestCase() -{ - // This ICO contains a BMP icon which has a height that doesn't match the size - // listed in the corresponding ICO directory entry. - return ImageTestCase("corrupt-with-bad-bmp-height.ico", "image/x-icon", - IntSize(100, 100), TEST_CASE_HAS_ERROR); -} - -ImageTestCase TransparentPNGTestCase() -{ - return ImageTestCase("transparent.png", "image/png", IntSize(32, 32), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase TransparentGIFTestCase() -{ - return ImageTestCase("transparent.gif", "image/gif", IntSize(16, 16), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase FirstFramePaddingGIFTestCase() -{ - return ImageTestCase("transparent.gif", "image/gif", IntSize(16, 16), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase TransparentIfWithinICOBMPTestCase(TestCaseFlags aFlags) -{ - // This is a BMP that is only transparent when decoded as if it is within an - // ICO file. (Note: aFlags needs to be set to TEST_CASE_DEFAULT_FLAGS or - // TEST_CASE_IS_TRANSPARENT accordingly.) - return ImageTestCase("transparent-if-within-ico.bmp", "image/bmp", - IntSize(32, 32), aFlags); -} - -ImageTestCase RLE4BMPTestCase() -{ - return ImageTestCase("rle4.bmp", "image/bmp", IntSize(320, 240), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase RLE8BMPTestCase() -{ - return ImageTestCase("rle8.bmp", "image/bmp", IntSize(32, 32), - TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase NoFrameDelayGIFTestCase() -{ - // This is an invalid (or at least, questionably valid) GIF that's animated - // even though it specifies a frame delay of zero. It's animated, but it's not - // marked TEST_CASE_IS_ANIMATED because the metadata decoder can't detect that - // it's animated. - return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100)); -} - -ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase() -{ - // This is a corrupt GIF that has extra image sub blocks between the first and - // second frame. - return ImageTestCase("animated-with-extra-image-sub-blocks.gif", "image/gif", - IntSize(100, 100)); -} - -ImageTestCase DownscaledPNGTestCase() -{ - // This testcase (and all the other "downscaled") testcases) consists of 25 - // lines of green, followed by 25 lines of red, followed by 25 lines of green, - // followed by 25 more lines of red. It's intended that tests downscale it - // from 100x100 to 20x20, so we specify a 20x20 output size. - return ImageTestCase("downscaled.png", "image/png", IntSize(100, 100), - IntSize(20, 20)); -} - -ImageTestCase DownscaledGIFTestCase() -{ - return ImageTestCase("downscaled.gif", "image/gif", IntSize(100, 100), - IntSize(20, 20)); -} - -ImageTestCase DownscaledJPGTestCase() -{ - return ImageTestCase("downscaled.jpg", "image/jpeg", IntSize(100, 100), - IntSize(20, 20)); -} - -ImageTestCase DownscaledBMPTestCase() -{ - return ImageTestCase("downscaled.bmp", "image/bmp", IntSize(100, 100), - IntSize(20, 20)); -} - -ImageTestCase DownscaledICOTestCase() -{ - return ImageTestCase("downscaled.ico", "image/x-icon", IntSize(100, 100), - IntSize(20, 20), TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase DownscaledIconTestCase() -{ - return ImageTestCase("downscaled.icon", "image/icon", IntSize(100, 100), - IntSize(20, 20), TEST_CASE_IS_TRANSPARENT); -} - -ImageTestCase DownscaledTransparentICOWithANDMaskTestCase() -{ - // This test case is an ICO with AND mask transparency. We want to ensure that - // we can downscale it without crashing or triggering ASAN failures, but its - // content isn't simple to verify, so for now we don't check the output. - return ImageTestCase("transparent-ico-with-and-mask.ico", "image/x-icon", - IntSize(32, 32), IntSize(20, 20), - TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT); -} - -ImageTestCase TruncatedSmallGIFTestCase() -{ - return ImageTestCase("green-1x1-truncated.gif", "image/gif", IntSize(1, 1)); -} - -} // namespace image -} // namespace mozilla diff --git a/image/test/gtest/Common.h b/image/test/gtest/Common.h deleted file mode 100644 index 0c288cddcb..0000000000 --- a/image/test/gtest/Common.h +++ /dev/null @@ -1,419 +0,0 @@ -/* -*- 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_image_test_gtest_Common_h -#define mozilla_image_test_gtest_Common_h - -#include - -#include "gtest/gtest.h" - -#include "mozilla/Maybe.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/gfx/2D.h" -#include "Decoder.h" -#include "gfxColor.h" -#include "imgITools.h" -#include "nsCOMPtr.h" -#include "SurfacePipe.h" -#include "SurfacePipeFactory.h" - -class nsIInputStream; - -namespace mozilla { -namespace image { - -/////////////////////////////////////////////////////////////////////////////// -// Types -/////////////////////////////////////////////////////////////////////////////// - -enum TestCaseFlags -{ - TEST_CASE_DEFAULT_FLAGS = 0, - TEST_CASE_IS_FUZZY = 1 << 0, - TEST_CASE_HAS_ERROR = 1 << 1, - TEST_CASE_IS_TRANSPARENT = 1 << 2, - TEST_CASE_IS_ANIMATED = 1 << 3, - TEST_CASE_IGNORE_OUTPUT = 1 << 4, -}; - -struct ImageTestCase -{ - ImageTestCase(const char* aPath, - const char* aMimeType, - gfx::IntSize aSize, - uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS) - : mPath(aPath) - , mMimeType(aMimeType) - , mSize(aSize) - , mOutputSize(aSize) - , mFlags(aFlags) - { } - - ImageTestCase(const char* aPath, - const char* aMimeType, - gfx::IntSize aSize, - gfx::IntSize aOutputSize, - uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS) - : mPath(aPath) - , mMimeType(aMimeType) - , mSize(aSize) - , mOutputSize(aOutputSize) - , mFlags(aFlags) - { } - - const char* mPath; - const char* mMimeType; - gfx::IntSize mSize; - gfx::IntSize mOutputSize; - uint32_t mFlags; -}; - -struct BGRAColor -{ - BGRAColor() : BGRAColor(0, 0, 0, 0) { } - - BGRAColor(uint8_t aBlue, uint8_t aGreen, uint8_t aRed, uint8_t aAlpha) - : mBlue(aBlue) - , mGreen(aGreen) - , mRed(aRed) - , mAlpha(aAlpha) - { } - - static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); } - static BGRAColor Red() { return BGRAColor(0x00, 0x00, 0xFF, 0xFF); } - static BGRAColor Blue() { return BGRAColor(0xFF, 0x00, 0x00, 0xFF); } - static BGRAColor Transparent() { return BGRAColor(0x00, 0x00, 0x00, 0x00); } - - uint32_t AsPixel() const { return gfxPackedPixel(mAlpha, mRed, mGreen, mBlue); } - - uint8_t mBlue; - uint8_t mGreen; - uint8_t mRed; - uint8_t mAlpha; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// General Helpers -/////////////////////////////////////////////////////////////////////////////// - -/** - * A RAII class that ensure that ImageLib services are available. Any tests that - * require ImageLib to be initialized (for example, any test that uses the - * SurfaceCache; see image::EnsureModuleInitialized() for the full list) can - * use this class to ensure that ImageLib services are available. Failure to do - * so can result in strange, non-deterministic failures. - */ -struct AutoInitializeImageLib -{ - AutoInitializeImageLib() - { - // Ensure that ImageLib services are initialized. - nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); - EXPECT_TRUE(imgTools != nullptr); - } -}; - -/// Loads a file from the current directory. @return an nsIInputStream for it. -already_AddRefed LoadFile(const char* aRelativePath); - -/** - * @returns true if every pixel of @aSurface is @aColor. - * - * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color - * component. This may be necessary for tests that involve JPEG images or - * downscaling. - */ -bool IsSolidColor(gfx::SourceSurface* aSurface, - BGRAColor aColor, - uint8_t aFuzz = 0); - -/** - * @returns true if every pixel of @aDecoder's surface has the palette index - * specified by @aColor. - */ -bool IsSolidPalettedColor(Decoder* aDecoder, uint8_t aColor); - -/** - * @returns true if every pixel in the range of rows specified by @aStartRow and - * @aRowCount of @aSurface is @aColor. - * - * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color - * component. This may be necessary for tests that involve JPEG images or - * downscaling. - */ -bool RowsAreSolidColor(gfx::SourceSurface* aSurface, - int32_t aStartRow, - int32_t aRowCount, - BGRAColor aColor, - uint8_t aFuzz = 0); - -/** - * @returns true if every pixel in the range of rows specified by @aStartRow and - * @aRowCount of @aDecoder's surface has the palette index specified by @aColor. - */ -bool PalettedRowsAreSolidColor(Decoder* aDecoder, - int32_t aStartRow, - int32_t aRowCount, - uint8_t aColor); - -/** - * @returns true if every pixel in the rect specified by @aRect is @aColor. - * - * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color - * component. This may be necessary for tests that involve JPEG images or - * downscaling. - */ -bool RectIsSolidColor(gfx::SourceSurface* aSurface, - const gfx::IntRect& aRect, - BGRAColor aColor, - uint8_t aFuzz = 0); - -/** - * @returns true if every pixel in the rect specified by @aRect has the palette - * index specified by @aColor. - */ -bool PalettedRectIsSolidColor(Decoder* aDecoder, - const gfx::IntRect& aRect, - uint8_t aColor); - -/** - * @returns true if the pixels in @aRow of @aSurface match the pixels given in - * @aPixels. - */ -bool RowHasPixels(gfx::SourceSurface* aSurface, - int32_t aRow, - const std::vector& aPixels); - -// ExpectNoResume is an IResumable implementation for use by tests that expect -// Resume() to never get called. -class ExpectNoResume final : public IResumable -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ExpectNoResume, override) - - void Resume() override { FAIL() << "Resume() should not get called"; } - -private: - ~ExpectNoResume() override { } -}; - -// CountResumes is an IResumable implementation for use by tests that expect -// Resume() to get called a certain number of times. -class CountResumes : public IResumable -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CountResumes, override) - - CountResumes() : mCount(0) { } - - void Resume() override { mCount++; } - uint32_t Count() const { return mCount; } - -private: - ~CountResumes() override { } - - uint32_t mCount; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// SurfacePipe Helpers -/////////////////////////////////////////////////////////////////////////////// - -/** - * Creates a decoder with no data associated with, suitable for testing code - * that requires a decoder to initialize or to allocate surfaces but doesn't - * actually need the decoder to do any decoding. - * - * XXX(seth): We only need this because SurfaceSink and PalettedSurfaceSink - * defer to the decoder for surface allocation. Once all decoders use - * SurfacePipe we won't need to do that anymore and we can remove this function. - */ -already_AddRefed CreateTrivialDecoder(); - -/** - * Creates a pipeline of SurfaceFilters from a list of Config structs and passes - * it to the provided lambda @aFunc. Assertions that the pipeline is constructly - * correctly and cleanup of any allocated surfaces is handled automatically. - * - * @param aDecoder The decoder to use for allocating surfaces. - * @param aFunc The lambda function to pass the filter pipeline to. - * @param aConfigs The configuration for the pipeline. - */ -template -void WithFilterPipeline(Decoder* aDecoder, Func aFunc, const Configs&... aConfigs) -{ - auto pipe = MakeUnique::Type>(); - nsresult rv = pipe->Configure(aConfigs...); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - aFunc(aDecoder, pipe.get()); - - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - if (currentFrame) { - currentFrame->Finish(); - } -} - -/** - * Creates a pipeline of SurfaceFilters from a list of Config structs and - * asserts that configuring it fails. Cleanup of any allocated surfaces is - * handled automatically. - * - * @param aDecoder The decoder to use for allocating surfaces. - * @param aConfigs The configuration for the pipeline. - */ -template -void AssertConfiguringPipelineFails(Decoder* aDecoder, const Configs&... aConfigs) -{ - auto pipe = MakeUnique::Type>(); - nsresult rv = pipe->Configure(aConfigs...); - - // Callers expect configuring the pipeline to fail. - ASSERT_TRUE(NS_FAILED(rv)); - - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - if (currentFrame) { - currentFrame->Finish(); - } -} - -/** - * Asserts that the provided filter pipeline is in the correct final state, - * which is to say, the entire surface has been written to (IsSurfaceFinished() - * returns true) and the invalid rects are as expected. - * - * @param aFilter The filter pipeline to check. - * @param aInputSpaceRect The expect invalid rect, in input space. - * @param aoutputSpaceRect The expect invalid rect, in output space. - */ -void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter, - const gfx::IntRect& aInputSpaceRect, - const gfx::IntRect& aOutputSpaceRect); - -/** - * Checks a generated image for correctness. Reports any unexpected deviation - * from the expected image as GTest failures. - * - * @param aDecoder The decoder which contains the image. The decoder's current - * frame will be checked. - * @param aRect The region in the space of the output surface that the filter - * pipeline will actually write to. It's expected that pixels in - * this region are green, while pixels outside this region are - * transparent. - * @param aFuzz The amount of fuzz to use in pixel comparisons. - */ -void CheckGeneratedImage(Decoder* aDecoder, - const gfx::IntRect& aRect, - uint8_t aFuzz = 0); - -/** - * Checks a generated paletted image for correctness. Reports any unexpected - * deviation from the expected image as GTest failures. - * - * @param aDecoder The decoder which contains the image. The decoder's current - * frame will be checked. - * @param aRect The region in the space of the output surface that the filter - * pipeline will actually write to. It's expected that pixels in - * this region have a palette index of 255, while pixels outside - * this region have a palette index of 0. - */ -void CheckGeneratedPalettedImage(Decoder* aDecoder, const gfx::IntRect& aRect); - -/** - * Tests the result of calling WritePixels() using the provided SurfaceFilter - * pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline. - * - * The arguments are specified in the an order intended to minimize the number - * of arguments that most test cases need to pass. - * - * @param aDecoder The decoder whose current frame will be written to. - * @param aFilter The SurfaceFilter pipeline to use. - * @param aOutputRect The region in the space of the output surface that will be - * invalidated by the filter pipeline. Defaults to - * (0, 0, 100, 100). - * @param aInputRect The region in the space of the input image that will be - * invalidated by the filter pipeline. Defaults to - * (0, 0, 100, 100). - * @param aInputWriteRect The region in the space of the input image that the - * filter pipeline will allow writes to. Note the - * difference from @aInputRect: @aInputRect is the actual - * region invalidated, while @aInputWriteRect is the - * region that is written to. These can differ in cases - * where the input is not clipped to the size of the image. - * Defaults to the entire input rect. - * @param aOutputWriteRect The region in the space of the output surface that - * the filter pipeline will actually write to. It's - * expected that pixels in this region are green, while - * pixels outside this region are transparent. Defaults - * to the entire output rect. - */ -void CheckWritePixels(Decoder* aDecoder, - SurfaceFilter* aFilter, - Maybe aOutputRect = Nothing(), - Maybe aInputRect = Nothing(), - Maybe aInputWriteRect = Nothing(), - Maybe aOutputWriteRect = Nothing(), - uint8_t aFuzz = 0); - -/** - * Tests the result of calling WritePixels() using the provided SurfaceFilter - * pipeline. The pipeline must be a paletted pipeline. - * @see CheckWritePixels() for documentation of the arguments. - */ -void CheckPalettedWritePixels(Decoder* aDecoder, - SurfaceFilter* aFilter, - Maybe aOutputRect = Nothing(), - Maybe aInputRect = Nothing(), - Maybe aInputWriteRect = Nothing(), - Maybe aOutputWriteRect = Nothing(), - uint8_t aFuzz = 0); - - -/////////////////////////////////////////////////////////////////////////////// -// Test Data -/////////////////////////////////////////////////////////////////////////////// - -ImageTestCase GreenPNGTestCase(); -ImageTestCase GreenGIFTestCase(); -ImageTestCase GreenJPGTestCase(); -ImageTestCase GreenBMPTestCase(); -ImageTestCase GreenICOTestCase(); -ImageTestCase GreenIconTestCase(); - -ImageTestCase GreenFirstFrameAnimatedGIFTestCase(); -ImageTestCase GreenFirstFrameAnimatedPNGTestCase(); - -ImageTestCase CorruptTestCase(); -ImageTestCase CorruptBMPWithTruncatedHeader(); -ImageTestCase CorruptICOWithBadBMPWidthTestCase(); -ImageTestCase CorruptICOWithBadBMPHeightTestCase(); - -ImageTestCase TransparentPNGTestCase(); -ImageTestCase TransparentGIFTestCase(); -ImageTestCase FirstFramePaddingGIFTestCase(); -ImageTestCase NoFrameDelayGIFTestCase(); -ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase(); - -ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase(); -ImageTestCase RLE4BMPTestCase(); -ImageTestCase RLE8BMPTestCase(); - -ImageTestCase DownscaledPNGTestCase(); -ImageTestCase DownscaledGIFTestCase(); -ImageTestCase DownscaledJPGTestCase(); -ImageTestCase DownscaledBMPTestCase(); -ImageTestCase DownscaledICOTestCase(); -ImageTestCase DownscaledIconTestCase(); -ImageTestCase DownscaledTransparentICOWithANDMaskTestCase(); - -ImageTestCase TruncatedSmallGIFTestCase(); - -} // namespace image -} // namespace mozilla - -#endif // mozilla_image_test_gtest_Common_h diff --git a/image/test/gtest/TestADAM7InterpolatingFilter.cpp b/image/test/gtest/TestADAM7InterpolatingFilter.cpp deleted file mode 100644 index d11224251e..0000000000 --- a/image/test/gtest/TestADAM7InterpolatingFilter.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "mozilla/Maybe.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfaceFilters.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -using std::generate; -using std::vector; - -template void -WithADAM7InterpolatingFilter(const IntSize& aSize, Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(bool(decoder)); - - WithFilterPipeline(decoder, Forward(aFunc), - ADAM7InterpolatingConfig { }, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -void -AssertConfiguringADAM7InterpolatingFilterFails(const IntSize& aSize) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(bool(decoder)); - - AssertConfiguringPipelineFails(decoder, - ADAM7InterpolatingConfig { }, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -uint8_t -InterpolateByte(uint8_t aByteA, uint8_t aByteB, float aWeight) -{ - return uint8_t(aByteA * aWeight + aByteB * (1.0f - aWeight)); -} - -BGRAColor -InterpolateColors(BGRAColor aColor1, BGRAColor aColor2, float aWeight) -{ - return BGRAColor(InterpolateByte(aColor1.mBlue, aColor2.mBlue, aWeight), - InterpolateByte(aColor1.mGreen, aColor2.mGreen, aWeight), - InterpolateByte(aColor1.mRed, aColor2.mRed, aWeight), - InterpolateByte(aColor1.mAlpha, aColor2.mAlpha, aWeight)); -} - -enum class ShouldInterpolate -{ - eYes, - eNo -}; - -BGRAColor -HorizontallyInterpolatedPixel(uint32_t aCol, - uint32_t aWidth, - const vector& aWeights, - ShouldInterpolate aShouldInterpolate, - const vector& aColors) -{ - // We cycle through the vector of weights forever. - float weight = aWeights[aCol % aWeights.size()]; - - // Find the columns of the two final pixels for this set of weights. - uint32_t finalPixel1 = aCol - aCol % aWeights.size(); - uint32_t finalPixel2 = finalPixel1 + aWeights.size(); - - // If |finalPixel2| is past the end of the row, that means that there is no - // final pixel after the pixel at |finalPixel1|. In that case, we just want to - // duplicate |finalPixel1|'s color until the end of the row. We can do that by - // setting |finalPixel2| equal to |finalPixel1| so that the interpolation has - // no effect. - if (finalPixel2 >= aWidth) { - finalPixel2 = finalPixel1; - } - - // We cycle through the vector of colors forever (subject to the above - // constraint about the end of the row). - BGRAColor color1 = aColors[finalPixel1 % aColors.size()]; - BGRAColor color2 = aColors[finalPixel2 % aColors.size()]; - - // If we're not interpolating, we treat all pixels which aren't final as - // transparent. Since the number of weights we have is equal to the stride - // between final pixels, we can check if |aCol| is a final pixel by checking - // whether |aCol| is a multiple of |aWeights.size()|. - if (aShouldInterpolate == ShouldInterpolate::eNo) { - return aCol % aWeights.size() == 0 ? color1 - : BGRAColor::Transparent(); - } - - // Interpolate. - return InterpolateColors(color1, color2, weight); -} - -vector& -InterpolationWeights(int32_t aStride) -{ - // Precalculated interpolation weights. These are used to interpolate - // between final pixels or between important rows. Although no interpolation - // is actually applied to the previous final pixel or important row value, - // the arrays still start with 1.0f, which is always skipped, primarily - // because otherwise |stride1Weights| would have zero elements. - static vector stride8Weights = - { 1.0f, 7 / 8.0f, 6 / 8.0f, 5 / 8.0f, 4 / 8.0f, 3 / 8.0f, 2 / 8.0f, 1 / 8.0f }; - static vector stride4Weights = { 1.0f, 3 / 4.0f, 2 / 4.0f, 1 / 4.0f }; - static vector stride2Weights = { 1.0f, 1 / 2.0f }; - static vector stride1Weights = { 1.0f }; - - switch (aStride) { - case 8: return stride8Weights; - case 4: return stride4Weights; - case 2: return stride2Weights; - case 1: return stride1Weights; - default: - MOZ_CRASH(); - } -} - -int32_t -ImportantRowStride(uint8_t aPass) -{ - // The stride between important rows for each pass, with a dummy value for - // the nonexistent pass 0 and for pass 8, since the tests run an extra pass to - // make sure nothing breaks. - static int32_t strides[] = { 1, 8, 8, 4, 4, 2, 2, 1, 1 }; - - return strides[aPass]; -} - -size_t -FinalPixelStride(uint8_t aPass) -{ - // The stride between the final pixels in important rows for each pass, with - // a dummy value for the nonexistent pass 0 and for pass 8, since the tests - // run an extra pass to make sure nothing breaks. - static size_t strides[] = { 1, 8, 4, 4, 2, 2, 1, 1, 1 }; - - return strides[aPass]; -} - -bool -IsImportantRow(int32_t aRow, uint8_t aPass) -{ - return aRow % ImportantRowStride(aPass) == 0; -} - -/** - * ADAM7 breaks up the image into 8x8 blocks. On each of the 7 passes, a new - * set of pixels in each block receives their final values, according to the - * following pattern: - * - * 1 6 4 6 2 6 4 6 - * 7 7 7 7 7 7 7 7 - * 5 6 5 6 5 6 5 6 - * 7 7 7 7 7 7 7 7 - * 3 6 4 6 3 6 4 6 - * 7 7 7 7 7 7 7 7 - * 5 6 5 6 5 6 5 6 - * 7 7 7 7 7 7 7 7 - * - * This function produces a row of pixels @aWidth wide, suitable for testing - * horizontal interpolation on pass @aPass. The pattern of pixels used is - * determined by @aPass and @aRow, which determine which pixels are final - * according to the table above, and @aColors, from which the pixel values - * are selected. - * - * There are two different behaviors: if |eNo| is passed for - * @aShouldInterpolate, non-final pixels are treated as transparent. If |eNo| - * is passed, non-final pixels get interpolated in from the surrounding final - * pixels. The intention is that |eNo| is passed to generate input which will - * be run through ADAM7InterpolatingFilter, and |eYes| is passed to generate - * reference data to check that the filter is performing horizontal - * interpolation correctly. - * - * This function does not perform vertical interpolation. Rows which aren't on - * the current pass are filled with transparent pixels. - * - * @return a vector representing a row of pixels. - */ -vector -ADAM7HorizontallyInterpolatedRow(uint8_t aPass, - uint32_t aRow, - uint32_t aWidth, - ShouldInterpolate aShouldInterpolate, - const vector& aColors) -{ - EXPECT_GT(aPass, 0); - EXPECT_LE(aPass, 8); - EXPECT_GT(aColors.size(), 0u); - - vector result(aWidth); - - if (IsImportantRow(aRow, aPass)) { - vector& weights = InterpolationWeights(FinalPixelStride(aPass)); - - // Compute the horizontally interpolated row. - uint32_t col = 0; - generate(result.begin(), result.end(), [&]{ - return HorizontallyInterpolatedPixel(col++, aWidth, weights, - aShouldInterpolate, aColors); - }); - } else { - // This is an unimportant row; just make the entire thing transparent. - generate(result.begin(), result.end(), []{ - return BGRAColor::Transparent(); - }); - } - - EXPECT_EQ(result.size(), size_t(aWidth)); - - return result; -} - -WriteState -WriteUninterpolatedPixels(SurfaceFilter* aFilter, - const IntSize& aSize, - uint8_t aPass, - const vector& aColors) -{ - WriteState result = WriteState::NEED_MORE_DATA; - - for (int32_t row = 0; row < aSize.height; ++row) { - // Compute uninterpolated pixels for this row. - vector pixels = - Move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width, - ShouldInterpolate::eNo, aColors)); - - // Write them to the surface. - auto pixelIterator = pixels.cbegin(); - result = aFilter->WritePixelsToRow([&]{ - return AsVariant((*pixelIterator++).AsPixel()); - }); - - if (result != WriteState::NEED_MORE_DATA) { - break; - } - } - - return result; -} - -bool -CheckHorizontallyInterpolatedImage(Decoder* aDecoder, - const IntSize& aSize, - uint8_t aPass, - const vector& aColors) -{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (int32_t row = 0; row < aSize.height; ++row) { - if (!IsImportantRow(row, aPass)) { - continue; // Don't check rows which aren't important on this pass. - } - - // Compute the expected pixels, *with* interpolation to match what the - // filter should have done. - vector expectedPixels = - Move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width, - ShouldInterpolate::eYes, aColors)); - - if (!RowHasPixels(surface, row, expectedPixels)) { - return false; - } - } - - return true; -} - -void -CheckHorizontalInterpolation(const IntSize& aSize, - const vector& aColors) -{ - const IntRect surfaceRect(IntPoint(0, 0), aSize); - - WithADAM7InterpolatingFilter(aSize, - [&](Decoder* aDecoder, SurfaceFilter* aFilter) { - // We check horizontal interpolation behavior for each pass individually. In - // addition to the normal 7 passes that ADAM7 includes, we also check an - // eighth pass to verify that nothing breaks if extra data is written. - for (uint8_t pass = 1; pass <= 8; ++pass) { - // Write our color pattern to the surface. We don't perform any - // interpolation when writing to the filter so that we can check that the - // filter itself *does*. - WriteState result = - WriteUninterpolatedPixels(aFilter, aSize, pass, aColors); - - EXPECT_EQ(WriteState::FINISHED, result); - AssertCorrectPipelineFinalState(aFilter, surfaceRect, surfaceRect); - - // Check that the generated image matches the expected pattern, with - // interpolation applied. - EXPECT_TRUE(CheckHorizontallyInterpolatedImage(aDecoder, aSize, - pass, aColors)); - - // Prepare for the next pass. - aFilter->ResetToFirstRow(); - } - }); -} - -BGRAColor -ADAM7RowColor(int32_t aRow, - uint8_t aPass, - const vector& aColors) -{ - EXPECT_LT(0, aPass); - EXPECT_GE(8, aPass); - EXPECT_LT(0u, aColors.size()); - - // If this is an important row, select the color from the provided vector of - // colors, which we cycle through infinitely. If not, just fill the row with - // transparent pixels. - return IsImportantRow(aRow, aPass) ? aColors[aRow % aColors.size()] - : BGRAColor::Transparent(); -} - -WriteState -WriteRowColorPixels(SurfaceFilter* aFilter, - const IntSize& aSize, - uint8_t aPass, - const vector& aColors) -{ - WriteState result = WriteState::NEED_MORE_DATA; - - for (int32_t row = 0; row < aSize.height; ++row) { - const uint32_t color = ADAM7RowColor(row, aPass, aColors).AsPixel(); - - // Fill the surface with |color| pixels. - result = aFilter->WritePixelsToRow([&]{ return AsVariant(color); }); - - if (result != WriteState::NEED_MORE_DATA) { - break; - } - } - - return result; -} - -bool -CheckVerticallyInterpolatedImage(Decoder* aDecoder, - const IntSize& aSize, - uint8_t aPass, - const vector& aColors) -{ - vector& weights = InterpolationWeights(ImportantRowStride(aPass)); - - for (int32_t row = 0; row < aSize.height; ++row) { - // Vertically interpolation takes place between two important rows. The - // separation between the important rows is determined by the stride of this - // pass. When there is no "next" important row because we'd run off the - // bottom of the image, we use the same row for both. This matches - // ADAM7InterpolatingFilter's behavior of duplicating the last important row - // since there isn't another important row to vertically interpolate it - // with. - const int32_t stride = ImportantRowStride(aPass); - const int32_t prevImportantRow = row - row % stride; - const int32_t maybeNextImportantRow = prevImportantRow + stride; - const int32_t nextImportantRow = maybeNextImportantRow < aSize.height - ? maybeNextImportantRow - : prevImportantRow; - - // Retrieve the colors for the important rows we're going to interpolate. - const BGRAColor prevImportantRowColor = - ADAM7RowColor(prevImportantRow, aPass, aColors); - const BGRAColor nextImportantRowColor = - ADAM7RowColor(nextImportantRow, aPass, aColors); - - // The weight we'll use for interpolation is also determined by the stride. - // A row halfway between two important rows should have pixels that have a - // 50% contribution from each of the important rows, for example. - const float weight = weights[row % stride]; - const BGRAColor interpolatedColor = - InterpolateColors(prevImportantRowColor, nextImportantRowColor, weight); - - // Generate a row of expected pixels. Every pixel in the row is always the - // same color since we're only testing vertical interpolation between - // solid-colored rows. - vector expectedPixels(aSize.width); - generate(expectedPixels.begin(), expectedPixels.end(), [&]{ - return interpolatedColor; - }); - - // Check that the pixels match. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - if (!RowHasPixels(surface, row, expectedPixels)) { - return false; - } - } - - return true; -} - -void -CheckVerticalInterpolation(const IntSize& aSize, - const vector& aColors) -{ - const IntRect surfaceRect(IntPoint(0, 0), aSize); - - WithADAM7InterpolatingFilter(aSize, - [&](Decoder* aDecoder, SurfaceFilter* aFilter) { - for (uint8_t pass = 1; pass <= 8; ++pass) { - // Write a pattern of rows to the surface. Important rows will receive a - // color selected from |aColors|; unimportant rows will be transparent. - WriteState result = WriteRowColorPixels(aFilter, aSize, pass, aColors); - - EXPECT_EQ(WriteState::FINISHED, result); - AssertCorrectPipelineFinalState(aFilter, surfaceRect, surfaceRect); - - // Check that the generated image matches the expected pattern, with - // interpolation applied. - EXPECT_TRUE(CheckVerticallyInterpolatedImage(aDecoder, aSize, - pass, aColors)); - - // Prepare for the next pass. - aFilter->ResetToFirstRow(); - } - }); -} - -void -CheckInterpolation(const IntSize& aSize, const vector& aColors) -{ - CheckHorizontalInterpolation(aSize, aColors); - CheckVerticalInterpolation(aSize, aColors); -} - -void -CheckADAM7InterpolatingWritePixels(const IntSize& aSize) -{ - // This test writes 8 passes of green pixels (the seven ADAM7 passes, plus one - // extra to make sure nothing goes wrong if we write too much input) and verifies - // that the output is a solid green surface each time. Because all the pixels - // are the same color, interpolation doesn't matter; we test the correctness - // of the interpolation algorithm itself separately. - WithADAM7InterpolatingFilter(aSize, - [&](Decoder* aDecoder, SurfaceFilter* aFilter) { - IntRect rect(IntPoint(0, 0), aSize); - - for (int32_t pass = 1; pass <= 8; ++pass) { - // We only actually write up to the last important row for each pass, - // because that row unambiguously determines the remaining rows. - const int32_t lastRow = aSize.height - 1; - const int32_t lastImportantRow = - lastRow - (lastRow % ImportantRowStride(pass)); - const IntRect inputWriteRect(0, 0, aSize.width, lastImportantRow + 1); - - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(rect), - /* aInputRect = */ Some(rect), - /* aInputWriteRect = */ Some(inputWriteRect)); - - aFilter->ResetToFirstRow(); - EXPECT_FALSE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - } - }); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels100_100) -{ - CheckADAM7InterpolatingWritePixels(IntSize(100, 100)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels99_99) -{ - CheckADAM7InterpolatingWritePixels(IntSize(99, 99)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels66_33) -{ - CheckADAM7InterpolatingWritePixels(IntSize(66, 33)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels33_66) -{ - CheckADAM7InterpolatingWritePixels(IntSize(33, 66)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels15_15) -{ - CheckADAM7InterpolatingWritePixels(IntSize(15, 15)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels9_9) -{ - CheckADAM7InterpolatingWritePixels(IntSize(9, 9)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels8_8) -{ - CheckADAM7InterpolatingWritePixels(IntSize(8, 8)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels7_7) -{ - CheckADAM7InterpolatingWritePixels(IntSize(7, 7)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels3_3) -{ - CheckADAM7InterpolatingWritePixels(IntSize(3, 3)); -} - -TEST(ImageADAM7InterpolatingFilter, WritePixels1_1) -{ - CheckADAM7InterpolatingWritePixels(IntSize(1, 1)); -} - -TEST(ImageADAM7InterpolatingFilter, TrivialInterpolation48_48) -{ - CheckInterpolation(IntSize(48, 48), { BGRAColor::Green() }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput33_17) -{ - // We check interpolation using irregular patterns to make sure that the - // interpolation will look different for different passes. - CheckInterpolation(IntSize(33, 17), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), BGRAColor::Blue(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput32_16) -{ - CheckInterpolation(IntSize(32, 16), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), BGRAColor::Blue(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput31_15) -{ - CheckInterpolation(IntSize(31, 15), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), BGRAColor::Blue(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput17_33) -{ - CheckInterpolation(IntSize(17, 33), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput16_32) -{ - CheckInterpolation(IntSize(16, 32), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput15_31) -{ - CheckInterpolation(IntSize(15, 31), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), - BGRAColor::Red(), BGRAColor::Green(), BGRAColor::Blue(), BGRAColor::Red(), - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput9_9) -{ - CheckInterpolation(IntSize(9, 9), { - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput8_8) -{ - CheckInterpolation(IntSize(8, 8), { - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput7_7) -{ - CheckInterpolation(IntSize(7, 7), { - BGRAColor::Blue(), BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(), - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Red(), BGRAColor::Blue() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput3_3) -{ - CheckInterpolation(IntSize(3, 3), { - BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Blue(), BGRAColor::Red() - }); -} - -TEST(ImageADAM7InterpolatingFilter, InterpolationOutput1_1) -{ - CheckInterpolation(IntSize(1, 1), { BGRAColor::Blue() }); -} - -TEST(ImageADAM7InterpolatingFilter, ADAM7InterpolationFailsFor0_0) -{ - // A 0x0 input size is invalid, so configuration should fail. - AssertConfiguringADAM7InterpolatingFilterFails(IntSize(0, 0)); -} - -TEST(ImageADAM7InterpolatingFilter, ADAM7InterpolationFailsForMinus1_Minus1) -{ - // A negative input size is invalid, so configuration should fail. - AssertConfiguringADAM7InterpolatingFilterFails(IntSize(-1, -1)); -} - -TEST(ImageADAM7InterpolatingFilter, ConfiguringPalettedADAM7InterpolatingFilterFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // ADAM7InterpolatingFilter does not support paletted images, so configuration - // should fail. - AssertConfiguringPipelineFails(decoder, - ADAM7InterpolatingConfig { }, - PalettedSurfaceConfig { decoder, IntSize(100, 100), - IntRect(0, 0, 50, 50), - SurfaceFormat::B8G8R8A8, 8, - false }); -} diff --git a/image/test/gtest/TestCopyOnWrite.cpp b/image/test/gtest/TestCopyOnWrite.cpp deleted file mode 100644 index 0d420b6722..0000000000 --- a/image/test/gtest/TestCopyOnWrite.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include "CopyOnWrite.h" - -using namespace mozilla; -using namespace mozilla::image; - -struct ValueStats -{ - int32_t mCopies = 0; - int32_t mFrees = 0; - int32_t mCalls = 0; - int32_t mConstCalls = 0; - int32_t mSerial = 0; -}; - -struct Value -{ - NS_INLINE_DECL_REFCOUNTING(Value) - - explicit Value(ValueStats& aStats) - : mStats(aStats) - , mSerial(mStats.mSerial++) - { } - - Value(const Value& aOther) - : mStats(aOther.mStats) - , mSerial(mStats.mSerial++) - { - mStats.mCopies++; - } - - void Go() { mStats.mCalls++; } - void Go() const { mStats.mConstCalls++; } - - int32_t Serial() const { return mSerial; } - -protected: - ~Value() { mStats.mFrees++; } - -private: - ValueStats& mStats; - int32_t mSerial; -}; - -TEST(ImageCopyOnWrite, Read) -{ - ValueStats stats; - - { - CopyOnWrite cow(new Value(stats)); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_TRUE(cow.CanRead()); - - cow.Read([&](const Value* aValue) { - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, aValue->Serial()); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - aValue->Go(); - - EXPECT_EQ(0, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - }); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - } - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(1, stats.mFrees); -} - -TEST(ImageCopyOnWrite, RecursiveRead) -{ - ValueStats stats; - - { - CopyOnWrite cow(new Value(stats)); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_TRUE(cow.CanRead()); - - cow.Read([&](const Value* aValue) { - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, aValue->Serial()); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - // Make sure that Read() inside a Read() succeeds. - cow.Read([&](const Value* aValue) { - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, aValue->Serial()); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - aValue->Go(); - - EXPECT_EQ(0, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - }, []() { - // This gets called if we can't read. We shouldn't get here. - EXPECT_TRUE(false); - }); - }); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - } - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(1, stats.mFrees); -} - -TEST(ImageCopyOnWrite, Write) -{ - ValueStats stats; - - { - CopyOnWrite cow(new Value(stats)); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - cow.Write([&](Value* aValue) { - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, aValue->Serial()); - EXPECT_TRUE(!cow.CanRead()); - EXPECT_TRUE(!cow.CanWrite()); - - aValue->Go(); - - EXPECT_EQ(1, stats.mCalls); - EXPECT_EQ(0, stats.mConstCalls); - }); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(1, stats.mCalls); - EXPECT_EQ(0, stats.mConstCalls); - } - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(1, stats.mFrees); -} - -TEST(ImageCopyOnWrite, WriteRecursive) -{ - ValueStats stats; - - { - CopyOnWrite cow(new Value(stats)); - - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - cow.Read([&](const Value* aValue) { - EXPECT_EQ(0, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(0, aValue->Serial()); - EXPECT_TRUE(cow.CanRead()); - EXPECT_TRUE(cow.CanWrite()); - - // Make sure Write() inside a Read() succeeds. - cow.Write([&](Value* aValue) { - EXPECT_EQ(1, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(1, aValue->Serial()); - EXPECT_TRUE(!cow.CanRead()); - EXPECT_TRUE(!cow.CanWrite()); - - aValue->Go(); - - EXPECT_EQ(1, stats.mCalls); - EXPECT_EQ(0, stats.mConstCalls); - - // Make sure Read() inside a Write() fails. - cow.Read([](const Value* aValue) { - // This gets called if we can read. We shouldn't get here. - EXPECT_TRUE(false); - }, []() { - // This gets called if we can't read. We *should* get here. - EXPECT_TRUE(true); - }); - - // Make sure Write() inside a Write() fails. - cow.Write([](Value* aValue) { - // This gets called if we can write. We shouldn't get here. - EXPECT_TRUE(false); - }, []() { - // This gets called if we can't write. We *should* get here. - EXPECT_TRUE(true); - }); - }, []() { - // This gets called if we can't write. We shouldn't get here. - EXPECT_TRUE(false); - }); - - aValue->Go(); - - EXPECT_EQ(1, stats.mCopies); - EXPECT_EQ(0, stats.mFrees); - EXPECT_EQ(1, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - }); - - EXPECT_EQ(1, stats.mCopies); - EXPECT_EQ(1, stats.mFrees); - EXPECT_EQ(1, stats.mCalls); - EXPECT_EQ(1, stats.mConstCalls); - } - - EXPECT_EQ(1, stats.mCopies); - EXPECT_EQ(2, stats.mFrees); -} diff --git a/image/test/gtest/TestDecodeToSurface.cpp b/image/test/gtest/TestDecodeToSurface.cpp deleted file mode 100644 index bd52e75901..0000000000 --- a/image/test/gtest/TestDecodeToSurface.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include "Common.h" -#include "imgIContainer.h" -#include "imgITools.h" -#include "ImageOps.h" -#include "mozilla/gfx/2D.h" -#include "nsComponentManagerUtils.h" -#include "nsCOMPtr.h" -#include "nsIInputStream.h" -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "mozilla/RefPtr.h" -#include "nsString.h" -#include "nsThreadUtils.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -class DecodeToSurfaceRunnable : public Runnable -{ -public: - DecodeToSurfaceRunnable(RefPtr& aSurface, - nsIInputStream* aInputStream, - const ImageTestCase& aTestCase) - : mSurface(aSurface) - , mInputStream(aInputStream) - , mTestCase(aTestCase) - { } - - NS_IMETHOD Run() override - { - Go(); - return NS_OK; - } - - void Go() - { - mSurface = - ImageOps::DecodeToSurface(mInputStream, - nsDependentCString(mTestCase.mMimeType), - imgIContainer::DECODE_FLAGS_DEFAULT); - ASSERT_TRUE(mSurface != nullptr); - - EXPECT_EQ(SurfaceType::DATA, mSurface->GetType()); - EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 || - mSurface->GetFormat() == SurfaceFormat::B8G8R8A8); - EXPECT_EQ(mTestCase.mSize, mSurface->GetSize()); - - EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(), - mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0)); - } - -private: - RefPtr& mSurface; - nsCOMPtr mInputStream; - ImageTestCase mTestCase; -}; - -static void -RunDecodeToSurface(const ImageTestCase& aTestCase) -{ - nsCOMPtr inputStream = LoadFile(aTestCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - nsCOMPtr thread; - nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // We run the DecodeToSurface tests off-main-thread to ensure that - // DecodeToSurface doesn't require any main-thread-only code. - RefPtr surface; - nsCOMPtr runnable = - new DecodeToSurfaceRunnable(surface, inputStream, aTestCase); - thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC); - - thread->Shutdown(); - - // Explicitly release the SourceSurface on the main thread. - surface = nullptr; -} - -class ImageDecodeToSurface : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); } -TEST_F(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); } -TEST_F(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); } -TEST_F(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); } -TEST_F(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); } -TEST_F(ImageDecodeToSurface, Icon) { RunDecodeToSurface(GreenIconTestCase()); } - -TEST_F(ImageDecodeToSurface, AnimatedGIF) -{ - RunDecodeToSurface(GreenFirstFrameAnimatedGIFTestCase()); -} - -TEST_F(ImageDecodeToSurface, AnimatedPNG) -{ - RunDecodeToSurface(GreenFirstFrameAnimatedPNGTestCase()); -} - -TEST_F(ImageDecodeToSurface, Corrupt) -{ - ImageTestCase testCase = CorruptTestCase(); - - nsCOMPtr inputStream = LoadFile(testCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - RefPtr surface = - ImageOps::DecodeToSurface(inputStream, - nsDependentCString(testCase.mMimeType), - imgIContainer::DECODE_FLAGS_DEFAULT); - EXPECT_TRUE(surface == nullptr); -} diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp deleted file mode 100644 index 58caa77a2e..0000000000 --- a/image/test/gtest/TestDecoders.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "decoders/nsBMPDecoder.h" -#include "IDecodingTask.h" -#include "imgIContainer.h" -#include "imgITools.h" -#include "ImageFactory.h" -#include "mozilla/gfx/2D.h" -#include "nsComponentManagerUtils.h" -#include "nsCOMPtr.h" -#include "nsIInputStream.h" -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "mozilla/RefPtr.h" -#include "nsStreamUtils.h" -#include "nsString.h" -#include "nsThreadUtils.h" -#include "ProgressTracker.h" -#include "SourceBuffer.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -static already_AddRefed -CheckDecoderState(const ImageTestCase& aTestCase, Decoder* aDecoder) -{ - EXPECT_TRUE(aDecoder->GetDecodeDone()); - EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), - aDecoder->HasError()); - - // Verify that the decoder made the expected progress. - Progress progress = aDecoder->TakeProgress(); - EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), - bool(progress & FLAG_HAS_ERROR)); - - if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) { - return nullptr; // That's all we can check for bad images. - } - - EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE)); - EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE)); - EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE)); - EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT), - bool(progress & FLAG_HAS_TRANSPARENCY)); - EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED), - bool(progress & FLAG_IS_ANIMATED)); - - // The decoder should get the correct size. - IntSize size = aDecoder->Size(); - EXPECT_EQ(aTestCase.mSize.width, size.width); - EXPECT_EQ(aTestCase.mSize.height, size.height); - - // Get the current frame, which is always the first frame of the image - // because CreateAnonymousDecoder() forces a first-frame-only decode. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - // Verify that the resulting surfaces matches our expectations. - EXPECT_EQ(SurfaceType::DATA, surface->GetType()); - EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 || - surface->GetFormat() == SurfaceFormat::B8G8R8A8); - EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize()); - - return surface.forget(); -} - -static void -CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder) -{ - RefPtr surface = CheckDecoderState(aTestCase, aDecoder); - if (!surface) { - return; - } - - if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) { - return; - } - - // Check the output. - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(), - aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0)); -} - -template -void WithSingleChunkDecode(const ImageTestCase& aTestCase, - const Maybe& aOutputSize, - Func aResultChecker) -{ - nsCOMPtr inputStream = LoadFile(aTestCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into a SourceBuffer. - NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); - sourceBuffer->ExpectLength(length); - rv = sourceBuffer->AppendFromInputStream(inputStream, length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - sourceBuffer->Complete(NS_OK); - - // Create a decoder. - DecoderType decoderType = - DecoderFactory::GetDecoderType(aTestCase.mMimeType); - RefPtr decoder = - DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, aOutputSize, - DefaultSurfaceFlags()); - ASSERT_TRUE(decoder != nullptr); - RefPtr task = new AnonymousDecodingTask(WrapNotNull(decoder)); - - // Run the full decoder synchronously. - task->Run(); - - // Call the lambda to verify the expected results. - aResultChecker(decoder); -} - -static void -CheckDecoderSingleChunk(const ImageTestCase& aTestCase) -{ - WithSingleChunkDecode(aTestCase, Nothing(), [&](Decoder* aDecoder) { - CheckDecoderResults(aTestCase, aDecoder); - }); -} - -static void -CheckDecoderMultiChunk(const ImageTestCase& aTestCase) -{ - nsCOMPtr inputStream = LoadFile(aTestCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Create a SourceBuffer and a decoder. - NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); - sourceBuffer->ExpectLength(length); - DecoderType decoderType = - DecoderFactory::GetDecoderType(aTestCase.mMimeType); - RefPtr decoder = - DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(), - DefaultSurfaceFlags()); - ASSERT_TRUE(decoder != nullptr); - RefPtr task = new AnonymousDecodingTask(WrapNotNull(decoder)); - - for (uint64_t read = 0; read < length ; ++read) { - uint64_t available = 0; - rv = inputStream->Available(&available); - ASSERT_TRUE(available > 0); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - rv = sourceBuffer->AppendFromInputStream(inputStream, 1); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - task->Run(); - } - - sourceBuffer->Complete(NS_OK); - task->Run(); - - CheckDecoderResults(aTestCase, decoder); -} - -static void -CheckDownscaleDuringDecode(const ImageTestCase& aTestCase) -{ - // This function expects that |aTestCase| consists of 25 lines of green, - // followed by 25 lines of red, followed by 25 lines of green, followed by 25 - // more lines of red. We'll downscale it from 100x100 to 20x20. - IntSize outputSize(20, 20); - - WithSingleChunkDecode(aTestCase, Some(outputSize), [&](Decoder* aDecoder) { - RefPtr surface = CheckDecoderState(aTestCase, aDecoder); - - // There are no downscale-during-decode tests that have TEST_CASE_HAS_ERROR - // set, so we expect to always get a surface here. - EXPECT_TRUE(surface != nullptr); - - if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) { - return; - } - - // Check that the downscaled image is correct. Note that we skip rows near - // the transitions between colors, since the downscaler does not produce a - // sharp boundary at these points. Even some of the rows we test need a - // small amount of fuzz; this is just the nature of Lanczos downscaling. - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 47)); - EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 27)); - EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 47)); - EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 27)); - }); -} - -class ImageDecoders : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageDecoders, PNGSingleChunk) -{ - CheckDecoderSingleChunk(GreenPNGTestCase()); -} - -TEST_F(ImageDecoders, PNGMultiChunk) -{ - CheckDecoderMultiChunk(GreenPNGTestCase()); -} - -TEST_F(ImageDecoders, PNGDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledPNGTestCase()); -} - -TEST_F(ImageDecoders, GIFSingleChunk) -{ - CheckDecoderSingleChunk(GreenGIFTestCase()); -} - -TEST_F(ImageDecoders, GIFMultiChunk) -{ - CheckDecoderMultiChunk(GreenGIFTestCase()); -} - -TEST_F(ImageDecoders, GIFDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledGIFTestCase()); -} - -TEST_F(ImageDecoders, JPGSingleChunk) -{ - CheckDecoderSingleChunk(GreenJPGTestCase()); -} - -TEST_F(ImageDecoders, JPGMultiChunk) -{ - CheckDecoderMultiChunk(GreenJPGTestCase()); -} - -TEST_F(ImageDecoders, JPGDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledJPGTestCase()); -} - -TEST_F(ImageDecoders, BMPSingleChunk) -{ - CheckDecoderSingleChunk(GreenBMPTestCase()); -} - -TEST_F(ImageDecoders, BMPMultiChunk) -{ - CheckDecoderMultiChunk(GreenBMPTestCase()); -} - -TEST_F(ImageDecoders, BMPDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledBMPTestCase()); -} - -TEST_F(ImageDecoders, ICOSingleChunk) -{ - CheckDecoderSingleChunk(GreenICOTestCase()); -} - -TEST_F(ImageDecoders, ICOMultiChunk) -{ - CheckDecoderMultiChunk(GreenICOTestCase()); -} - -TEST_F(ImageDecoders, ICODownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledICOTestCase()); -} - -TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase()); -} - -TEST_F(ImageDecoders, IconSingleChunk) -{ - CheckDecoderSingleChunk(GreenIconTestCase()); -} - -TEST_F(ImageDecoders, IconMultiChunk) -{ - CheckDecoderMultiChunk(GreenIconTestCase()); -} - -TEST_F(ImageDecoders, IconDownscaleDuringDecode) -{ - CheckDownscaleDuringDecode(DownscaledIconTestCase()); -} - -TEST_F(ImageDecoders, AnimatedGIFSingleChunk) -{ - CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase()); -} - -TEST_F(ImageDecoders, AnimatedGIFMultiChunk) -{ - CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase()); -} - -TEST_F(ImageDecoders, AnimatedPNGSingleChunk) -{ - CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase()); -} - -TEST_F(ImageDecoders, AnimatedPNGMultiChunk) -{ - CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase()); -} - -TEST_F(ImageDecoders, CorruptSingleChunk) -{ - CheckDecoderSingleChunk(CorruptTestCase()); -} - -TEST_F(ImageDecoders, CorruptMultiChunk) -{ - CheckDecoderMultiChunk(CorruptTestCase()); -} - -TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderSingleChunk) -{ - CheckDecoderSingleChunk(CorruptBMPWithTruncatedHeader()); -} - -TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderMultiChunk) -{ - CheckDecoderMultiChunk(CorruptBMPWithTruncatedHeader()); -} - -TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) -{ - CheckDecoderSingleChunk(CorruptICOWithBadBMPWidthTestCase()); -} - -TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) -{ - CheckDecoderMultiChunk(CorruptICOWithBadBMPWidthTestCase()); -} - -TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) -{ - CheckDecoderSingleChunk(CorruptICOWithBadBMPHeightTestCase()); -} - -TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) -{ - CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase()); -} - -TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST) -{ - ImageTestCase testCase = GreenFirstFrameAnimatedGIFTestCase(); - - // Verify that we can decode this test case and retrieve the first frame using - // imgIContainer::FRAME_FIRST. This ensures that we correctly trigger a - // single-frame decode rather than an animated decode when - // imgIContainer::FRAME_FIRST is requested. - - // Create an image. - RefPtr image = - ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); - ASSERT_TRUE(!image->HasError()); - - nsCOMPtr inputStream = LoadFile(testCase.mPath); - ASSERT_TRUE(inputStream); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into the image. - rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0, - static_cast(length)); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Let the image know we've sent all the data. - rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - RefPtr tracker = image->GetProgressTracker(); - tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); - - // Lock the image so its surfaces don't disappear during the test. - image->LockImage(); - - // Use GetFrame() to force a sync decode of the image, specifying FRAME_FIRST - // to ensure that we don't get an animated decode. - RefPtr surface = - image->GetFrame(imgIContainer::FRAME_FIRST, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that the image's metadata meets our expectations. - IntSize imageSize(0, 0); - rv = image->GetWidth(&imageSize.width); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - rv = image->GetHeight(&imageSize.height); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - - EXPECT_EQ(testCase.mSize.width, imageSize.width); - EXPECT_EQ(testCase.mSize.height, imageSize.height); - - Progress imageProgress = tracker->GetProgress(); - - EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); - EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); - - // Ensure that we decoded the static version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eStatic)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - EXPECT_TRUE(bool(result.Surface())); - } - - // Ensure that we didn't decode the animated version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::NOT_FOUND, result.Type()); - } - - // Use GetFrame() to force a sync decode of the image, this time specifying - // FRAME_CURRENT to ensure that we get an animated decode. - RefPtr animatedSurface = - image->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that we decoded both frames of the animated version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); - EXPECT_TRUE(bool(result.Surface())); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); - } - - // Ensure that the static version is still around. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eStatic)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - EXPECT_TRUE(bool(result.Surface())); - } -} - -TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) -{ - ImageTestCase testCase = GreenFirstFrameAnimatedGIFTestCase(); - - // Verify that we can decode this test case and retrieve the entire sequence - // of frames using imgIContainer::FRAME_CURRENT. This ensures that we - // correctly trigger an animated decode rather than a single-frame decode when - // imgIContainer::FRAME_CURRENT is requested. - - // Create an image. - RefPtr image = - ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); - ASSERT_TRUE(!image->HasError()); - - nsCOMPtr inputStream = LoadFile(testCase.mPath); - ASSERT_TRUE(inputStream); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into the image. - rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0, - static_cast(length)); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Let the image know we've sent all the data. - rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - RefPtr tracker = image->GetProgressTracker(); - tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); - - // Lock the image so its surfaces don't disappear during the test. - image->LockImage(); - - // Use GetFrame() to force a sync decode of the image, specifying - // FRAME_CURRENT to ensure we get an animated decode. - RefPtr surface = - image->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that the image's metadata meets our expectations. - IntSize imageSize(0, 0); - rv = image->GetWidth(&imageSize.width); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - rv = image->GetHeight(&imageSize.height); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - - EXPECT_EQ(testCase.mSize.width, imageSize.width); - EXPECT_EQ(testCase.mSize.height, imageSize.height); - - Progress imageProgress = tracker->GetProgress(); - - EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); - EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); - - // Ensure that we decoded both frames of the animated version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); - EXPECT_TRUE(bool(result.Surface())); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); - } - - // Ensure that we didn't decode the static version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eStatic)); - ASSERT_EQ(MatchType::NOT_FOUND, result.Type()); - } - - // Use GetFrame() to force a sync decode of the image, this time specifying - // FRAME_FIRST to ensure that we get a single-frame decode. - RefPtr animatedSurface = - image->GetFrame(imgIContainer::FRAME_FIRST, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that we decoded the static version of the image. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eStatic)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - EXPECT_TRUE(bool(result.Surface())); - } - - // Ensure that both frames of the animated version are still around. - { - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); - EXPECT_TRUE(bool(result.Surface())); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); - } -} - -TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) -{ - ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase(); - - // Verify that we can decode this test case and get two frames, even though - // there are extra image sub blocks between the first and second frame. The - // extra data shouldn't confuse the decoder or cause the decode to fail. - - // Create an image. - RefPtr image = - ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); - ASSERT_TRUE(!image->HasError()); - - nsCOMPtr inputStream = LoadFile(testCase.mPath); - ASSERT_TRUE(inputStream); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into the image. - rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0, - static_cast(length)); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Let the image know we've sent all the data. - rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - RefPtr tracker = image->GetProgressTracker(); - tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); - - // Use GetFrame() to force a sync decode of the image. - RefPtr surface = - image->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that the image's metadata meets our expectations. - IntSize imageSize(0, 0); - rv = image->GetWidth(&imageSize.width); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - rv = image->GetHeight(&imageSize.height); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - - EXPECT_EQ(testCase.mSize.width, imageSize.width); - EXPECT_EQ(testCase.mSize.height, imageSize.height); - - Progress imageProgress = tracker->GetProgress(); - - EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); - EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); - - // Ensure that we decoded both frames of the image. - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); - EXPECT_TRUE(bool(result.Surface())); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); -} - -TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) -{ - CheckDecoderSingleChunk(TruncatedSmallGIFTestCase()); -} diff --git a/image/test/gtest/TestDeinterlacingFilter.cpp b/image/test/gtest/TestDeinterlacingFilter.cpp deleted file mode 100644 index 82637bbf71..0000000000 --- a/image/test/gtest/TestDeinterlacingFilter.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfaceFilters.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -template void -WithDeinterlacingFilter(const IntSize& aSize, - bool aProgressiveDisplay, - Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(bool(decoder)); - - WithFilterPipeline(decoder, Forward(aFunc), - DeinterlacingConfig { aProgressiveDisplay }, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -template void -WithPalettedDeinterlacingFilter(const IntSize& aSize, - Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - WithFilterPipeline(decoder, Forward(aFunc), - DeinterlacingConfig { /* mProgressiveDisplay = */ true }, - PalettedSurfaceConfig { decoder, aSize, - IntRect(0, 0, 100, 100), - SurfaceFormat::B8G8R8A8, 8, - false }); -} - -void -AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - AssertConfiguringPipelineFails(decoder, - DeinterlacingConfig { /* mProgressiveDisplay = */ true}, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -class ImageDeinterlacingFilter : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageDeinterlacingFilter, WritePixels100_100) -{ - WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100))); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixels99_99) -{ - WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 99, 99)), - /* aInputRect = */ Some(IntRect(0, 0, 99, 99))); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixels8_8) -{ - WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 8, 8)), - /* aInputRect = */ Some(IntRect(0, 0, 8, 8))); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixels7_7) -{ - WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 7, 7)), - /* aInputRect = */ Some(IntRect(0, 0, 7, 7))); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixels3_3) -{ - WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 3, 3)), - /* aInputRect = */ Some(IntRect(0, 0, 3, 3))); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixels1_1) -{ - WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 1, 1)), - /* aInputRect = */ Some(IntRect(0, 0, 1, 1))); - }); -} - -TEST_F(ImageDeinterlacingFilter, PalettedWritePixels) -{ - WithPalettedDeinterlacingFilter(IntSize(100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckPalettedWritePixels(aDecoder, aFilter); - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52) -{ - WithDeinterlacingFilter(IntSize(51, 52), /* aProgressiveDisplay = */ false, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be green for even rows and red for odd - // rows but we need to write the rows in the order that the deinterlacer - // expects them. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() { - uint32_t row = count / 51; // Integer division. - ++count; - - // Note that we use a switch statement here, even though it's quite - // verbose, because it's useful to have the mappings between input and - // output rows available when debugging these tests. - - switch (row) { - // First pass. Output rows are positioned at 8n + 0. - case 0: // Output row 0. - case 1: // Output row 8. - case 2: // Output row 16. - case 3: // Output row 24. - case 4: // Output row 32. - case 5: // Output row 40. - case 6: // Output row 48. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Second pass. Rows are positioned at 8n + 4. - case 7: // Output row 4. - case 8: // Output row 12. - case 9: // Output row 20. - case 10: // Output row 28. - case 11: // Output row 36. - case 12: // Output row 44. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Third pass. Rows are positioned at 4n + 2. - case 13: // Output row 2. - case 14: // Output row 6. - case 15: // Output row 10. - case 16: // Output row 14. - case 17: // Output row 18. - case 18: // Output row 22. - case 19: // Output row 26. - case 20: // Output row 30. - case 21: // Output row 34. - case 22: // Output row 38. - case 23: // Output row 42. - case 24: // Output row 46. - case 25: // Output row 50. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Fourth pass. Rows are positioned at 2n + 1. - case 26: // Output row 1. - case 27: // Output row 3. - case 28: // Output row 5. - case 29: // Output row 7. - case 30: // Output row 9. - case 31: // Output row 11. - case 32: // Output row 13. - case 33: // Output row 15. - case 34: // Output row 17. - case 35: // Output row 19. - case 36: // Output row 21. - case 37: // Output row 23. - case 38: // Output row 25. - case 39: // Output row 27. - case 40: // Output row 29. - case 41: // Output row 31. - case 42: // Output row 33. - case 43: // Output row 35. - case 44: // Output row 37. - case 45: // Output row 39. - case 46: // Output row 41. - case 47: // Output row 43. - case 48: // Output row 45. - case 49: // Output row 47. - case 50: // Output row 49. - case 51: // Output row 51. - return AsVariant(BGRAColor::Red().AsPixel()); - - default: - MOZ_ASSERT_UNREACHABLE("Unexpected row"); - return AsVariant(BGRAColor::Transparent().AsPixel()); - } - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(51u * 52u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 51, 52), - IntRect(0, 0, 51, 52)); - - // Check that the generated image is correct. As mentioned above, we expect - // even rows to be green and odd rows to be red. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 52; ++row) { - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, - row % 2 == 0 ? BGRAColor::Green() - : BGRAColor::Red())); - } - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsOutput20_20) -{ - WithDeinterlacingFilter(IntSize(20, 20), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be green for even rows and red for odd - // rows but we need to write the rows in the order that the deinterlacer - // expects them. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() { - uint32_t row = count / 20; // Integer division. - ++count; - - // Note that we use a switch statement here, even though it's quite - // verbose, because it's useful to have the mappings between input and - // output rows available when debugging these tests. - - switch (row) { - // First pass. Output rows are positioned at 8n + 0. - case 0: // Output row 0. - case 1: // Output row 8. - case 2: // Output row 16. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Second pass. Rows are positioned at 8n + 4. - case 3: // Output row 4. - case 4: // Output row 12. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Third pass. Rows are positioned at 4n + 2. - case 5: // Output row 2. - case 6: // Output row 6. - case 7: // Output row 10. - case 8: // Output row 14. - case 9: // Output row 18. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Fourth pass. Rows are positioned at 2n + 1. - case 10: // Output row 1. - case 11: // Output row 3. - case 12: // Output row 5. - case 13: // Output row 7. - case 14: // Output row 9. - case 15: // Output row 11. - case 16: // Output row 13. - case 17: // Output row 15. - case 18: // Output row 17. - case 19: // Output row 19. - return AsVariant(BGRAColor::Red().AsPixel()); - - default: - MOZ_ASSERT_UNREACHABLE("Unexpected row"); - return AsVariant(BGRAColor::Transparent().AsPixel()); - } - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(20u * 20u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 20, 20), - IntRect(0, 0, 20, 20)); - - // Check that the generated image is correct. As mentioned above, we expect - // even rows to be green and odd rows to be red. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 20; ++row) { - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, - row % 2 == 0 ? BGRAColor::Green() - : BGRAColor::Red())); - } - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsOutput7_7) -{ - WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be a repeating pattern of two green - // rows followed by two red rows but we need to write the rows in the order - // that the deinterlacer expects them. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() { - uint32_t row = count / 7; // Integer division. - ++count; - - switch (row) { - // First pass. Output rows are positioned at 8n + 0. - case 0: // Output row 0. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Second pass. Rows are positioned at 8n + 4. - case 1: // Output row 4. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Third pass. Rows are positioned at 4n + 2. - case 2: // Output row 2. - case 3: // Output row 6. - return AsVariant(BGRAColor::Red().AsPixel()); - - // Fourth pass. Rows are positioned at 2n + 1. - case 4: // Output row 1. - return AsVariant(BGRAColor::Green().AsPixel()); - - case 5: // Output row 3. - return AsVariant(BGRAColor::Red().AsPixel()); - - case 6: // Output row 5. - return AsVariant(BGRAColor::Green().AsPixel()); - - default: - MOZ_ASSERT_UNREACHABLE("Unexpected row"); - return AsVariant(BGRAColor::Transparent().AsPixel()); - } - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(7u * 7u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 7, 7), - IntRect(0, 0, 7, 7)); - - // Check that the generated image is correct. As mentioned above, we expect - // two green rows, followed by two red rows, then two green rows, etc. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 7; ++row) { - BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 - ? BGRAColor::Green() - : BGRAColor::Red(); - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); - } - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsOutput3_3) -{ - WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be green, red, green in that order, but - // we need to write the rows in the order that the deinterlacer expects - // them. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() { - uint32_t row = count / 3; // Integer division. - ++count; - - switch (row) { - // First pass. Output rows are positioned at 8n + 0. - case 0: // Output row 0. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Second pass. Rows are positioned at 8n + 4. - // No rows for this pass. - - // Third pass. Rows are positioned at 4n + 2. - case 1: // Output row 2. - return AsVariant(BGRAColor::Green().AsPixel()); - - // Fourth pass. Rows are positioned at 2n + 1. - case 2: // Output row 1. - return AsVariant(BGRAColor::Red().AsPixel()); - - default: - MOZ_ASSERT_UNREACHABLE("Unexpected row"); - return AsVariant(BGRAColor::Transparent().AsPixel()); - } - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(3u * 3u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 3, 3), - IntRect(0, 0, 3, 3)); - - // Check that the generated image is correct. As mentioned above, we expect - // green, red, green in that order. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 3; ++row) { - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, - row == 0 || row == 2 ? BGRAColor::Green() - : BGRAColor::Red())); - } - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsOutput1_1) -{ - WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be a single red row. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(1u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 1, 1), - IntRect(0, 0, 1, 1)); - - // Check that the generated image is correct. As mentioned above, we expect - // a single red row. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 1, BGRAColor::Red())); - }); -} - -void -WriteRowAndCheckInterlacerOutput(Decoder* aDecoder, - SurfaceFilter* aFilter, - BGRAColor aColor, - WriteState aNextState, - IntRect aInvalidRect, - uint32_t aFirstHaeberliRow, - uint32_t aLastHaeberliRow) -{ - uint32_t count = 0; - - auto result = aFilter->WritePixels([&]() -> NextPixel { - if (count < 7) { - ++count; - return AsVariant(aColor.AsPixel()); - } - return AsVariant(WriteState::NEED_MORE_DATA); - }); - - EXPECT_EQ(aNextState, result); - EXPECT_EQ(7u, count); - - // Assert that we got the expected invalidation region. - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(aInvalidRect, invalidRect->mInputSpaceRect); - EXPECT_EQ(aInvalidRect, invalidRect->mOutputSpaceRect); - - // Check that the portion of the image generated so far is correct. The rows - // from aFirstHaeberliRow to aLastHaeberliRow should be filled with aColor. - // Note that this is not the same as the set of rows in aInvalidRect, because - // after writing a row the deinterlacer seeks to the next row to write, which - // may involve copying previously-written rows in the buffer to the output - // even though they don't change in this pass. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = aFirstHaeberliRow; row <= aLastHaeberliRow; ++row) { - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, aColor)); - } -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) -{ - WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be a repeating pattern of two green - // rows followed by two red rows but we need to write the rows in the order - // that the deinterlacer expects them. - - // First pass. Output rows are positioned at 8n + 0. - - // Output row 0. The invalid rect is the entire image because this is the - // end of the first pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 0, 4); - - // Second pass. Rows are positioned at 8n + 4. - - // Output row 4. The invalid rect is the entire image because this is the - // end of the second pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 1, 4); - - // Third pass. Rows are positioned at 4n + 2. - - // Output row 2. The invalid rect contains the Haeberli rows for this output - // row (rows 2 and 3) as well as the rows that we copy from previous passes - // when seeking to the next output row (rows 4 and 5). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 2, 7, 4), 2, 3); - - // Output row 6. The invalid rect is the entire image because this is the - // end of the third pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 6, 6); - - // Fourth pass. Rows are positioned at 2n + 1. - - // Output row 1. The invalid rect contains the Haeberli rows for this output - // row (just row 1) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 2). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 1, 7, 2), 1, 1); - - // Output row 3. The invalid rect contains the Haeberli rows for this output - // row (just row 3) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 4). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 3, 7, 2), 3, 3); - - // Output row 5. The invalid rect contains the Haeberli rows for this output - // row (just row 5) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 6). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::FINISHED, - IntRect(0, 5, 7, 2), 5, 5); - - // Assert that we're in the expected final state. - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the generated image is correct. As mentioned above, we expect - // two green rows, followed by two red rows, then two green rows, etc. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 7; ++row) { - BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 - ? BGRAColor::Green() - : BGRAColor::Red(); - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); - } - }); -} - -TEST_F(ImageDeinterlacingFilter, WritePixelsNonProgressiveIntermediateOutput7_7) -{ - WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ false, - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. The output should be a repeating pattern of two green - // rows followed by two red rows but we need to write the rows in the order - // that the deinterlacer expects them. - - // First pass. Output rows are positioned at 8n + 0. - - // Output row 0. The invalid rect is the entire image because this is the - // end of the first pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 0, 0); - - // Second pass. Rows are positioned at 8n + 4. - - // Output row 4. The invalid rect is the entire image because this is the - // end of the second pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 4, 4); - - // Third pass. Rows are positioned at 4n + 2. - - // Output row 2. The invalid rect contains the Haeberli rows for this output - // row (rows 2 and 3) as well as the rows that we copy from previous passes - // when seeking to the next output row (rows 4 and 5). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 2, 7, 4), 2, 2); - - // Output row 6. The invalid rect is the entire image because this is the - // end of the third pass. - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 0, 7, 7), 6, 6); - - // Fourth pass. Rows are positioned at 2n + 1. - - // Output row 1. The invalid rect contains the Haeberli rows for this output - // row (just row 1) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 2). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::NEED_MORE_DATA, - IntRect(0, 1, 7, 2), 1, 1); - - // Output row 3. The invalid rect contains the Haeberli rows for this output - // row (just row 3) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 4). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), - WriteState::NEED_MORE_DATA, - IntRect(0, 3, 7, 2), 3, 3); - - // Output row 5. The invalid rect contains the Haeberli rows for this output - // row (just row 5) as well as the rows that we copy from previous passes - // when seeking to the next output row (row 6). - WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), - WriteState::FINISHED, - IntRect(0, 5, 7, 2), 5, 5); - - // Assert that we're in the expected final state. - EXPECT_TRUE(aFilter->IsSurfaceFinished()); - Maybe invalidRect = aFilter->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the generated image is correct. As mentioned above, we expect - // two green rows, followed by two red rows, then two green rows, etc. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - for (uint32_t row = 0; row < 7; ++row) { - BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 - ? BGRAColor::Green() - : BGRAColor::Red(); - EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); - } - }); -} - - -TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0) -{ - // A 0x0 input size is invalid, so configuration should fail. - AssertConfiguringDeinterlacingFilterFails(IntSize(0, 0)); -} - -TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1) -{ - // A negative input size is invalid, so configuration should fail. - AssertConfiguringDeinterlacingFilterFails(IntSize(-1, -1)); -} diff --git a/image/test/gtest/TestDownscalingFilter.cpp b/image/test/gtest/TestDownscalingFilter.cpp deleted file mode 100644 index d7aa0ead2a..0000000000 --- a/image/test/gtest/TestDownscalingFilter.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfaceFilters.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -template void -WithDownscalingFilter(const IntSize& aInputSize, - const IntSize& aOutputSize, - Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - WithFilterPipeline(decoder, Forward(aFunc), - DownscalingConfig { aInputSize, - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, aOutputSize, - SurfaceFormat::B8G8R8A8, false }); -} - -void -AssertConfiguringDownscalingFilterFails(const IntSize& aInputSize, - const IntSize& aOutputSize) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - AssertConfiguringPipelineFails(decoder, - DownscalingConfig { aInputSize, - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, aOutputSize, - SurfaceFormat::B8G8R8A8, false }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to99_99) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 99, 99))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to33_33) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 33, 33))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to1_1) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 1, 1))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to33_99) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 33, 99))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to99_33) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 99, 33))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to99_1) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 99, 1))); - }); -} - -TEST(ImageDownscalingFilter, WritePixels100_100to1_99) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 1, 99))); - }); -} - -TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to101_101) -{ - // Upscaling is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(101, 101)); -} - -TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to100_100) -{ - // "Scaling" to the same size is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(100, 100)); -} - -TEST(ImageDownscalingFilter, DownscalingFailsFor0_0toMinus1_Minus1) -{ - // A 0x0 input size is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(0, 0), IntSize(-1, -1)); -} - -TEST(ImageDownscalingFilter, DownscalingFailsForMinus1_Minus1toMinus2_Minus2) -{ - // A negative input size is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(-1, -1), IntSize(-2, -2)); -} - -TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to0_0) -{ - // A 0x0 output size is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(0, 0)); -} - -TEST(ImageDownscalingFilter, DownscalingFailsFor100_100toMinus1_Minus1) -{ - // A negative output size is disallowed. - AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(-1, -1)); -} - -TEST(ImageDownscalingFilter, WritePixelsOutput100_100to20_20) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(20, 20), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. It consists of 25 lines of green, followed by 25 lines of - // red, followed by 25 lines of green, followed by 25 more lines of red. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() -> NextPixel { - uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) - ? BGRAColor::Green().AsPixel() - : BGRAColor::Red().AsPixel(); - ++count; - return AsVariant(color); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 20, 20)); - - // Check that the generated image is correct. Note that we skip rows near - // the transitions between colors, since the downscaler does not produce a - // sharp boundary at these points. Even some of the rows we test need a - // small amount of fuzz; this is just the nature of Lanczos downscaling. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); - EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); - EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); - EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); - }); -} - -TEST(ImageDownscalingFilter, WritePixelsOutput100_100to10_20) -{ - WithDownscalingFilter(IntSize(100, 100), IntSize(10, 20), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Fill the image. It consists of 25 lines of green, followed by 25 lines of - // red, followed by 25 lines of green, followed by 25 more lines of red. - uint32_t count = 0; - auto result = aFilter->WritePixels([&]() -> NextPixel { - uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) - ? BGRAColor::Green().AsPixel() - : BGRAColor::Red().AsPixel(); - ++count; - return AsVariant(color); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - AssertCorrectPipelineFinalState(aFilter, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 10, 20)); - - // Check that the generated image is correct. Note that we skip rows near - // the transitions between colors, since the downscaler does not produce a - // sharp boundary at these points. Even some of the rows we test need a - // small amount of fuzz; this is just the nature of Lanczos downscaling. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); - EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); - EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); - EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); - }); -} - -TEST(ImageDownscalingFilter, ConfiguringPalettedDownscaleFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // DownscalingFilter does not support paletted images, so configuration should - // fail. - AssertConfiguringPipelineFails(decoder, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, IntSize(20, 20), - IntRect(0, 0, 20, 20), - SurfaceFormat::B8G8R8A8, 8, - false }); -} diff --git a/image/test/gtest/TestDownscalingFilterNoSkia.cpp b/image/test/gtest/TestDownscalingFilterNoSkia.cpp deleted file mode 100644 index 80928a8809..0000000000 --- a/image/test/gtest/TestDownscalingFilterNoSkia.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfacePipe.h" - -// We want to ensure that we're testing the non-Skia fallback version of -// DownscalingFilter, but there are two issues: -// (1) We don't know whether Skia is currently enabled. -// (2) If we force disable it, the disabled version will get linked into the -// binary and will cause the tests in TestDownscalingFilter to fail. -// To avoid these problems, we ensure that MOZ_ENABLE_SKIA is defined when -// including DownscalingFilter.h, and we use the preprocessor to redefine the -// DownscalingFilter class to DownscalingFilterNoSkia. - -#define DownscalingFilter DownscalingFilterNoSkia - -#ifdef MOZ_ENABLE_SKIA - -#undef MOZ_ENABLE_SKIA -#include "Common.h" -#include "DownscalingFilter.h" -#define MOZ_ENABLE_SKIA - -#else - -#include "Common.h" -#include "DownscalingFilter.h" - -#endif - -#undef DownscalingFilter - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -TEST(ImageDownscalingFilter, NoSkia) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(bool(decoder)); - - // Configuring a DownscalingFilter should fail without Skia. - AssertConfiguringPipelineFails(decoder, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(50, 50), - SurfaceFormat::B8G8R8A8, false }); -} diff --git a/image/test/gtest/TestLoader.cpp b/image/test/gtest/TestLoader.cpp deleted file mode 100644 index 5551f3f053..0000000000 --- a/image/test/gtest/TestLoader.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "Common.h" -#include "imgLoader.h" -#include "nsMimeTypes.h" -#include "nsString.h" - -using namespace mozilla; -using namespace mozilla::image; - -static void -CheckMimeType(const char* aContents, size_t aLength, const char* aExpected) -{ - nsAutoCString detected; - nsresult rv = imgLoader::GetMimeTypeFromContent(aContents, aLength, detected); - if (aExpected) { - ASSERT_TRUE(NS_SUCCEEDED(rv)); - EXPECT_TRUE(detected.EqualsASCII(aExpected)); - } else { - ASSERT_TRUE(NS_FAILED(rv)); - EXPECT_TRUE(detected.IsEmpty()); - } -} - -class ImageLoader : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageLoader, DetectGIF) -{ - const char buffer[] = "GIF87a"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_GIF); -} - -TEST_F(ImageLoader, DetectPNG) -{ - const char buffer[] = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_PNG); -} - -TEST_F(ImageLoader, DetectJPEG) -{ - const char buffer[] = "\xFF\xD8\xFF"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_JPEG); -} - -TEST_F(ImageLoader, DetectART) -{ - const char buffer[] = "\x4A\x47\xFF\xFF\x00"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_ART); -} - -TEST_F(ImageLoader, DetectBMP) -{ - const char buffer[] = "BM"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_BMP); -} - -TEST_F(ImageLoader, DetectICO) -{ - const char buffer[] = "\x00\x00\x01\x00"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_ICO); -} - -TEST_F(ImageLoader, DetectWebP) -{ - const char buffer[] = "RIFF\xFF\xFF\xFF\xFFWEBPVP8L"; - CheckMimeType(buffer, sizeof(buffer), IMAGE_WEBP); -} - -TEST_F(ImageLoader, DetectNone) -{ - const char buffer[] = "abcdefghijklmnop"; - CheckMimeType(buffer, sizeof(buffer), nullptr); -} - diff --git a/image/test/gtest/TestMetadata.cpp b/image/test/gtest/TestMetadata.cpp deleted file mode 100644 index 9f3a648988..0000000000 --- a/image/test/gtest/TestMetadata.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "decoders/nsBMPDecoder.h" -#include "IDecodingTask.h" -#include "imgIContainer.h" -#include "imgITools.h" -#include "ImageFactory.h" -#include "mozilla/gfx/2D.h" -#include "nsComponentManagerUtils.h" -#include "nsCOMPtr.h" -#include "nsIInputStream.h" -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "mozilla/RefPtr.h" -#include "nsStreamUtils.h" -#include "nsString.h" -#include "nsThreadUtils.h" -#include "ProgressTracker.h" -#include "SourceBuffer.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -enum class BMPWithinICO -{ - NO, - YES -}; - -static void -CheckMetadata(const ImageTestCase& aTestCase, - BMPWithinICO aBMPWithinICO = BMPWithinICO::NO) -{ - nsCOMPtr inputStream = LoadFile(aTestCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into a SourceBuffer. - NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); - sourceBuffer->ExpectLength(length); - rv = sourceBuffer->AppendFromInputStream(inputStream, length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - sourceBuffer->Complete(NS_OK); - - // Create a metadata decoder. - DecoderType decoderType = - DecoderFactory::GetDecoderType(aTestCase.mMimeType); - RefPtr decoder = - DecoderFactory::CreateAnonymousMetadataDecoder(decoderType, sourceBuffer); - ASSERT_TRUE(decoder != nullptr); - RefPtr task = new AnonymousDecodingTask(WrapNotNull(decoder)); - - if (aBMPWithinICO == BMPWithinICO::YES) { - static_cast(decoder.get())->SetIsWithinICO(); - } - - // Run the metadata decoder synchronously. - task->Run(); - - // Ensure that the metadata decoder didn't make progress it shouldn't have - // (which would indicate that it decoded past the header of the image). - Progress metadataProgress = decoder->TakeProgress(); - EXPECT_TRUE(0 == (metadataProgress & ~(FLAG_SIZE_AVAILABLE | - FLAG_HAS_TRANSPARENCY | - FLAG_IS_ANIMATED))); - - // If the test case is corrupt, assert what we can and return early. - if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) { - EXPECT_TRUE(decoder->GetDecodeDone()); - EXPECT_TRUE(decoder->HasError()); - return; - } - - EXPECT_TRUE(decoder->GetDecodeDone() && !decoder->HasError()); - - // Check that we got the expected metadata. - EXPECT_TRUE(metadataProgress & FLAG_SIZE_AVAILABLE); - - IntSize metadataSize = decoder->Size(); - EXPECT_EQ(aTestCase.mSize.width, metadataSize.width); - EXPECT_EQ(aTestCase.mSize.height, metadataSize.height); - - bool expectTransparency = aBMPWithinICO == BMPWithinICO::YES - ? true - : bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT); - EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY)); - - EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED), - bool(metadataProgress & FLAG_IS_ANIMATED)); - - // Create a full decoder, so we can compare the result. - decoder = - DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(), - DefaultSurfaceFlags()); - ASSERT_TRUE(decoder != nullptr); - task = new AnonymousDecodingTask(WrapNotNull(decoder)); - - if (aBMPWithinICO == BMPWithinICO::YES) { - static_cast(decoder.get())->SetIsWithinICO(); - } - - // Run the full decoder synchronously. - task->Run(); - - EXPECT_TRUE(decoder->GetDecodeDone() && !decoder->HasError()); - Progress fullProgress = decoder->TakeProgress(); - - // If the metadata decoder set a progress bit, the full decoder should also - // have set the same bit. - EXPECT_EQ(fullProgress, metadataProgress | fullProgress); - - // The full decoder and the metadata decoder should agree on the image's size. - IntSize fullSize = decoder->Size(); - EXPECT_EQ(metadataSize.width, fullSize.width); - EXPECT_EQ(metadataSize.height, fullSize.height); - - // We should not discover transparency during the full decode that we didn't - // discover during the metadata decode, unless the image is animated. - EXPECT_TRUE(!(fullProgress & FLAG_HAS_TRANSPARENCY) || - (metadataProgress & FLAG_HAS_TRANSPARENCY) || - (fullProgress & FLAG_IS_ANIMATED)); -} - -class ImageDecoderMetadata : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageDecoderMetadata, PNG) { CheckMetadata(GreenPNGTestCase()); } -TEST_F(ImageDecoderMetadata, TransparentPNG) { CheckMetadata(TransparentPNGTestCase()); } -TEST_F(ImageDecoderMetadata, GIF) { CheckMetadata(GreenGIFTestCase()); } -TEST_F(ImageDecoderMetadata, TransparentGIF) { CheckMetadata(TransparentGIFTestCase()); } -TEST_F(ImageDecoderMetadata, JPG) { CheckMetadata(GreenJPGTestCase()); } -TEST_F(ImageDecoderMetadata, BMP) { CheckMetadata(GreenBMPTestCase()); } -TEST_F(ImageDecoderMetadata, ICO) { CheckMetadata(GreenICOTestCase()); } -TEST_F(ImageDecoderMetadata, Icon) { CheckMetadata(GreenIconTestCase()); } - -TEST_F(ImageDecoderMetadata, AnimatedGIF) -{ - CheckMetadata(GreenFirstFrameAnimatedGIFTestCase()); -} - -TEST_F(ImageDecoderMetadata, AnimatedPNG) -{ - CheckMetadata(GreenFirstFrameAnimatedPNGTestCase()); -} - -TEST_F(ImageDecoderMetadata, FirstFramePaddingGIF) -{ - CheckMetadata(FirstFramePaddingGIFTestCase()); -} - -TEST_F(ImageDecoderMetadata, TransparentIfWithinICOBMPNotWithinICO) -{ - CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_DEFAULT_FLAGS), - BMPWithinICO::NO); -} - -TEST_F(ImageDecoderMetadata, TransparentIfWithinICOBMPWithinICO) -{ - CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_IS_TRANSPARENT), - BMPWithinICO::YES); -} - -TEST_F(ImageDecoderMetadata, RLE4BMP) { CheckMetadata(RLE4BMPTestCase()); } -TEST_F(ImageDecoderMetadata, RLE8BMP) { CheckMetadata(RLE8BMPTestCase()); } - -TEST_F(ImageDecoderMetadata, Corrupt) { CheckMetadata(CorruptTestCase()); } - -TEST_F(ImageDecoderMetadata, NoFrameDelayGIF) -{ - CheckMetadata(NoFrameDelayGIFTestCase()); -} - -TEST_F(ImageDecoderMetadata, NoFrameDelayGIFFullDecode) -{ - ImageTestCase testCase = NoFrameDelayGIFTestCase(); - - // The previous test (NoFrameDelayGIF) verifies that we *don't* detect that - // this test case is animated, because it has a zero frame delay for the first - // frame. This test verifies that when we do a full decode, we detect the - // animation at that point and successfully decode all the frames. - - // Create an image. - RefPtr image = - ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); - ASSERT_TRUE(!image->HasError()); - - nsCOMPtr inputStream = LoadFile(testCase.mPath); - ASSERT_TRUE(inputStream != nullptr); - - // Figure out how much data we have. - uint64_t length; - nsresult rv = inputStream->Available(&length); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Write the data into the image. - rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0, - static_cast(length)); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - // Let the image know we've sent all the data. - rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - RefPtr tracker = image->GetProgressTracker(); - tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); - - // Use GetFrame() to force a sync decode of the image. - RefPtr surface = - image->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - - // Ensure that the image's metadata meets our expectations. - IntSize imageSize(0, 0); - rv = image->GetWidth(&imageSize.width); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - rv = image->GetHeight(&imageSize.height); - EXPECT_TRUE(NS_SUCCEEDED(rv)); - - EXPECT_EQ(testCase.mSize.width, imageSize.width); - EXPECT_EQ(testCase.mSize.height, imageSize.height); - - Progress imageProgress = tracker->GetProgress(); - - EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); - EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); - - // Ensure that we decoded both frames of the image. - LookupResult result = - SurfaceCache::Lookup(ImageKey(image.get()), - RasterSurfaceKey(imageSize, - DefaultSurfaceFlags(), - PlaybackType::eAnimated)); - ASSERT_EQ(MatchType::EXACT, result.Type()); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); - EXPECT_TRUE(bool(result.Surface())); - - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); -} diff --git a/image/test/gtest/TestRemoveFrameRectFilter.cpp b/image/test/gtest/TestRemoveFrameRectFilter.cpp deleted file mode 100644 index ad1f944fc4..0000000000 --- a/image/test/gtest/TestRemoveFrameRectFilter.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfaceFilters.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -template void -WithRemoveFrameRectFilter(const IntSize& aSize, - const IntRect& aFrameRect, - Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - WithFilterPipeline(decoder, Forward(aFunc), - RemoveFrameRectConfig { aFrameRect }, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -void -AssertConfiguringRemoveFrameRectFilterFails(const IntSize& aSize, - const IntRect& aFrameRect) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - AssertConfiguringPipelineFails(decoder, - RemoveFrameRectConfig { aFrameRect }, - SurfaceConfig { decoder, aSize, - SurfaceFormat::B8G8R8A8, false }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_0_0) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(0, 0, 0, 0), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_50_0_0) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(-50, 50, 0, 0), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_Minus50_0_0) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(50, -50, 0, 0), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_150_50_0_0) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(150, 50, 0, 0), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_150_0_0) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(50, 150, 0, 0), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_200_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(200, 200, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_25_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(-200, 25, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus200_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(25, -200, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_25_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(200, 25, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_200_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(25, 200, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_Minus200_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(-200, -200, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_Minus50_100_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(-50, -50, 100, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 50, 50))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_25_100_50) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(-50, 25, 100, 50), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), - /* aOutputWriteRect = */ Some(IntRect(0, 25, 50, 50))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus50_50_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(25, -50, 50, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 100)), - /* aOutputWriteRect = */ Some(IntRect(25, 0, 50, 50))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_25_100_50) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(50, 25, 100, 50), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), - /* aOutputWriteRect = */ Some(IntRect(50, 25, 50, 50))); - }); -} - -TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_50_50_100) -{ - WithRemoveFrameRectFilter(IntSize(100, 100), - IntRect(25, 50, 50, 100), - [](Decoder* aDecoder, SurfaceFilter* aFilter) { - // Note that aInputRect is 50x50 because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows - // unfortunately can't be ignored.) - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(25, 50, 50, 100))); - }); -} - -TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor0_0_to_0_0_100_100) -{ - // A zero-size image is disallowed. - AssertConfiguringRemoveFrameRectFilterFails(IntSize(0, 0), - IntRect(0, 0, 100, 100)); -} - -TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsForMinus1_Minus1_to_0_0_100_100) -{ - // A negative-size image is disallowed. - AssertConfiguringRemoveFrameRectFilterFails(IntSize(-1, -1), - IntRect(0, 0, 100, 100)); -} - -TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_0_0) -{ - // A zero size frame rect is disallowed. - AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100), - IntRect(0, 0, -1, -1)); -} - -TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_Minus1_Minus1) -{ - // A negative size frame rect is disallowed. - AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100), - IntRect(0, 0, -1, -1)); -} - -TEST(ImageRemoveFrameRectFilter, ConfiguringPalettedRemoveFrameRectFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // RemoveFrameRectFilter does not support paletted images, so configuration - // should fail. - AssertConfiguringPipelineFails(decoder, - RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, - PalettedSurfaceConfig { decoder, IntSize(100, 100), - IntRect(0, 0, 50, 50), - SurfaceFormat::B8G8R8A8, 8, - false }); -} diff --git a/image/test/gtest/TestSourceBuffer.cpp b/image/test/gtest/TestSourceBuffer.cpp deleted file mode 100644 index 05a88093f5..0000000000 --- a/image/test/gtest/TestSourceBuffer.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include -#include - -#include "mozilla/Move.h" -#include "SourceBuffer.h" -#include "SurfaceCache.h" - -using namespace mozilla; -using namespace mozilla::image; - -using std::min; - -void -ExpectChunkAndByteCount(const SourceBufferIterator& aIterator, - uint32_t aChunks, - size_t aBytes) -{ - EXPECT_EQ(aChunks, aIterator.ChunkCount()); - EXPECT_EQ(aBytes, aIterator.ByteCount()); -} - -void -ExpectRemainingBytes(const SourceBufferIterator& aIterator, size_t aBytes) -{ - EXPECT_TRUE(aIterator.RemainingBytesIsNoMoreThan(aBytes)); - EXPECT_TRUE(aIterator.RemainingBytesIsNoMoreThan(aBytes + 1)); - - if (aBytes > 0) { - EXPECT_FALSE(aIterator.RemainingBytesIsNoMoreThan(0)); - EXPECT_FALSE(aIterator.RemainingBytesIsNoMoreThan(aBytes - 1)); - } -} - -char -GenerateByte(size_t aIndex) -{ - uint8_t byte = aIndex % 256; - return *reinterpret_cast(&byte); -} - -void -GenerateData(char* aOutput, size_t aOffset, size_t aLength) -{ - for (size_t i = 0; i < aLength; ++i) { - aOutput[i] = GenerateByte(aOffset + i); - } -} - -void -GenerateData(char* aOutput, size_t aLength) -{ - GenerateData(aOutput, 0, aLength); -} - -void -CheckData(const char* aData, size_t aOffset, size_t aLength) -{ - for (size_t i = 0; i < aLength; ++i) { - ASSERT_EQ(GenerateByte(aOffset + i), aData[i]); - } -} - -enum class AdvanceMode -{ - eAdvanceAsMuchAsPossible, - eAdvanceByLengthExactly -}; - -class ImageSourceBuffer : public ::testing::Test -{ -public: - ImageSourceBuffer() - : mSourceBuffer(new SourceBuffer) - , mExpectNoResume(new ExpectNoResume) - , mCountResumes(new CountResumes) - { - GenerateData(mData, sizeof(mData)); - EXPECT_FALSE(mSourceBuffer->IsComplete()); - } - -protected: - void CheckedAppendToBuffer(const char* aData, size_t aLength) - { - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->Append(aData, aLength))); - } - - void CheckedAppendToBufferLastByteForLength(size_t aLength) - { - const char lastByte = GenerateByte(aLength); - CheckedAppendToBuffer(&lastByte, 1); - } - - void CheckedAppendToBufferInChunks(size_t aChunkLength, size_t aTotalLength) - { - char* data = new char[aChunkLength]; - - size_t bytesWritten = 0; - while (bytesWritten < aTotalLength) { - GenerateData(data, bytesWritten, aChunkLength); - size_t toWrite = min(aChunkLength, aTotalLength - bytesWritten); - CheckedAppendToBuffer(data, toWrite); - bytesWritten += toWrite; - } - - delete[] data; - } - - void CheckedCompleteBuffer(nsresult aCompletionStatus = NS_OK) - { - mSourceBuffer->Complete(aCompletionStatus); - EXPECT_TRUE(mSourceBuffer->IsComplete()); - } - - void CheckedCompleteBuffer(SourceBufferIterator& aIterator, - size_t aLength, - nsresult aCompletionStatus = NS_OK) - { - CheckedCompleteBuffer(aCompletionStatus); - ExpectRemainingBytes(aIterator, aLength); - } - - void CheckedAdvanceIteratorStateOnly(SourceBufferIterator& aIterator, - size_t aLength, - uint32_t aChunks, - size_t aTotalLength, - AdvanceMode aAdvanceMode - = AdvanceMode::eAdvanceAsMuchAsPossible) - { - const size_t advanceBy = aAdvanceMode == AdvanceMode::eAdvanceAsMuchAsPossible - ? SIZE_MAX - : aLength; - - auto state = aIterator.AdvanceOrScheduleResume(advanceBy, mExpectNoResume); - ASSERT_EQ(SourceBufferIterator::READY, state); - EXPECT_TRUE(aIterator.Data()); - EXPECT_EQ(aLength, aIterator.Length()); - - ExpectChunkAndByteCount(aIterator, aChunks, aTotalLength); - } - - void CheckedAdvanceIteratorStateOnly(SourceBufferIterator& aIterator, - size_t aLength) - { - CheckedAdvanceIteratorStateOnly(aIterator, aLength, 1, aLength); - } - - void CheckedAdvanceIterator(SourceBufferIterator& aIterator, - size_t aLength, - uint32_t aChunks, - size_t aTotalLength, - AdvanceMode aAdvanceMode - = AdvanceMode::eAdvanceAsMuchAsPossible) - { - // Check that the iterator is in the expected state. - CheckedAdvanceIteratorStateOnly(aIterator, aLength, aChunks, - aTotalLength, aAdvanceMode); - - // Check that we read the expected data. To do this, we need to compute our - // offset in the SourceBuffer, but fortunately that's pretty easy: it's the - // total number of bytes the iterator has advanced through, minus the length - // of the current chunk. - const size_t offset = aIterator.ByteCount() - aIterator.Length(); - CheckData(aIterator.Data(), offset, aIterator.Length()); - } - - void CheckedAdvanceIterator(SourceBufferIterator& aIterator, size_t aLength) - { - CheckedAdvanceIterator(aIterator, aLength, 1, aLength); - } - - void CheckIteratorMustWait(SourceBufferIterator& aIterator, - IResumable* aOnResume) - { - auto state = aIterator.AdvanceOrScheduleResume(1, aOnResume); - EXPECT_EQ(SourceBufferIterator::WAITING, state); - } - - void CheckIteratorIsComplete(SourceBufferIterator& aIterator, - uint32_t aChunks, - size_t aTotalLength, - nsresult aCompletionStatus = NS_OK) - { - ASSERT_TRUE(mSourceBuffer->IsComplete()); - auto state = aIterator.AdvanceOrScheduleResume(1, mExpectNoResume); - ASSERT_EQ(SourceBufferIterator::COMPLETE, state); - EXPECT_EQ(aCompletionStatus, aIterator.CompletionStatus()); - ExpectRemainingBytes(aIterator, 0); - ExpectChunkAndByteCount(aIterator, aChunks, aTotalLength); - } - - void CheckIteratorIsComplete(SourceBufferIterator& aIterator, - size_t aTotalLength) - { - CheckIteratorIsComplete(aIterator, 1, aTotalLength); - } - - AutoInitializeImageLib mInit; - char mData[9]; - RefPtr mSourceBuffer; - RefPtr mExpectNoResume; - RefPtr mCountResumes; -}; - -TEST_F(ImageSourceBuffer, InitialState) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // RemainingBytesIsNoMoreThan() should always return false in the initial - // state, since we can't know the answer until Complete() has been called. - EXPECT_FALSE(iterator.RemainingBytesIsNoMoreThan(0)); - EXPECT_FALSE(iterator.RemainingBytesIsNoMoreThan(SIZE_MAX)); - - // We haven't advanced our iterator at all, so its counters should be zero. - ExpectChunkAndByteCount(iterator, 0, 0); - - // Attempt to advance; we should fail, and end up in the WAITING state. We - // expect no resumes because we don't actually append anything to the - // SourceBuffer in this test. - CheckIteratorMustWait(iterator, mExpectNoResume); -} - -TEST_F(ImageSourceBuffer, ZeroLengthBufferAlwaysFails) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Complete the buffer without writing to it, providing a successful - // completion status. - CheckedCompleteBuffer(iterator, 0); - - // Completing a buffer without writing to it results in an automatic failure; - // make sure that the actual completion status we get from the iterator - // reflects this. - CheckIteratorIsComplete(iterator, 0, 0, NS_ERROR_FAILURE); -} - -TEST_F(ImageSourceBuffer, CompleteSuccess) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write a single byte to the buffer and complete the buffer. (We have to - // write at least one byte because completing a zero length buffer always - // fails; see the ZeroLengthBufferAlwaysFails test.) - CheckedAppendToBuffer(mData, 1); - CheckedCompleteBuffer(iterator, 1); - - // We should be able to advance once (to read the single byte) and then should - // reach the COMPLETE state with a successful status. - CheckedAdvanceIterator(iterator, 1); - CheckIteratorIsComplete(iterator, 1); -} - -TEST_F(ImageSourceBuffer, CompleteFailure) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write a single byte to the buffer and complete the buffer. (We have to - // write at least one byte because completing a zero length buffer always - // fails; see the ZeroLengthBufferAlwaysFails test.) - CheckedAppendToBuffer(mData, 1); - CheckedCompleteBuffer(iterator, 1, NS_ERROR_FAILURE); - - // Advance the iterator. Because a failing status is propagated to the - // iterator as soon as it advances, we won't be able to read the single byte - // that we wrote above; we go directly into the COMPLETE state. - CheckIteratorIsComplete(iterator, 0, 0, NS_ERROR_FAILURE); -} - -TEST_F(ImageSourceBuffer, Append) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write test data to the buffer. - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->ExpectLength(sizeof(mData)))); - CheckedAppendToBuffer(mData, sizeof(mData)); - CheckedCompleteBuffer(iterator, sizeof(mData)); - - // Verify that we can read it back via the iterator, and that the final state - // is what we expect. - CheckedAdvanceIterator(iterator, sizeof(mData)); - CheckIteratorIsComplete(iterator, sizeof(mData)); -} - -TEST_F(ImageSourceBuffer, HugeAppendFails) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // We should fail to append anything bigger than what the SurfaceCache can - // hold, so use the SurfaceCache's maximum capacity to calculate what a - // "massive amount of data" (see below) consists of on this platform. - ASSERT_LT(SurfaceCache::MaximumCapacity(), SIZE_MAX); - const size_t hugeSize = SurfaceCache::MaximumCapacity() + 1; - - // Attempt to write a massive amount of data and verify that it fails. (We'd - // get a buffer overrun during the test if it succeeds, but if it succeeds - // that's the least of our problems.) - EXPECT_TRUE(NS_FAILED(mSourceBuffer->Append(mData, hugeSize))); - EXPECT_TRUE(mSourceBuffer->IsComplete()); - CheckIteratorIsComplete(iterator, 0, 0, NS_ERROR_OUT_OF_MEMORY); -} - -TEST_F(ImageSourceBuffer, AppendFromInputStream) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Construct an input stream with some arbitrary data. (We use test data from - // one of the decoder tests.) - nsCOMPtr inputStream = LoadFile(GreenPNGTestCase().mPath); - ASSERT_TRUE(inputStream != nullptr); - - // Figure out how much data we have. - uint64_t length; - ASSERT_TRUE(NS_SUCCEEDED(inputStream->Available(&length))); - - // Write test data to the buffer. - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->AppendFromInputStream(inputStream, - length))); - CheckedCompleteBuffer(iterator, length); - - // Verify that the iterator sees the appropriate amount of data. - CheckedAdvanceIteratorStateOnly(iterator, length); - CheckIteratorIsComplete(iterator, length); -} - -TEST_F(ImageSourceBuffer, AppendAfterComplete) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write test data to the buffer. - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->ExpectLength(sizeof(mData)))); - CheckedAppendToBuffer(mData, sizeof(mData)); - CheckedCompleteBuffer(iterator, sizeof(mData)); - - // Verify that we can read it back via the iterator, and that the final state - // is what we expect. - CheckedAdvanceIterator(iterator, sizeof(mData)); - CheckIteratorIsComplete(iterator, sizeof(mData)); - - // Write more data to the completed buffer. - EXPECT_TRUE(NS_FAILED(mSourceBuffer->Append(mData, sizeof(mData)))); - - // Try to read with a new iterator and verify that the new data got ignored. - SourceBufferIterator iterator2 = mSourceBuffer->Iterator(); - CheckedAdvanceIterator(iterator2, sizeof(mData)); - CheckIteratorIsComplete(iterator2, sizeof(mData)); -} - -TEST_F(ImageSourceBuffer, MinChunkCapacity) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write test data to the buffer using many small appends. Since - // ExpectLength() isn't being called, we should be able to write up to - // SourceBuffer::MIN_CHUNK_CAPACITY bytes without a second chunk being - // allocated. - CheckedAppendToBufferInChunks(10, SourceBuffer::MIN_CHUNK_CAPACITY); - - // Verify that the iterator sees the appropriate amount of data. - CheckedAdvanceIterator(iterator, SourceBuffer::MIN_CHUNK_CAPACITY); - - // Write one more byte; we expect to see that it triggers an allocation. - CheckedAppendToBufferLastByteForLength(SourceBuffer::MIN_CHUNK_CAPACITY); - CheckedCompleteBuffer(iterator, 1); - - // Verify that the iterator sees the new byte and a new chunk has been - // allocated. - CheckedAdvanceIterator(iterator, 1, 2, SourceBuffer::MIN_CHUNK_CAPACITY + 1); - CheckIteratorIsComplete(iterator, 2, SourceBuffer::MIN_CHUNK_CAPACITY + 1); -} - -TEST_F(ImageSourceBuffer, ExpectLengthDoesNotShrinkBelowMinCapacity) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the buffer, - // but call ExpectLength() first to make SourceBuffer expect only a single - // byte. We expect this to still result in only one chunk, because - // regardless of ExpectLength() we won't allocate a chunk smaller than - // MIN_CHUNK_CAPACITY bytes. - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->ExpectLength(1))); - CheckedAppendToBufferInChunks(10, SourceBuffer::MIN_CHUNK_CAPACITY); - CheckedCompleteBuffer(iterator, SourceBuffer::MIN_CHUNK_CAPACITY); - - // Verify that the iterator sees a single chunk. - CheckedAdvanceIterator(iterator, SourceBuffer::MIN_CHUNK_CAPACITY); - CheckIteratorIsComplete(iterator, 1, SourceBuffer::MIN_CHUNK_CAPACITY); -} - -TEST_F(ImageSourceBuffer, ExpectLengthGrowsAboveMinCapacity) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write two times SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer, calling ExpectLength() with the correct length first. We expect - // this to result in only one chunk, because ExpectLength() allows us to - // allocate a larger first chunk than MIN_CHUNK_CAPACITY bytes. - const size_t length = 2 * SourceBuffer::MIN_CHUNK_CAPACITY; - EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->ExpectLength(length))); - CheckedAppendToBufferInChunks(10, length); - - // Verify that the iterator sees a single chunk. - CheckedAdvanceIterator(iterator, length); - - // Write one more byte; we expect to see that it triggers an allocation. - CheckedAppendToBufferLastByteForLength(length); - CheckedCompleteBuffer(iterator, 1); - - // Verify that the iterator sees the new byte and a new chunk has been - // allocated. - CheckedAdvanceIterator(iterator, 1, 2, length + 1); - CheckIteratorIsComplete(iterator, 2, length + 1); -} - -TEST_F(ImageSourceBuffer, HugeExpectLengthFails) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // ExpectLength() should fail if the length is bigger than what the - // SurfaceCache can hold, so use the SurfaceCache's maximum capacity to - // calculate what a "massive amount of data" (see below) consists of on this - // platform. - ASSERT_LT(SurfaceCache::MaximumCapacity(), SIZE_MAX); - const size_t hugeSize = SurfaceCache::MaximumCapacity() + 1; - - // Attempt to write a massive amount of data and verify that it fails. (We'd - // get a buffer overrun during the test if it succeeds, but if it succeeds - // that's the least of our problems.) - EXPECT_TRUE(NS_FAILED(mSourceBuffer->ExpectLength(hugeSize))); - EXPECT_TRUE(mSourceBuffer->IsComplete()); - CheckIteratorIsComplete(iterator, 0, 0, NS_ERROR_OUT_OF_MEMORY); -} - -TEST_F(ImageSourceBuffer, LargeAppendsAllocateOnlyOneChunk) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write two times SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer in a single Append() call. We expect this to result in only one - // chunk even though ExpectLength() wasn't called, because we should always - // allocate a new chunk large enough to store the data we have at hand. - constexpr size_t length = 2 * SourceBuffer::MIN_CHUNK_CAPACITY; - char data[length]; - GenerateData(data, sizeof(data)); - CheckedAppendToBuffer(data, length); - - // Verify that the iterator sees a single chunk. - CheckedAdvanceIterator(iterator, length); - - // Write one more byte; we expect to see that it triggers an allocation. - CheckedAppendToBufferLastByteForLength(length); - CheckedCompleteBuffer(iterator, 1); - - // Verify that the iterator sees the new byte and a new chunk has been - // allocated. - CheckedAdvanceIterator(iterator, 1, 2, length + 1); - CheckIteratorIsComplete(iterator, 2, length + 1); -} - -TEST_F(ImageSourceBuffer, LargeAppendsAllocateAtMostOneChunk) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Allocate some data we'll use below. - constexpr size_t firstWriteLength = SourceBuffer::MIN_CHUNK_CAPACITY / 2; - constexpr size_t secondWriteLength = 3 * SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = firstWriteLength + secondWriteLength; - char data[totalLength]; - GenerateData(data, sizeof(data)); - - // Write half of SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer in a single Append() call. This should fill half of the first chunk. - CheckedAppendToBuffer(data, firstWriteLength); - - // Write three times SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer in a single Append() call. We expect this to result in the first of - // the first chunk being filled and a new chunk being allocated for the - // remainder. - CheckedAppendToBuffer(data + firstWriteLength, secondWriteLength); - - // Verify that the iterator sees a MIN_CHUNK_CAPACITY-length chunk. - CheckedAdvanceIterator(iterator, SourceBuffer::MIN_CHUNK_CAPACITY); - - // Verify that the iterator sees a second chunk of the length we expect. - const size_t expectedSecondChunkLength = - totalLength - SourceBuffer::MIN_CHUNK_CAPACITY; - CheckedAdvanceIterator(iterator, expectedSecondChunkLength, 2, totalLength); - - // Write one more byte; we expect to see that it triggers an allocation. - CheckedAppendToBufferLastByteForLength(totalLength); - CheckedCompleteBuffer(iterator, 1); - - // Verify that the iterator sees the new byte and a new chunk has been - // allocated. - CheckedAdvanceIterator(iterator, 1, 3, totalLength + 1); - CheckIteratorIsComplete(iterator, 3, totalLength + 1); -} - -TEST_F(ImageSourceBuffer, CompactionHappensWhenBufferIsComplete) -{ - constexpr size_t chunkLength = SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = 2 * chunkLength; - - // Write enough data to create two chunks. - CheckedAppendToBufferInChunks(chunkLength, totalLength); - - { - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Verify that the iterator sees two chunks. - CheckedAdvanceIterator(iterator, chunkLength); - CheckedAdvanceIterator(iterator, chunkLength, 2, totalLength); - } - - // Complete the buffer, which should trigger compaction implicitly. - CheckedCompleteBuffer(); - - { - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Verify that compaction happened and there's now only one chunk. - CheckedAdvanceIterator(iterator, totalLength); - CheckIteratorIsComplete(iterator, 1, totalLength); - } -} - -TEST_F(ImageSourceBuffer, CompactionIsDelayedWhileIteratorsExist) -{ - constexpr size_t chunkLength = SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = 2 * chunkLength; - - { - SourceBufferIterator outerIterator = mSourceBuffer->Iterator(); - - { - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Write enough data to create two chunks. - CheckedAppendToBufferInChunks(chunkLength, totalLength); - CheckedCompleteBuffer(iterator, totalLength); - - // Verify that the iterator sees two chunks. Since there are live - // iterators, compaction shouldn't have happened when we completed the - // buffer. - CheckedAdvanceIterator(iterator, chunkLength); - CheckedAdvanceIterator(iterator, chunkLength, 2, totalLength); - CheckIteratorIsComplete(iterator, 2, totalLength); - } - - // Now |iterator| has been destroyed, but |outerIterator| still exists, so - // we expect no compaction to have occurred at this point. - CheckedAdvanceIterator(outerIterator, chunkLength); - CheckedAdvanceIterator(outerIterator, chunkLength, 2, totalLength); - CheckIteratorIsComplete(outerIterator, 2, totalLength); - } - - // Now all iterators have been destroyed. Since the buffer was already - // complete, we expect compaction to happen implicitly here. - - { - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Verify that compaction happened and there's now only one chunk. - CheckedAdvanceIterator(iterator, totalLength); - CheckIteratorIsComplete(iterator, 1, totalLength); - } -} - -TEST_F(ImageSourceBuffer, SourceBufferIteratorsCanBeMoved) -{ - constexpr size_t chunkLength = SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = 2 * chunkLength; - - // Write enough data to create two chunks. We create an iterator here to make - // sure that compaction doesn't happen during the test. - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - CheckedAppendToBufferInChunks(chunkLength, totalLength); - CheckedCompleteBuffer(iterator, totalLength); - - auto GetIterator = [&]{ - SourceBufferIterator lambdaIterator = mSourceBuffer->Iterator(); - CheckedAdvanceIterator(lambdaIterator, chunkLength); - return lambdaIterator; - }; - - // Move-construct |movedIterator| from the iterator returned from - // GetIterator() and check that its state is as we expect. - SourceBufferIterator movedIterator = Move(GetIterator()); - EXPECT_TRUE(movedIterator.Data()); - EXPECT_EQ(chunkLength, movedIterator.Length()); - ExpectChunkAndByteCount(movedIterator, 1, chunkLength); - - // Make sure that we can advance the iterator. - CheckedAdvanceIterator(movedIterator, chunkLength, 2, totalLength); - - // Make sure that the iterator handles completion properly. - CheckIteratorIsComplete(movedIterator, 2, totalLength); - - // Move-assign |movedIterator| from the iterator returned from - // GetIterator() and check that its state is as we expect. - movedIterator = Move(GetIterator()); - EXPECT_TRUE(movedIterator.Data()); - EXPECT_EQ(chunkLength, movedIterator.Length()); - ExpectChunkAndByteCount(movedIterator, 1, chunkLength); - - // Make sure that we can advance the iterator. - CheckedAdvanceIterator(movedIterator, chunkLength, 2, totalLength); - - // Make sure that the iterator handles completion properly. - CheckIteratorIsComplete(movedIterator, 2, totalLength); -} - -TEST_F(ImageSourceBuffer, SubchunkAdvance) -{ - constexpr size_t chunkLength = SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = 2 * chunkLength; - - // Write enough data to create two chunks. We create our iterator here to make - // sure that compaction doesn't happen during the test. - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - CheckedAppendToBufferInChunks(chunkLength, totalLength); - CheckedCompleteBuffer(iterator, totalLength); - - // Advance through the first chunk. The chunk count should not increase. - // We check that by always passing 1 for the |aChunks| parameter of - // CheckedAdvanceIteratorStateOnly(). We have to call CheckData() manually - // because the offset calculation in CheckedAdvanceIterator() assumes that - // we're advancing a chunk at a time. - size_t offset = 0; - while (offset < chunkLength) { - CheckedAdvanceIteratorStateOnly(iterator, 1, 1, chunkLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - } - - // Read the first byte of the second chunk. This is the point at which we - // can't advance within the same chunk, so the chunk count should increase. We - // check that by passing 2 for the |aChunks| parameter of - // CheckedAdvanceIteratorStateOnly(). - CheckedAdvanceIteratorStateOnly(iterator, 1, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - - // Read the rest of the second chunk. The chunk count should not increase. - while (offset < totalLength) { - CheckedAdvanceIteratorStateOnly(iterator, 1, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - } - - // Make sure we reached the end. - CheckIteratorIsComplete(iterator, 2, totalLength); -} - -TEST_F(ImageSourceBuffer, SubchunkZeroByteAdvance) -{ - constexpr size_t chunkLength = SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = 2 * chunkLength; - - // Write enough data to create two chunks. We create our iterator here to make - // sure that compaction doesn't happen during the test. - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - CheckedAppendToBufferInChunks(chunkLength, totalLength); - CheckedCompleteBuffer(iterator, totalLength); - - // Make an initial zero-length advance. Although a zero-length advance - // normally won't cause us to read a chunk from the SourceBuffer, we'll do so - // if the iterator is in the initial state to keep the invariant that - // SourceBufferIterator in the READY state always returns a non-null pointer - // from Data(). - CheckedAdvanceIteratorStateOnly(iterator, 0, 1, chunkLength, - AdvanceMode::eAdvanceByLengthExactly); - - // Advance through the first chunk. As in the |SubchunkAdvance| test, the - // chunk count should not increase. We do a zero-length advance after each - // normal advance to ensure that zero-length advances do not change the - // iterator's position or cause a new chunk to be read. - size_t offset = 0; - while (offset < chunkLength) { - CheckedAdvanceIteratorStateOnly(iterator, 1, 1, chunkLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - CheckedAdvanceIteratorStateOnly(iterator, 0, 1, chunkLength, - AdvanceMode::eAdvanceByLengthExactly); - } - - // Read the first byte of the second chunk. This is the point at which we - // can't advance within the same chunk, so the chunk count should increase. As - // before, we do a zero-length advance afterward. - CheckedAdvanceIteratorStateOnly(iterator, 1, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - CheckedAdvanceIteratorStateOnly(iterator, 0, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - - // Read the rest of the second chunk. The chunk count should not increase. As - // before, we do a zero-length advance after each normal advance. - while (offset < totalLength) { - CheckedAdvanceIteratorStateOnly(iterator, 1, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - CheckData(iterator.Data(), offset++, iterator.Length()); - CheckedAdvanceIteratorStateOnly(iterator, 0, 2, totalLength, - AdvanceMode::eAdvanceByLengthExactly); - } - - // Make sure we reached the end. - CheckIteratorIsComplete(iterator, 2, totalLength); -} - -TEST_F(ImageSourceBuffer, SubchunkZeroByteAdvanceWithNoData) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that advancing by zero bytes still makes us enter the WAITING state. - // This is because if we entered the READY state before reading any data at - // all, we'd break the invariant that SourceBufferIterator::Data() always - // returns a non-null pointer in the READY state. - auto state = iterator.AdvanceOrScheduleResume(0, mCountResumes); - EXPECT_EQ(SourceBufferIterator::WAITING, state); - - // Call Complete(). This should trigger a resume. - CheckedCompleteBuffer(); - EXPECT_EQ(1u, mCountResumes->Count()); -} - -TEST_F(ImageSourceBuffer, NullIResumable) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that we can't advance. - CheckIteratorMustWait(iterator, nullptr); - - // Append to the buffer, which would cause a resume if we had passed a - // non-null IResumable. - CheckedAppendToBuffer(mData, sizeof(mData)); - CheckedCompleteBuffer(iterator, sizeof(mData)); -} - -TEST_F(ImageSourceBuffer, AppendTriggersResume) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that we can't advance. - CheckIteratorMustWait(iterator, mCountResumes); - - // Call Append(). This should trigger a resume. - mSourceBuffer->Append(mData, sizeof(mData)); - EXPECT_EQ(1u, mCountResumes->Count()); -} - -TEST_F(ImageSourceBuffer, OnlyOneResumeTriggeredPerAppend) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that we can't advance. - CheckIteratorMustWait(iterator, mCountResumes); - - // Allocate some data we'll use below. - constexpr size_t firstWriteLength = SourceBuffer::MIN_CHUNK_CAPACITY / 2; - constexpr size_t secondWriteLength = 3 * SourceBuffer::MIN_CHUNK_CAPACITY; - constexpr size_t totalLength = firstWriteLength + secondWriteLength; - char data[totalLength]; - GenerateData(data, sizeof(data)); - - // Write half of SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer in a single Append() call. This should fill half of the first chunk. - // This should trigger a resume. - CheckedAppendToBuffer(data, firstWriteLength); - EXPECT_EQ(1u, mCountResumes->Count()); - - // Advance past the new data and wait again. - CheckedAdvanceIterator(iterator, firstWriteLength); - CheckIteratorMustWait(iterator, mCountResumes); - - // Write three times SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the - // buffer in a single Append() call. We expect this to result in the first of - // the first chunk being filled and a new chunk being allocated for the - // remainder. Even though two chunks are getting written to here, only *one* - // resume should get triggered, for a total of two in this test. - CheckedAppendToBuffer(data + firstWriteLength, secondWriteLength); - EXPECT_EQ(2u, mCountResumes->Count()); -} - -TEST_F(ImageSourceBuffer, CompleteTriggersResume) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that we can't advance. - CheckIteratorMustWait(iterator, mCountResumes); - - // Call Complete(). This should trigger a resume. - CheckedCompleteBuffer(); - EXPECT_EQ(1u, mCountResumes->Count()); -} - -TEST_F(ImageSourceBuffer, ExpectLengthDoesNotTriggerResume) -{ - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - - // Check that we can't advance. - CheckIteratorMustWait(iterator, mExpectNoResume); - - // Call ExpectLength(). If this triggers a resume, |mExpectNoResume| will - // ensure that the test fails. - mSourceBuffer->ExpectLength(1000); -} diff --git a/image/test/gtest/TestStreamingLexer.cpp b/image/test/gtest/TestStreamingLexer.cpp deleted file mode 100644 index 590b10e818..0000000000 --- a/image/test/gtest/TestStreamingLexer.cpp +++ /dev/null @@ -1,973 +0,0 @@ -/* 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 "gtest/gtest.h" - -#include "mozilla/Vector.h" -#include "StreamingLexer.h" - -using namespace mozilla; -using namespace mozilla::image; - -enum class TestState -{ - ONE, - TWO, - THREE, - UNBUFFERED, - TRUNCATED_SUCCESS, - TRUNCATED_FAILURE -}; - -void -CheckLexedData(const char* aData, - size_t aLength, - size_t aOffset, - size_t aExpectedLength) -{ - EXPECT_TRUE(aLength == aExpectedLength); - - for (size_t i = 0; i < aLength; ++i) { - EXPECT_EQ(aData[i], char(aOffset + i + 1)); - } -} - -LexerTransition -DoLex(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::To(TestState::TWO, 3); - case TestState::TWO: - CheckLexedData(aData, aLength, 3, 3); - return Transition::To(TestState::THREE, 3); - case TestState::THREE: - CheckLexedData(aData, aLength, 6, 3); - return Transition::TerminateSuccess(); - case TestState::TRUNCATED_SUCCESS: - return Transition::TerminateSuccess(); - case TestState::TRUNCATED_FAILURE: - return Transition::TerminateFailure(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithUnbuffered(TestState aState, const char* aData, size_t aLength, - Vector& aUnbufferedVector) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3); - case TestState::TWO: - CheckLexedData(aUnbufferedVector.begin(), aUnbufferedVector.length(), 3, 3); - return Transition::To(TestState::THREE, 3); - case TestState::THREE: - CheckLexedData(aData, aLength, 6, 3); - return Transition::TerminateSuccess(); - case TestState::UNBUFFERED: - EXPECT_TRUE(aLength <= 3); - EXPECT_TRUE(aUnbufferedVector.append(aData, aLength)); - return Transition::ContinueUnbuffered(TestState::UNBUFFERED); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithUnbufferedTerminate(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3); - case TestState::UNBUFFERED: - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithYield(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::ToAfterYield(TestState::TWO); - case TestState::TWO: - CheckLexedData(aData, aLength, 0, 3); - return Transition::To(TestState::THREE, 6); - case TestState::THREE: - CheckLexedData(aData, aLength, 3, 6); - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithTerminateAfterYield(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::ToAfterYield(TestState::TWO); - case TestState::TWO: - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithZeroLengthStates(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - EXPECT_TRUE(aLength == 0); - return Transition::To(TestState::TWO, 0); - case TestState::TWO: - EXPECT_TRUE(aLength == 0); - return Transition::To(TestState::THREE, 9); - case TestState::THREE: - CheckLexedData(aData, aLength, 0, 9); - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithZeroLengthStatesAtEnd(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 9); - return Transition::To(TestState::TWO, 0); - case TestState::TWO: - EXPECT_TRUE(aLength == 0); - return Transition::To(TestState::THREE, 0); - case TestState::THREE: - EXPECT_TRUE(aLength == 0); - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithZeroLengthYield(TestState aState, const char* aData, size_t aLength) -{ - switch (aState) { - case TestState::ONE: - EXPECT_EQ(0u, aLength); - return Transition::ToAfterYield(TestState::TWO); - case TestState::TWO: - EXPECT_EQ(0u, aLength); - return Transition::To(TestState::THREE, 9); - case TestState::THREE: - CheckLexedData(aData, aLength, 0, 9); - return Transition::TerminateSuccess(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithZeroLengthStatesUnbuffered(TestState aState, - const char* aData, - size_t aLength) -{ - switch (aState) { - case TestState::ONE: - EXPECT_TRUE(aLength == 0); - return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 0); - case TestState::TWO: - EXPECT_TRUE(aLength == 0); - return Transition::To(TestState::THREE, 9); - case TestState::THREE: - CheckLexedData(aData, aLength, 0, 9); - return Transition::TerminateSuccess(); - case TestState::UNBUFFERED: - ADD_FAILURE() << "Should not enter zero-length unbuffered state"; - return Transition::TerminateFailure(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -LexerTransition -DoLexWithZeroLengthStatesAfterUnbuffered(TestState aState, - const char* aData, - size_t aLength) -{ - switch (aState) { - case TestState::ONE: - EXPECT_TRUE(aLength == 0); - return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 9); - case TestState::TWO: - EXPECT_TRUE(aLength == 0); - return Transition::To(TestState::THREE, 0); - case TestState::THREE: - EXPECT_TRUE(aLength == 0); - return Transition::TerminateSuccess(); - case TestState::UNBUFFERED: - CheckLexedData(aData, aLength, 0, 9); - return Transition::ContinueUnbuffered(TestState::UNBUFFERED); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } -} - -class ImageStreamingLexer : public ::testing::Test -{ -public: - // Note that mLexer is configured to enter TerminalState::FAILURE immediately - // if the input data is truncated. We don't expect that to happen in most - // tests, so we want to detect that issue. If a test needs a different - // behavior, we create a special StreamingLexer just for that test. - ImageStreamingLexer() - : mLexer(Transition::To(TestState::ONE, 3), Transition::TerminateFailure()) - , mSourceBuffer(new SourceBuffer) - , mIterator(mSourceBuffer->Iterator()) - , mExpectNoResume(new ExpectNoResume) - , mCountResumes(new CountResumes) - { } - -protected: - void CheckTruncatedState(StreamingLexer& aLexer, - TerminalState aExpectedTerminalState, - nsresult aCompletionStatus = NS_OK) - { - for (unsigned i = 0; i < 9; ++i) { - if (i < 2) { - mSourceBuffer->Append(mData + i, 1); - } else if (i == 2) { - mSourceBuffer->Complete(aCompletionStatus); - } - - LexerResult result = aLexer.Lex(mIterator, mCountResumes, DoLex); - - if (i >= 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(aExpectedTerminalState, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(2u, mCountResumes->Count()); - } - - AutoInitializeImageLib mInit; - const char mData[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - StreamingLexer mLexer; - RefPtr mSourceBuffer; - SourceBufferIterator mIterator; - RefPtr mExpectNoResume; - RefPtr mCountResumes; -}; - -TEST_F(ImageStreamingLexer, ZeroLengthData) -{ - // Test a zero-length input. - mSourceBuffer->Complete(NS_OK); - - LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::FAILURE, result.as()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthDataUnbuffered) -{ - // Test a zero-length input. - mSourceBuffer->Complete(NS_OK); - - // Create a special StreamingLexer for this test because we want the first - // state to be unbuffered. - StreamingLexer lexer(Transition::ToUnbuffered(TestState::ONE, - TestState::UNBUFFERED, - sizeof(mData)), - Transition::TerminateFailure()); - - LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::FAILURE, result.as()); -} - -TEST_F(ImageStreamingLexer, StartWithTerminal) -{ - // Create a special StreamingLexer for this test because we want the first - // state to be a terminal state. This doesn't really make sense, but we should - // handle it. - StreamingLexer lexer(Transition::TerminateSuccess(), - Transition::TerminateFailure()); - LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, SingleChunk) -{ - // Test delivering all the data at once. - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, SingleChunkWithUnbuffered) -{ - Vector unbufferedVector; - - // Test delivering all the data at once. - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - LexerResult result = - mLexer.Lex(mIterator, mExpectNoResume, - [&](TestState aState, const char* aData, size_t aLength) { - return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector); - }); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, SingleChunkWithYield) -{ - // Test delivering all the data at once. - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - - result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield); - ASSERT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, ChunkPerState) -{ - // Test delivering in perfectly-sized chunks, one per state. - for (unsigned i = 0; i < 3; ++i) { - mSourceBuffer->Append(mData + 3 * i, 3); - LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex); - - if (i == 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(2u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbuffered) -{ - Vector unbufferedVector; - - // Test delivering in perfectly-sized chunks, one per state. - for (unsigned i = 0; i < 3; ++i) { - mSourceBuffer->Append(mData + 3 * i, 3); - LexerResult result = - mLexer.Lex(mIterator, mCountResumes, - [&](TestState aState, const char* aData, size_t aLength) { - return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector); - }); - - if (i == 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(2u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, ChunkPerStateWithYield) -{ - // Test delivering in perfectly-sized chunks, one per state. - mSourceBuffer->Append(mData, 3); - LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield); - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - - result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield); - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - - mSourceBuffer->Append(mData + 3, 6); - result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - - EXPECT_EQ(1u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbufferedYield) -{ - size_t unbufferedCallCount = 0; - Vector unbufferedVector; - auto lexerFunc = [&](TestState aState, const char* aData, size_t aLength) - -> LexerTransition { - switch (aState) { - case TestState::ONE: - CheckLexedData(aData, aLength, 0, 3); - return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3); - case TestState::TWO: - CheckLexedData(unbufferedVector.begin(), unbufferedVector.length(), 3, 3); - return Transition::To(TestState::THREE, 3); - case TestState::THREE: - CheckLexedData(aData, aLength, 6, 3); - return Transition::TerminateSuccess(); - case TestState::UNBUFFERED: - switch (unbufferedCallCount) { - case 0: - CheckLexedData(aData, aLength, 3, 3); - EXPECT_TRUE(unbufferedVector.append(aData, 2)); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 2 bytes. - return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 2); - - case 1: - CheckLexedData(aData, aLength, 5, 1); - EXPECT_TRUE(unbufferedVector.append(aData, 1)); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 1 byte. - // We should end up in the TWO state. - return Transition::ContinueUnbuffered(TestState::UNBUFFERED); - } - ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED"; - return Transition::TerminateFailure(); - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } - }; - - // Test delivering in perfectly-sized chunks, one per state. - for (unsigned i = 0; i < 3; ++i) { - mSourceBuffer->Append(mData + 3 * i, 3); - LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc); - - switch (i) { - case 0: - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - EXPECT_EQ(0u, unbufferedCallCount); - break; - - case 1: - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - EXPECT_EQ(1u, unbufferedCallCount); - - result = mLexer.Lex(mIterator, mCountResumes, lexerFunc); - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - EXPECT_EQ(2u, unbufferedCallCount); - break; - - case 2: - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - break; - } - } - - EXPECT_EQ(2u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); - - LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, OneByteChunks) -{ - // Test delivering in one byte chunks. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex); - - if (i == 8) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(8u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, OneByteChunksWithUnbuffered) -{ - Vector unbufferedVector; - - // Test delivering in one byte chunks. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = - mLexer.Lex(mIterator, mCountResumes, - [&](TestState aState, const char* aData, size_t aLength) { - return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector); - }); - - if (i == 8) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(8u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, OneByteChunksWithYield) -{ - // Test delivering in one byte chunks. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield); - - switch (i) { - case 2: - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - - result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield); - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - break; - - case 8: - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - break; - - default: - EXPECT_TRUE(i < 9); - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - EXPECT_EQ(8u, mCountResumes->Count()); - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, ZeroLengthState) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Create a special StreamingLexer for this test because we want the first - // state to be zero length. - StreamingLexer lexer(Transition::To(TestState::ONE, 0), - Transition::TerminateFailure()); - - LexerResult result = - lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStates); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthStatesAtEnd) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Create a special StreamingLexer for this test because we want the first - // state to consume the full input. - StreamingLexer lexer(Transition::To(TestState::ONE, 9), - Transition::TerminateFailure()); - - LexerResult result = - lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesAtEnd); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthStateWithYield) -{ - // Create a special StreamingLexer for this test because we want the first - // state to be zero length. - StreamingLexer lexer(Transition::To(TestState::ONE, 0), - Transition::TerminateFailure()); - - mSourceBuffer->Append(mData, 3); - LexerResult result = - lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - - result = lexer.Lex(mIterator, mCountResumes, DoLexWithZeroLengthYield); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - - mSourceBuffer->Append(mData + 3, sizeof(mData) - 3); - mSourceBuffer->Complete(NS_OK); - result = lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield); - ASSERT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - EXPECT_EQ(1u, mCountResumes->Count()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbuffered) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Create a special StreamingLexer for this test because we want the first - // state to be both zero length and unbuffered. - StreamingLexer lexer(Transition::ToUnbuffered(TestState::ONE, - TestState::UNBUFFERED, - 0), - Transition::TerminateFailure()); - - LexerResult result = - lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesUnbuffered); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthStateAfterUnbuffered) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Create a special StreamingLexer for this test because we want the first - // state to be zero length. - StreamingLexer lexer(Transition::To(TestState::ONE, 0), - Transition::TerminateFailure()); - - LexerResult result = - lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesAfterUnbuffered); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbufferedYield) -{ - size_t unbufferedCallCount = 0; - auto lexerFunc = [&](TestState aState, const char* aData, size_t aLength) - -> LexerTransition { - switch (aState) { - case TestState::ONE: - EXPECT_EQ(0u, aLength); - return Transition::TerminateSuccess(); - - case TestState::UNBUFFERED: - switch (unbufferedCallCount) { - case 0: - CheckLexedData(aData, aLength, 0, 3); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 0 bytes. - return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 0); - - case 1: - CheckLexedData(aData, aLength, 0, 3); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 2 bytes. - return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 2); - - case 2: - EXPECT_EQ(1u, aLength); - CheckLexedData(aData, aLength, 2, 1); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 1 bytes. - return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 1); - - case 3: - CheckLexedData(aData, aLength, 3, 6); - unbufferedCallCount++; - - // Continue after yield, telling StreamingLexer we consumed 6 bytes. - // We should transition to TestState::ONE when we return from the - // yield. - return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 6); - } - - ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED"; - return Transition::TerminateFailure(); - - default: - MOZ_CRASH("Unexpected or unhandled TestState"); - } - }; - - // Create a special StreamingLexer for this test because we want the first - // state to be unbuffered. - StreamingLexer lexer(Transition::ToUnbuffered(TestState::ONE, - TestState::UNBUFFERED, - sizeof(mData)), - Transition::TerminateFailure()); - - mSourceBuffer->Append(mData, 3); - LexerResult result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - EXPECT_EQ(1u, unbufferedCallCount); - - result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - EXPECT_EQ(2u, unbufferedCallCount); - - result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - EXPECT_EQ(3u, unbufferedCallCount); - - result = lexer.Lex(mIterator, mCountResumes, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - EXPECT_EQ(3u, unbufferedCallCount); - - mSourceBuffer->Append(mData + 3, 6); - mSourceBuffer->Complete(NS_OK); - EXPECT_EQ(1u, mCountResumes->Count()); - result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - EXPECT_EQ(4u, unbufferedCallCount); - - result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc); - ASSERT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, TerminateSuccess) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Test that Terminate is "sticky". - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - LexerResult result = - mLexer.Lex(iterator, mExpectNoResume, - [&](TestState aState, const char* aData, size_t aLength) { - EXPECT_TRUE(aState == TestState::ONE); - return Transition::TerminateSuccess(); - }); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - - SourceBufferIterator iterator2 = mSourceBuffer->Iterator(); - result = - mLexer.Lex(iterator2, mExpectNoResume, - [&](TestState aState, const char* aData, size_t aLength) { - EXPECT_TRUE(false); // Shouldn't get here. - return Transition::TerminateFailure(); - }); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); -} - -TEST_F(ImageStreamingLexer, TerminateFailure) -{ - mSourceBuffer->Append(mData, sizeof(mData)); - mSourceBuffer->Complete(NS_OK); - - // Test that Terminate is "sticky". - SourceBufferIterator iterator = mSourceBuffer->Iterator(); - LexerResult result = - mLexer.Lex(iterator, mExpectNoResume, - [&](TestState aState, const char* aData, size_t aLength) { - EXPECT_TRUE(aState == TestState::ONE); - return Transition::TerminateFailure(); - }); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::FAILURE, result.as()); - - SourceBufferIterator iterator2 = mSourceBuffer->Iterator(); - result = - mLexer.Lex(iterator2, mExpectNoResume, - [&](TestState aState, const char* aData, size_t aLength) { - EXPECT_TRUE(false); // Shouldn't get here. - return Transition::TerminateFailure(); - }); - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::FAILURE, result.as()); -} - -TEST_F(ImageStreamingLexer, TerminateUnbuffered) -{ - // Test that Terminate works during an unbuffered read. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = - mLexer.Lex(mIterator, mCountResumes, DoLexWithUnbufferedTerminate); - - if (i > 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - // We expect 3 resumes because TestState::ONE consumes 3 bytes and then - // transitions to TestState::UNBUFFERED, which calls TerminateSuccess() as - // soon as it receives a single byte. That's four bytes total, which are - // delivered one at a time, requiring 3 resumes. - EXPECT_EQ(3u, mCountResumes->Count()); - - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, TerminateAfterYield) -{ - // Test that Terminate works after yielding. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = - mLexer.Lex(mIterator, mCountResumes, DoLexWithTerminateAfterYield); - - if (i > 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else if (i == 2) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - // We expect 2 resumes because TestState::ONE consumes 3 bytes and then - // yields. When the lexer resumes at TestState::TWO, which receives the same 3 - // bytes, TerminateSuccess() gets called immediately. That's three bytes - // total, which are delivered one at a time, requiring 2 resumes. - EXPECT_EQ(2u, mCountResumes->Count()); - - mSourceBuffer->Complete(NS_OK); -} - -TEST_F(ImageStreamingLexer, SourceBufferImmediateComplete) -{ - // Test calling SourceBuffer::Complete() without appending any data. This - // causes the SourceBuffer to automatically have a failing completion status, - // no matter what you pass, so we expect TerminalState::FAILURE below. - mSourceBuffer->Complete(NS_OK); - - LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex); - - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::FAILURE, result.as()); -} - -TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateSuccess) -{ - // Test that using a terminal state (in this case TerminalState::SUCCESS) as a - // truncated state works. - StreamingLexer lexer(Transition::To(TestState::ONE, 3), - Transition::TerminateSuccess()); - - CheckTruncatedState(lexer, TerminalState::SUCCESS); -} - -TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateFailure) -{ - // Test that using a terminal state (in this case TerminalState::FAILURE) as a - // truncated state works. - StreamingLexer lexer(Transition::To(TestState::ONE, 3), - Transition::TerminateFailure()); - - CheckTruncatedState(lexer, TerminalState::FAILURE); -} - -TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningSuccess) -{ - // Test that a truncated state that returns TerminalState::SUCCESS works. When - // |lexer| discovers that the data is truncated, it invokes the - // TRUNCATED_SUCCESS state, which returns TerminalState::SUCCESS. - // CheckTruncatedState() verifies that this happens. - StreamingLexer lexer(Transition::To(TestState::ONE, 3), - Transition::To(TestState::TRUNCATED_SUCCESS, 0)); - - CheckTruncatedState(lexer, TerminalState::SUCCESS); -} - -TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningFailure) -{ - // Test that a truncated state that returns TerminalState::FAILURE works. When - // |lexer| discovers that the data is truncated, it invokes the - // TRUNCATED_FAILURE state, which returns TerminalState::FAILURE. - // CheckTruncatedState() verifies that this happens. - StreamingLexer lexer(Transition::To(TestState::ONE, 3), - Transition::To(TestState::TRUNCATED_FAILURE, 0)); - - CheckTruncatedState(lexer, TerminalState::FAILURE); -} - -TEST_F(ImageStreamingLexer, SourceBufferTruncatedFailingCompleteStatus) -{ - // Test that calling SourceBuffer::Complete() with a failing status results in - // an immediate TerminalState::FAILURE result. (Note that |lexer|'s truncated - // state is TerminalState::SUCCESS, so if we ignore the failing status, the - // test will fail.) - StreamingLexer lexer(Transition::To(TestState::ONE, 3), - Transition::TerminateSuccess()); - - CheckTruncatedState(lexer, TerminalState::FAILURE, NS_ERROR_FAILURE); -} - -TEST_F(ImageStreamingLexer, NoSourceBufferResumable) -{ - // Test delivering in one byte chunks with no IResumable. - for (unsigned i = 0; i < 9; ++i) { - mSourceBuffer->Append(mData + i, 1); - LexerResult result = mLexer.Lex(mIterator, nullptr, DoLex); - - if (i == 8) { - EXPECT_TRUE(result.is()); - EXPECT_EQ(TerminalState::SUCCESS, result.as()); - } else { - EXPECT_TRUE(result.is()); - EXPECT_EQ(Yield::NEED_MORE_DATA, result.as()); - } - } - - mSourceBuffer->Complete(NS_OK); -} diff --git a/image/test/gtest/TestSurfacePipeIntegration.cpp b/image/test/gtest/TestSurfacePipeIntegration.cpp deleted file mode 100644 index 27138a3ee6..0000000000 --- a/image/test/gtest/TestSurfacePipeIntegration.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -namespace mozilla { -namespace image { - -class TestSurfacePipeFactory -{ -public: - static SurfacePipe SimpleSurfacePipe() - { - SurfacePipe pipe; - return Move(pipe); - } - - template - static SurfacePipe SurfacePipeFromPipeline(T&& aPipeline) - { - return SurfacePipe { Move(aPipeline) }; - } - -private: - TestSurfacePipeFactory() { } -}; - -} // namespace image -} // namespace mozilla - -void -CheckSurfacePipeMethodResults(SurfacePipe* aPipe, - Decoder* aDecoder, - const IntRect& aRect = IntRect(0, 0, 100, 100)) -{ - // Check that the pipeline ended up in the state we expect. Note that we're - // explicitly testing the SurfacePipe versions of these methods, so we don't - // want to use AssertCorrectPipelineFinalState() here. - EXPECT_TRUE(aPipe->IsSurfaceFinished()); - Maybe invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); - - // Check the generated image. - CheckGeneratedImage(aDecoder, aRect); - - // Reset and clear the image before the next test. - aPipe->ResetToFirstRow(); - EXPECT_FALSE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - uint32_t count = 0; - auto result = aPipe->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Transparent().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - EXPECT_TRUE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); - - aPipe->ResetToFirstRow(); - EXPECT_FALSE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); -} - -void -CheckPalettedSurfacePipeMethodResults(SurfacePipe* aPipe, - Decoder* aDecoder, - const IntRect& aRect - = IntRect(0, 0, 100, 100)) -{ - // Check that the pipeline ended up in the state we expect. Note that we're - // explicitly testing the SurfacePipe versions of these methods, so we don't - // want to use AssertCorrectPipelineFinalState() here. - EXPECT_TRUE(aPipe->IsSurfaceFinished()); - Maybe invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); - - // Check the generated image. - CheckGeneratedPalettedImage(aDecoder, aRect); - - // Reset and clear the image before the next test. - aPipe->ResetToFirstRow(); - EXPECT_FALSE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - uint32_t count = 0; - auto result = aPipe->WritePixels([&]() { - ++count; - return AsVariant(uint8_t(0)); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - EXPECT_TRUE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); - - aPipe->ResetToFirstRow(); - EXPECT_FALSE(aPipe->IsSurfaceFinished()); - invalidRect = aPipe->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); -} - -class ImageSurfacePipeIntegration : public ::testing::Test -{ -protected: - AutoInitializeImageLib mInit; -}; - -TEST_F(ImageSurfacePipeIntegration, SurfacePipe) -{ - // Test that SurfacePipe objects can be initialized and move constructed. - SurfacePipe pipe = TestSurfacePipeFactory::SimpleSurfacePipe(); - - // Test that SurfacePipe objects can be move assigned. - pipe = TestSurfacePipeFactory::SimpleSurfacePipe(); - - // Test that SurfacePipe objects can be initialized with a pipeline. - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - auto sink = MakeUnique(); - nsresult rv = - sink->Configure(SurfaceConfig { decoder, IntSize(100, 100), - SurfaceFormat::B8G8R8A8, false }); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink); - - // Test that WritePixels() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - auto result = pipe.WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - CheckSurfacePipeMethodResults(&pipe, decoder); - } - - // Create a buffer the same size as one row of the surface, containing all - // green pixels. We'll use this for the WriteBuffer() tests. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = BGRAColor::Green().AsPixel(); - } - - // Test that WriteBuffer() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteBuffer(buffer); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckSurfacePipeMethodResults(&pipe, decoder); - } - - // Test that the 3 argument version of WriteBuffer() gets passed through to - // the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteBuffer(buffer, 0, 100); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckSurfacePipeMethodResults(&pipe, decoder); - } - - // Test that WriteEmptyRow() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteEmptyRow(); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckSurfacePipeMethodResults(&pipe, decoder, IntRect(0, 0, 0, 0)); - } - - // Mark the frame as finished so we don't get an assertion. - RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef(); - currentFrame->Finish(); -} - -TEST_F(ImageSurfacePipeIntegration, PalettedSurfacePipe) -{ - // Create a SurfacePipe containing a PalettedSurfaceSink. - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - auto sink = MakeUnique(); - nsresult rv = - sink->Configure(PalettedSurfaceConfig { decoder, IntSize(100, 100), - IntRect(0, 0, 100, 100), - SurfaceFormat::B8G8R8A8, - 8, false }); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - - SurfacePipe pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink); - - // Test that WritePixels() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - auto result = pipe.WritePixels([&]() { - ++count; - return AsVariant(uint8_t(255)); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - CheckPalettedSurfacePipeMethodResults(&pipe, decoder); - } - - // Create a buffer the same size as one row of the surface, containing all - // 255 pixels. We'll use this for the WriteBuffer() tests. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 255; - } - - // Test that WriteBuffer() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteBuffer(buffer); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckPalettedSurfacePipeMethodResults(&pipe, decoder); - } - - // Test that the 3 argument version of WriteBuffer() gets passed through to - // the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteBuffer(buffer, 0, 100); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckPalettedSurfacePipeMethodResults(&pipe, decoder); - } - - // Test that WriteEmptyRow() gets passed through to the underlying pipeline. - { - uint32_t count = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = pipe.WriteEmptyRow(); - ++count; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - CheckPalettedSurfacePipeMethodResults(&pipe, decoder, IntRect(0, 0, 0, 0)); - } - - // Mark the frame as finished so we don't get an assertion. - RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef(); - currentFrame->Finish(); -} - -TEST_F(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 25, 25))); - }; - - WithFilterPipeline(decoder, test, - DeinterlacingConfig { /* mProgressiveDisplay = */ true }, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(25, 25), - SurfaceFormat::B8G8R8A8, false }); -} - -TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixels) -{ - // This test case uses a frame rect that extends beyond the borders of the - // image to the bottom and to the right. It looks roughly like this (with the - // box made of '#'s representing the frame rect): - // - // +------------+ - // + + - // + +------------+ - // + +############+ - // +------+############+ - // +############+ - // +------------+ - - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // Note that aInputWriteRect is 100x50 because RemoveFrameRectFilter ignores - // trailing rows that don't show up in the output. (Leading rows unfortunately - // can't be ignored.) So the action of the pipeline is as follows: - // - // (1) RemoveFrameRectFilter reads a 100x50 region of the input. - // (aInputWriteRect captures this fact.) The remaining 50 rows are ignored - // because they extend off the bottom of the image due to the frame rect's - // (50, 50) offset. The 50 columns on the right also don't end up in the - // output, so ultimately only a 50x50 region in the output contains data - // from the input. The filter's output is not 50x50, though, but 100x100, - // because what RemoveFrameRectFilter does is introduce blank rows or - // columns as necessary to transform an image that needs a frame rect into - // an image that doesn't. - // - // (2) DownscalingFilter reads the output of RemoveFrameRectFilter (100x100) - // and downscales it to 20x20. - // - // (3) The surface owned by SurfaceSink logically has only a 10x10 region - // region in it that's non-blank; this is the downscaled version of the - // 50x50 region discussed in (1). (aOutputWriteRect captures this fact.) - // Some fuzz, as usual, is necessary when dealing with Lanczos downscaling. - - auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 50)), - /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), - /* aFuzz = */ 0x33); - }; - - WithFilterPipeline(decoder, test, - RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(20, 20), - SurfaceFormat::B8G8R8A8, false }); -} - -TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels) -{ - // This test case uses a frame rect that extends beyond the borders of the - // image to the top and to the left. It looks roughly like this (with the - // box made of '#'s representing the frame rect): - // - // +------------+ - // +############+ - // +############+------+ - // +############+ + - // +------------+ + - // + + - // +------------+ - - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)), - /* aOutputWriteRect = */ Some(IntRect(0, 0, 10, 10)), - /* aFuzz = */ 0x21); - }; - - WithFilterPipeline(decoder, test, - RemoveFrameRectConfig { IntRect(-50, -50, 100, 100) }, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(20, 20), - SurfaceFormat::B8G8R8A8, false }); -} - -TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // Note that aInputRect is the full 100x100 size even though - // RemoveFrameRectFilter is part of this pipeline, because deinterlacing - // requires reading every row. - - auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), - /* aOutputWriteRect = */ Some(IntRect(50, 50, 50, 50))); - }; - - WithFilterPipeline(decoder, test, - DeinterlacingConfig { /* mProgressiveDisplay = */ true }, - RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, - SurfaceConfig { decoder, IntSize(100, 100), - SurfaceFormat::B8G8R8A8, false }); -} - -TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { - CheckWritePixels(aDecoder, aFilter, - /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), - /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), - /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), - /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), - /* aFuzz = */ 33); - }; - - WithFilterPipeline(decoder, test, - DeinterlacingConfig { /* mProgressiveDisplay = */ true }, - RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(20, 20), - SurfaceFormat::B8G8R8A8, false }); -} - -TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // This is an invalid pipeline for paletted images, so configuration should - // fail. - AssertConfiguringPipelineFails(decoder, - RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, IntSize(100, 100), - IntRect(0, 0, 50, 50), - SurfaceFormat::B8G8R8A8, 8, - false }); -} - -TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // This is an invalid pipeline for paletted images, so configuration should - // fail. - AssertConfiguringPipelineFails(decoder, - DeinterlacingConfig { /* mProgressiveDisplay = */ true}, - DownscalingConfig { IntSize(100, 100), - SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, IntSize(100, 100), - IntRect(0, 0, 20, 20), - SurfaceFormat::B8G8R8A8, 8, - false }); -} - -TEST_F(ImageSurfacePipeIntegration, ConfiguringHugeDeinterlacingBufferFails) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - // When DownscalingFilter is used, we may succeed in allocating an output - // surface for huge images, because we only need to store the scaled-down - // version of the image. However, regardless of downscaling, - // DeinterlacingFilter needs to allocate a buffer as large as the size of the - // input. This can cause OOMs on operating systems that allow overcommit. This - // test makes sure that we reject such allocations. - AssertConfiguringPipelineFails(decoder, - DeinterlacingConfig { /* mProgressiveDisplay = */ true}, - DownscalingConfig { IntSize(60000, 60000), - SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, IntSize(600, 600), - SurfaceFormat::B8G8R8A8, false }); -} diff --git a/image/test/gtest/TestSurfaceSink.cpp b/image/test/gtest/TestSurfaceSink.cpp deleted file mode 100644 index 3a1c74d12e..0000000000 --- a/image/test/gtest/TestSurfaceSink.cpp +++ /dev/null @@ -1,1491 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" - -#include "mozilla/gfx/2D.h" -#include "Common.h" -#include "Decoder.h" -#include "DecoderFactory.h" -#include "SourceBuffer.h" -#include "SurfacePipe.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::image; - -enum class Orient -{ - NORMAL, - FLIP_VERTICALLY -}; - -template void -WithSurfaceSink(Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - const bool flipVertically = Orientation == Orient::FLIP_VERTICALLY; - - WithFilterPipeline(decoder, Forward(aFunc), - SurfaceConfig { decoder, IntSize(100, 100), - SurfaceFormat::B8G8R8A8, flipVertically }); -} - -template void -WithPalettedSurfaceSink(const IntRect& aFrameRect, Func aFunc) -{ - RefPtr decoder = CreateTrivialDecoder(); - ASSERT_TRUE(decoder != nullptr); - - WithFilterPipeline(decoder, Forward(aFunc), - PalettedSurfaceConfig { decoder, IntSize(100, 100), - aFrameRect, SurfaceFormat::B8G8R8A8, - 8, false }); -} - -void -ResetForNextPass(SurfaceFilter* aSink) -{ - aSink->ResetToFirstRow(); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); -} - -template void -DoCheckIterativeWrite(SurfaceFilter* aSink, - WriteFunc aWriteFunc, - CheckFunc aCheckFunc) -{ - // Write the buffer to successive rows until every row of the surface - // has been written. - uint32_t row = 0; - WriteState result = WriteState::NEED_MORE_DATA; - while (result == WriteState::NEED_MORE_DATA) { - result = aWriteFunc(row); - ++row; - } - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, row); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Check that the generated image is correct. - aCheckFunc(); -} - -template void -CheckIterativeWrite(Decoder* aDecoder, - SurfaceSink* aSink, - const IntRect& aOutputRect, - WriteFunc aWriteFunc) -{ - // Ignore the row passed to WriteFunc, since no callers use it. - auto writeFunc = [&](uint32_t) { - return aWriteFunc(); - }; - - DoCheckIterativeWrite(aSink, writeFunc, [&]{ - CheckGeneratedImage(aDecoder, aOutputRect); - }); -} - -template void -CheckPalettedIterativeWrite(Decoder* aDecoder, - PalettedSurfaceSink* aSink, - const IntRect& aOutputRect, - WriteFunc aWriteFunc) -{ - // Ignore the row passed to WriteFunc, since no callers use it. - auto writeFunc = [&](uint32_t) { - return aWriteFunc(); - }; - - DoCheckIterativeWrite(aSink, writeFunc, [&]{ - CheckGeneratedPalettedImage(aDecoder, aOutputRect); - }); -} - -TEST(ImageSurfaceSink, NullSurfaceSink) -{ - // Create the NullSurfaceSink. - NullSurfaceSink sink; - nsresult rv = sink.Configure(NullSurfaceConfig { }); - ASSERT_TRUE(NS_SUCCEEDED(rv)); - EXPECT_TRUE(!sink.IsValidPalettedPipe()); - - // Ensure that we can't write anything. - bool gotCalled = false; - auto result = sink.WritePixels([&]() { - gotCalled = true; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_FALSE(gotCalled); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(sink.IsSurfaceFinished()); - Maybe invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - uint32_t source = BGRAColor::Red().AsPixel(); - result = sink.WriteBuffer(&source); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - result = sink.WriteBuffer(&source, 0, 1); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - result = sink.WriteEmptyRow(); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - result = sink.WriteUnsafeComputedRow([&](uint32_t* aRow, - uint32_t aLength) { - gotCalled = true; - for (uint32_t col = 0; col < aLength; ++col, ++aRow) { - *aRow = BGRAColor::Red().AsPixel(); - } - }); - EXPECT_FALSE(gotCalled); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Attempt to advance to the next row and make sure nothing changes. - sink.AdvanceRow(); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Attempt to advance to the next pass and make sure nothing changes. - sink.ResetToFirstRow(); - EXPECT_TRUE(sink.IsSurfaceFinished()); - invalidRect = sink.TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); -} - -TEST(ImageSurfaceSink, SurfaceSinkInitialization) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Check initial state. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the surface is zero-initialized. We verify this by calling - // CheckGeneratedImage() and telling it that we didn't write to the surface - // anyway (i.e., we wrote to the empty rect); it will then expect the entire - // surface to be transparent, which is what it should be if it was - // zero-initialied. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 0, 0)); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWritePixels) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - CheckWritePixels(aDecoder, aSink); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWritePixelsFinish) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Write nothing into the surface; just finish immediately. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - count++; - return AsVariant(WriteState::FINISHED); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(1u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixels([&]() { - count++; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Transparent())); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWritePixelsEarlyExit) -{ - auto checkEarlyExit = - [](Decoder* aDecoder, SurfaceSink* aSink, WriteState aState) { - // Write half a row of green pixels and then exit early with |aState|. If - // the lambda keeps getting called, we'll write red pixels, which will cause - // the test to fail. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(aState); - } - return count++ < 50 ? AsVariant(BGRAColor::Green().AsPixel()) - : AsVariant(BGRAColor::Red().AsPixel()); - }); - - EXPECT_EQ(aState, result); - EXPECT_EQ(50u, count); - CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1)); - - if (aState != WriteState::FINISHED) { - // We should still be able to write more at this point. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Verify that we can resume writing. We'll finish up the same row. - count = 0; - result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1)); - - return; - } - - // We should've finished the surface at this point. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixels([&]{ - count++; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1)); - }; - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::NEED_MORE_DATA); - }); - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FAILURE); - }); - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FINISHED); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Write the first 99 rows of our 100x100 surface and verify that even - // though our lambda will yield pixels forever, only one row is written per - // call to WritePixelsToRow(). - for (int row = 0; row < 99; ++row) { - uint32_t count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(100u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect); - - CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, row + 1)); - } - - // Write the final line, which should finish the surface. - uint32_t count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - - // Note that the final invalid rect we expect here is only the last row; - // that's because we called TakeInvalidRect() repeatedly in the loop above. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 99, 100, 1), - IntRect(0, 99, 100, 1)); - - // Check that the generated image is correct. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixelsToRow([&]{ - count++; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 100)); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWritePixelsToRowEarlyExit) -{ - auto checkEarlyExit = - [](Decoder* aDecoder, SurfaceSink* aSink, WriteState aState) { - // Write half a row of green pixels and then exit early with |aState|. If - // the lambda keeps getting called, we'll write red pixels, which will cause - // the test to fail. - uint32_t count = 0; - auto result = aSink->WritePixelsToRow([&]() -> NextPixel { - if (count == 50) { - return AsVariant(aState); - } - return count++ < 50 ? AsVariant(BGRAColor::Green().AsPixel()) - : AsVariant(BGRAColor::Red().AsPixel()); - }); - - EXPECT_EQ(aState, result); - EXPECT_EQ(50u, count); - CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1)); - - if (aState != WriteState::FINISHED) { - // We should still be able to write more at this point. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Verify that we can resume the same row and still stop at the end. - count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1)); - - return; - } - - // We should've finished the surface at this point. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixelsToRow([&]{ - count++; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1)); - }; - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::NEED_MORE_DATA); - }); - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FAILURE); - }); - - WithSurfaceSink([&](Decoder* aDecoder, SurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FINISHED); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteBuffer) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Create a green buffer the same size as one row of the surface (which is 100x100), - // containing 60 pixels of green in the middle and 20 transparent pixels on - // either side. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 20 <= i && i < 80 ? BGRAColor::Green().AsPixel() - : BGRAColor::Transparent().AsPixel(); - } - - // Write the buffer to every row of the surface and check that the generated - // image is correct. - CheckIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{ - return aSink->WriteBuffer(buffer); - }); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Create a buffer the same size as one row of the surface, containing all - // green pixels. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = BGRAColor::Green().AsPixel(); - } - - // Write the buffer to the middle 60 pixels of every row of the surface and - // check that the generated image is correct. - CheckIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{ - return aSink->WriteBuffer(buffer, 20, 60); - }); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRowStartColOverflow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Create a buffer the same size as one row of the surface, containing all - // green pixels. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = BGRAColor::Green().AsPixel(); - } - - { - // Write the buffer to successive rows until every row of the surface - // has been written. We place the start column beyond the end of the row, - // which will prevent us from writing anything, so we check that the - // generated image is entirely transparent. - CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteBuffer(buffer, 100, 100); - }); - } - - ResetForNextPass(aSink); - - { - // Write the buffer to successive rows until every row of the surface - // has been written. We use column 50 as the start column, but we still - // write the buffer, which means we overflow the right edge of the surface - // by 50 pixels. We check that the left half of the generated image is - // transparent and the right half is green. - CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteBuffer(buffer, 50, 100); - }); - } - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRowBufferOverflow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Create a buffer twice as large as a row of the surface. The first half - // (which is as large as a row of the image) will contain green pixels, - // while the second half will contain red pixels. - uint32_t buffer[200]; - for (int i = 0; i < 200; ++i) { - buffer[i] = i < 100 ? BGRAColor::Green().AsPixel() - : BGRAColor::Red().AsPixel(); - } - - { - // Write the buffer to successive rows until every row of the surface has - // been written. The buffer extends 100 pixels to the right of a row of - // the surface, but bounds checking will prevent us from overflowing the - // buffer. We check that the generated image is entirely green since the - // pixels on the right side of the buffer shouldn't have been written to - // the surface. - CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 100, 100), [&]{ - return aSink->WriteBuffer(buffer, 0, 200); - }); - } - - ResetForNextPass(aSink); - - { - // Write from the buffer to the middle of each row of the surface. That - // means that the left side of each row should be transparent, since we - // didn't write anything there. A buffer overflow would cause us to write - // buffer contents into the left side of each row. We check that the - // generated image is transparent on the left side and green on the right. - CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteBuffer(buffer, 50, 200); - }); - } - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteBufferFromNullSource) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Calling WriteBuffer() with a null pointer should fail without making any - // changes to the surface. - uint32_t* nullBuffer = nullptr; - WriteState result = aSink->WriteBuffer(nullBuffer); - - EXPECT_EQ(WriteState::FAILURE, result); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that nothing got written to the surface. - CheckGeneratedImage(aDecoder, IntRect(0, 0, 0, 0)); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteEmptyRow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - { - // Write an empty row to each row of the surface. We check that the - // generated image is entirely transparent. - CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteEmptyRow(); - }); - } - - ResetForNextPass(aSink); - - { - // Write a partial row before we begin calling WriteEmptyRow(). We check - // that the generated image is entirely transparent, which is to be - // expected since WriteEmptyRow() overwrites the current row even if some - // data has already been written to it. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteEmptyRow(); - }); - } - - ResetForNextPass(aSink); - - { - // Create a buffer the same size as one row of the surface, containing all - // green pixels. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = BGRAColor::Green().AsPixel(); - } - - // Write an empty row to the middle 60 rows of the surface. The first 20 - // and last 20 rows will be green. (We need to use DoCheckIterativeWrite() - // here because we need a custom function to check the output, since it - // can't be described by a simple rect.) - auto writeFunc = [&](uint32_t aRow) { - if (aRow < 20 || aRow >= 80) { - return aSink->WriteBuffer(buffer); - } else { - return aSink->WriteEmptyRow(); - } - }; - - auto checkFunc = [&]{ - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 20, BGRAColor::Green())); - EXPECT_TRUE(RowsAreSolidColor(surface, 20, 60, BGRAColor::Transparent())); - EXPECT_TRUE(RowsAreSolidColor(surface, 80, 20, BGRAColor::Green())); - }; - - DoCheckIterativeWrite(aSink, writeFunc, checkFunc); - } - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkWriteUnsafeComputedRow) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - // Create a green buffer the same size as one row of the surface. - uint32_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = BGRAColor::Green().AsPixel(); - } - - // Write the buffer to successive rows until every row of the surface - // has been written. We only write to the right half of each row, so we - // check that the left side of the generated image is transparent and the - // right side is green. - CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteUnsafeComputedRow([&](uint32_t* aRow, - uint32_t aLength) { - EXPECT_EQ(100u, aLength ); - memcpy(aRow + 50, buffer, 50 * sizeof(uint32_t)); - }); - }); - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - { - // Fill the image with a first pass of red. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); - } - - { - ResetForNextPass(aSink); - - // Check that the generated image is still the first pass image. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); - } - - { - // Fill the image with a second pass of green. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); - } - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkInvalidRect) -{ - WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { - { - // Write one row. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 100) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(100u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we have the right invalid rect. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect); - } - - { - // Write eight rows. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 100 * 8) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(100u * 8u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we have the right invalid rect. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect); - } - - { - // Write the left half of one row. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we don't have an invalid rect, since the invalid rect only - // gets updated when a row gets completed. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - } - - { - // Write the right half of the same row. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we have the right invalid rect, which will include both the - // left and right halves of this row now that we've completed it. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect); - } - - { - // Write no rows. - auto result = aSink->WritePixels([&]() { - return AsVariant(WriteState::NEED_MORE_DATA); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we don't have an invalid rect. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - } - - { - // Fill the rest of the image. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 90u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Assert that we have the right invalid rect. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); - } - }); -} - -TEST(ImageSurfaceSink, SurfaceSinkFlipVertically) -{ - WithSurfaceSink([](Decoder* aDecoder, - SurfaceSink* aSink) { - { - // Fill the image with a first pass of red. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Red().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u * 100u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); - } - - { - ResetForNextPass(aSink); - - // Check that the generated image is still the first pass image. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); - } - - { - // Fill 25 rows of the image with green and make sure everything is OK. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 25 * 100) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - count++; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(25u * 100u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Assert that we have the right invalid rect, which should include the - // *bottom* (since we're flipping vertically) 25 rows of the image. - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(RowsAreSolidColor(surface, 0, 75, BGRAColor::Red())); - EXPECT_TRUE(RowsAreSolidColor(surface, 75, 25, BGRAColor::Green())); - } - - { - // Fill the rest of the image with a second pass of green. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() { - ++count; - return AsVariant(BGRAColor::Green().AsPixel()); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(75u * 100u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 75), - IntRect(0, 0, 100, 75)); - - // Check that the generated image is correct. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - RefPtr surface = currentFrame->GetSourceSurface(); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); - } - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkInitialization) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Check initial state. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that the paletted image data is zero-initialized. - RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); - uint8_t* imageData = nullptr; - uint32_t imageLength = 0; - currentFrame->GetImageData(&imageData, &imageLength); - ASSERT_TRUE(imageData != nullptr); - ASSERT_EQ(100u * 100u, imageLength); - for (uint32_t i = 0; i < imageLength; ++i) { - ASSERT_EQ(uint8_t(0), imageData[i]); - } - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor0_0_100_100) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor25_25_50_50) -{ - WithPalettedSurfaceSink(IntRect(25, 25, 50, 50), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink, - /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputWriteRect = */ Some(IntRect(25, 25, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(25, 25, 50, 50))); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_Minus25_50_50) -{ - WithPalettedSurfaceSink(IntRect(-25, -25, 50, 50), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink, - /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputWriteRect = */ Some(IntRect(-25, -25, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(-25, -25, 50, 50))); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_Minus25_50_50) -{ - WithPalettedSurfaceSink(IntRect(75, -25, 50, 50), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink, - /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputWriteRect = */ Some(IntRect(75, -25, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(75, -25, 50, 50))); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_75_50_50) -{ - WithPalettedSurfaceSink(IntRect(-25, 75, 50, 50), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink, - /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputWriteRect = */ Some(IntRect(-25, 75, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(-25, 75, 50, 50))); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_75_50_50) -{ - WithPalettedSurfaceSink(IntRect(75, 75, 50, 50), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - CheckPalettedWritePixels(aDecoder, aSink, - /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), - /* aInputWriteRect = */ Some(IntRect(75, 75, 50, 50)), - /* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50))); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFinish) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Write nothing into the surface; just finish immediately. - uint32_t count = 0; - auto result = aSink->WritePixels([&]{ - count++; - return AsVariant(WriteState::FINISHED); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(1u, count); - - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixels([&]() { - count++; - return AsVariant(uint8_t(128)); - }); - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is correct. - EXPECT_TRUE(IsSolidPalettedColor(aDecoder, 0)); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsEarlyExit) -{ - auto checkEarlyExit = - [](Decoder* aDecoder, PalettedSurfaceSink* aSink, WriteState aState) { - // Write half a row of green pixels and then exit early with |aState|. If - // the lambda keeps getting called, we'll write red pixels, which will cause - // the test to fail. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(aState); - } - return count++ < 50 ? AsVariant(uint8_t(255)) : AsVariant(uint8_t(128)); - }); - - EXPECT_EQ(aState, result); - EXPECT_EQ(50u, count); - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 50, 1)); - - if (aState != WriteState::FINISHED) { - // We should still be able to write more at this point. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Verify that we can resume writing. We'll finish up the same row. - count = 0; - result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - ++count; - return AsVariant(uint8_t(255)); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 100, 1)); - - return; - } - - // We should've finished the surface at this point. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixels([&]{ - count++; - return AsVariant(uint8_t(128)); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 50, 1)); - }; - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::NEED_MORE_DATA); - }); - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FAILURE); - }); - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FINISHED); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsToRow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Write the first 99 rows of our 100x100 surface and verify that even - // though our lambda will yield pixels forever, only one row is written per - // call to WritePixelsToRow(). - for (int row = 0; row < 99; ++row) { - uint32_t count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(uint8_t(255)); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(100u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isSome()); - EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mInputSpaceRect); - EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect); - - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 100, row + 1)); - } - - // Write the final line, which should finish the surface. - uint32_t count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(uint8_t(255)); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(100u, count); - - // Note that the final invalid rect we expect here is only the last row; - // that's because we called TakeInvalidRect() repeatedly in the loop above. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 99, 100, 1), - IntRect(0, 99, 100, 1)); - - // Check that the generated image is correct. - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixelsToRow([&]{ - count++; - return AsVariant(uint8_t(128)); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 100, 100)); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsToRowEarlyExit) -{ - auto checkEarlyExit = - [](Decoder* aDecoder, PalettedSurfaceSink* aSink, WriteState aState) { - // Write half a row of 255s and then exit early with |aState|. If the lambda - // keeps getting called, we'll write 128s, which will cause the test to - // fail. - uint32_t count = 0; - auto result = aSink->WritePixelsToRow([&]() -> NextPixel { - if (count == 50) { - return AsVariant(aState); - } - return count++ < 50 ? AsVariant(uint8_t(255)) - : AsVariant(uint8_t(128)); - }); - - EXPECT_EQ(aState, result); - EXPECT_EQ(50u, count); - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 50, 1)); - - if (aState != WriteState::FINISHED) { - // We should still be able to write more at this point. - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - // Verify that we can resume the same row and still stop at the end. - count = 0; - WriteState result = aSink->WritePixelsToRow([&]{ - ++count; - return AsVariant(uint8_t(255)); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 100, 1)); - - return; - } - - // We should've finished the surface at this point. - AssertCorrectPipelineFinalState(aSink, - IntRect(0, 0, 100, 100), - IntRect(0, 0, 100, 100)); - - // Attempt to write more and make sure that nothing gets written. - count = 0; - result = aSink->WritePixelsToRow([&]{ - count++; - return AsVariant(uint8_t(128)); - }); - - EXPECT_EQ(WriteState::FINISHED, result); - EXPECT_EQ(0u, count); - EXPECT_TRUE(aSink->IsSurfaceFinished()); - - // Check that the generated image is still correct. - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 50, 1)); - }; - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::NEED_MORE_DATA); - }); - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FAILURE); - }); - - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [&](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - checkEarlyExit(aDecoder, aSink, WriteState::FINISHED); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBuffer) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Create a buffer the same size as one row of the surface (which is 100x100), - // containing 60 pixels of 255 in the middle and 20 transparent pixels of 0 on - // either side. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 20 <= i && i < 80 ? 255 : 0; - } - - // Write the buffer to every row of the surface and check that the generated - // image is correct. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{ - return aSink->WriteBuffer(buffer); - }); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Create a buffer the same size as one row of the surface, containing all - // 255 pixels. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 255; - } - - // Write the buffer to the middle 60 pixels of every row of the surface and - // check that the generated image is correct. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{ - return aSink->WriteBuffer(buffer, 20, 60); - }); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRowStartColOverflow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Create a buffer the same size as one row of the surface, containing all - // 255 pixels. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 255; - } - - { - // Write the buffer to successive rows until every row of the surface - // has been written. We place the start column beyond the end of the row, - // which will prevent us from writing anything, so we check that the - // generated image is entirely 0. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteBuffer(buffer, 100, 100); - }); - } - - ResetForNextPass(aSink); - - { - // Write the buffer to successive rows until every row of the surface - // has been written. We use column 50 as the start column, but we still - // write the buffer, which means we overflow the right edge of the surface - // by 50 pixels. We check that the left half of the generated image is - // 0 and the right half is 255. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteBuffer(buffer, 50, 100); - }); - } - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRowBufferOverflow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Create a buffer twice as large as a row of the surface. The first half - // (which is as large as a row of the image) will contain 255 pixels, - // while the second half will contain 128 pixels. - uint8_t buffer[200]; - for (int i = 0; i < 200; ++i) { - buffer[i] = i < 100 ? 255 : 128; - } - - { - // Write the buffer to successive rows until every row of the surface has - // been written. The buffer extends 100 pixels to the right of a row of - // the surface, but bounds checking will prevent us from overflowing the - // buffer. We check that the generated image is entirely 255 since the - // pixels on the right side of the buffer shouldn't have been written to - // the surface. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 100, 100), [&]{ - return aSink->WriteBuffer(buffer, 0, 200); - }); - } - - ResetForNextPass(aSink); - - { - // Write from the buffer to the middle of each row of the surface. That - // means that the left side of each row should be 0, since we didn't write - // anything there. A buffer overflow would cause us to write buffer - // contents into the left side of each row. We check that the generated - // image is 0 on the left side and 255 on the right. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteBuffer(buffer, 50, 200); - }); - } - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferFromNullSource) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Calling WriteBuffer() with a null pointer should fail without making any - // changes to the surface. - uint8_t* nullBuffer = nullptr; - WriteState result = aSink->WriteBuffer(nullBuffer); - - EXPECT_EQ(WriteState::FAILURE, result); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - Maybe invalidRect = aSink->TakeInvalidRect(); - EXPECT_TRUE(invalidRect.isNothing()); - - // Check that nothing got written to the surface. - CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 0, 0)); - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteEmptyRow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - { - // Write an empty row to each row of the surface. We check that the - // generated image is entirely 0. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteEmptyRow(); - }); - } - - ResetForNextPass(aSink); - - { - // Write a partial row before we begin calling WriteEmptyRow(). We check - // that the generated image is entirely 0, which is to be expected since - // WriteEmptyRow() overwrites the current row even if some data has - // already been written to it. - uint32_t count = 0; - auto result = aSink->WritePixels([&]() -> NextPixel { - if (count == 50) { - return AsVariant(WriteState::NEED_MORE_DATA); - } - ++count; - return AsVariant(uint8_t(255)); - }); - - EXPECT_EQ(WriteState::NEED_MORE_DATA, result); - EXPECT_EQ(50u, count); - EXPECT_FALSE(aSink->IsSurfaceFinished()); - - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{ - return aSink->WriteEmptyRow(); - }); - } - - ResetForNextPass(aSink); - - { - // Create a buffer the same size as one row of the surface, containing all - // 255 pixels. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 255; - } - - // Write an empty row to the middle 60 rows of the surface. The first 20 - // and last 20 rows will be 255. (We need to use DoCheckIterativeWrite() - // here because we need a custom function to check the output, since it - // can't be described by a simple rect.) - auto writeFunc = [&](uint32_t aRow) { - if (aRow < 20 || aRow >= 80) { - return aSink->WriteBuffer(buffer); - } else { - return aSink->WriteEmptyRow(); - } - }; - - auto checkFunc = [&]{ - EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 0, 20, 255)); - EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 20, 60, 0)); - EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 80, 20, 255)); - }; - - DoCheckIterativeWrite(aSink, writeFunc, checkFunc); - } - }); -} - -TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteUnsafeComputedRow) -{ - WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), - [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { - // Create an all-255 buffer the same size as one row of the surface. - uint8_t buffer[100]; - for (int i = 0; i < 100; ++i) { - buffer[i] = 255; - } - - // Write the buffer to successive rows until every row of the surface has - // been written. We only write to the right half of each row, so we check - // that the left side of the generated image is 0 and the right side is 255. - CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{ - return aSink->WriteUnsafeComputedRow([&](uint8_t* aRow, - uint32_t aLength) { - EXPECT_EQ(100u, aLength ); - memcpy(aRow + 50, buffer, 50 * sizeof(uint8_t)); - }); - }); - }); -} diff --git a/image/test/gtest/animated-with-extra-image-sub-blocks.gif b/image/test/gtest/animated-with-extra-image-sub-blocks.gif deleted file mode 100644 index a145c814a684c454e4003ab41699798db0ed8366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 434 zcmZ?wbhEHbOkqf2_`txx@E?d76o0ZXaDnLm+bCU^SwR4`P&|OOncV3?A57l@3@bD^11%4_xZ1L-~aLRaJ3&<^s&Q7 zYxJ}PV6f%_0Ia@)ReQ* z_IAsbjKh7-I&B35hIWC|SzBWC@Qn9{avE2~p-jM#z>*O19EuWQa({E^9PM zj5SfnFqRBOqh<_Z44&NSdG71p*X#au@BN(D`Tldh=e)k}*V&ucn*)Tb&LGbKAT9s^ zaTc&Q1(*X6FgG_h7{VzK2!sc^4+iB#kdL2tA6)Rj0k|MsNcf+>>&wB zDH$0VVKF&`oHRmGT1NWUBOuOIC=YZ$47Oid1TG@|KWDE4fWrWLz#a^e1GwNIFdVc; z0%SOILO_27_-8;|U~bNoFkU`>PD7&*zy$(>xj6H40G#f4&N;vhha8YqH{}s_xB!(4 z6VbStSqPIit9>Kt_<@Pg^u^rbLNL)fe@#rz7<67D}x_bHs=D%5-u{?{ka&mTY zb#wRd^z*+M5P0cwQ25n|$f#@4F^RX6?%Ykjm+}z%C<~YUI0s+!toV5ep|q^LuD+qM z>1A`vtIjS`cTaC$|G>!T*vE15#3Y3}zwr6X;?h^z^6J|9kBv>%7JK`b3j~1wW^wA@ zu>WwuIW8{Fw{Sy$xj_L7`8zNiFadVtl%8cr;iye{lG1kyUq7-GY{P7$ z2+}zOQ+ccE_5O8?z7ehc^I3HJpr6eK-vpKdn1O;0>O$LrzQt~FNgwz#c4OaH+qw+DjUtOQZ~{UXT*8FK-Xl( zTbI1Z+BRXS{rc{o&^hRl6Q^(tgO6;qaMb-U&)OT%5DY7GsPVa2SMi*j?pQSY}rg^orD$jOUl@ zC$3@biCbyg1~zr$Jz;zv$Bx&I4A#b1%+Sg(4?Nn&#&^OKA86>&$fBfTY>>3V%eK{X z-z-8G)xOSS#7*g=DJ!%32mIUXWCI-%r?iKbW4vGCiWFKB;|6z%hh@```HI*suaSIR zN*JkvM(t#G75`gigQ97~M72{l`;IJZROm|J3Sy~~TBQvWA&PfgqH%v@sQ1ca^A?O} zDl9EV(!1Y=I%K}-=x~_ed;2jsptiNS0W_lYf}h}>kw~L^>^RR1&K^X)QzIx-KY`An zjWudNESQI!$Qj0+e|&nFn?*ylG3%+>$%c@MAoBK;L7M=-lV;9y0~kW&DbW3)(p|o~ z=G1v^;Rp$Zzptbtuh|N?tO0&!@%1q(by(05yOyP?G-jJGx zIk%FZBd+*O0(Iw<5uetzS-(wetJ2hzKHbxaC1GdY-{V-gwcyKL;5#1 zxn;}X=P9C(CNYI=i!Q5N$rp#M%llR(W@e(kFvDHZsS%EPKva#3sj9=m(D(bBNo}|j zcVD4$MC(=QWANh0%x57k00VJyS|f}+(rz>M6eo7}oZaK4!eulqb9KdZ)h-bpLCk*N zibN}ZWz5$K7f&35LK#b=P0DXt1B)jue19TFwWBxqJp$Zu9`v+*qe328ZbxNf^H`$2 zx1CC+5%+yVG*Y6pN*Y=kneXxogNepxJs!klY22T$@g3LOs3cY2 zM`~0X*=r%q& zfH=4ooR*QgtehHb;!)=(o*dQ_btPWeugh2(zex{#9p88N6f~R>)S_fQE7MrvfJvR3 zL0y>N(S)rRi@}^jD8GYywSTbas`GaHY1=kgS%WNfG}a5c<}(L$t>~}x(Kc#w5iQI- z6Je`w_&AC!wgD3BO;iT4h*68>aaQAtW4jJo>1ESF@Sar3aO+%Nd%ceS1?i3J!;~>w ziu>nMwtUEQWavI@w%-(T`V$@7dO?rl$#6q6wEv9cL+u)5*xU zl6wGLPdsF+(jAXfNTE!yvxP5+K|!YU0w;V`0$MwL)N2~3JN6muiD4PYRmLtQMpQ^S zncwiTP5XMoAn?KUtjNVat3fs;CWYNIv>c1P-872i&qzx%t)lFM?aab#!o%72c$>zX;=9lb~d(-<|FyMY>Q~;8f}%D4;6fO zp)zRn>o&biRkVwc!(AJ8qpS1{!zh-Fo7w}a`ga9_dQB!4U$!(hyXKmll)w2s-qHb; zax2Z*VQH*&X4pEnLl=Kl=2E8ot9nC)8Dey%ZaZ~!wcGRkk6gX;af6~zr?i63<{H6k z>)y;i=_I`N`=-X6{#a|V+qYtZ|5)87yU1i*mAa@IPe@l>`5EJx*V#K(xbr&c^5O2h LYJvK_NxpvoIw+iI diff --git a/image/test/gtest/downscaled.bmp b/image/test/gtest/downscaled.bmp deleted file mode 100644 index 9e6a29e62ba6cae31498a7cc039d4ef1deaeb44b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30138 zcmeI%y$(S!6ae4~kzf>wNem)JVKs=wWHB2Ia$i7f28+dFws{OOdI=9jM><%7f_OHP}Xq>hs-ne~PS diff --git a/image/test/gtest/downscaled.icon b/image/test/gtest/downscaled.icon deleted file mode 100644 index 19785f5dcb84a0a3f1fd541f0de8ef9f3e8b4076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40003 zcmeI)u?YY$2t~nPXHNHDL9>Q(NcwQRQmjfF0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAaFn+-SHS`Km!`kfCe<60S#zC0~*kP1~i}n4QN0E8qk0S zG@tfRF155A%(ibi5Qf&n{2w3o0hNAY%0~H zX{FQx$$V$Jv&>qibEqZGvJGZ?x-&yM8ay3kRxOuGMok>08PYY&3M5$;n@*A{OO+)` z(c7lgr>nAa?)c(chV;%ND=I2v70EJ-%^*)oOG}d{D&z`90$L>4H<}%4XM))t_wNYV zI=jYZvN}u_vxJSPF0qt5GNe*D&LF=t1uNcN>jFurg%}7i5Mm(2K!|}513x|n#!fpr zGahj&@GL{VhS>#1i^F0!TC9>}St88K%w5Kx25g&n>1R8;>)8|kbbT) zH!G{SK(!(#H-9l6v;eqkHfYN1{6v5N7fi^WoVOvHt}T}%5e>&jYTqE zXI{M$`*^&63U*L|5;8#oxv&_rU=Acf8b0Sh0w_R+Z*U)f#i;*su%NF7pH|oiHZXw! zjNpLTs4d6nI_&kR*WtAREwHhB!1e%R+}icYY&?WMJ`X@}m5||C0K%66g4+qXb&!x? z695l+IZ;36Z>a~E_YLZIjp^cF0f?#wIQqeuuA~{Dbr-E@Ere8jSccp0a#~p0z_e; z1uc&w0=CX?bs{`wsE*TzF?d%EIc9-4c?guTn>-NcsgFE5?eXa|X3k1Uoile{ zT6$LY;vD6Y+`N^mRzFpQgln`qy}@YurQK2fT!nMvrs`kUJimR%3$?%bZT+5?8usqn zf3WHI&3`y__>X^j>&V;h9BqB~y<_bsJ5HVc@XVjjUhKN`@h6wBbbs2{fA#MJUtAl! z{-tMV*!%6xfBHuJEG`c4?oxJ7Tu1_k%jfg>LKYW?TfqVs@db}1jhnQnP^f-3TB_I< z7L&RAz?*I1amgxoY>Dkc#N_ytzG)s7+915orJFlsNEqi@ z^*0nBnak|y_Qn!8t#tDUG`s2cYrc~N78myyF;jjqgTO$u_{+I`0vE*XJ-)gDDsV>Z zS=!S5GJ(7s{s;nB<9r+f7kyNpJ)kCVu*LHPfykB^dgx-^w?C<(2kZJQ0p(C5qmA-4 zU%qh;CwXqOfcEST0Dh5*O3k8l5eURtc8%LNbv1)PNs)NT2kJ}F`T+T&e84SntDB#`oP0O=PU z>ge>(q=zT$qK6L?I2*;t)&!4=z5D5rZ;G=!ncbMv}1-ft#zUM{t z57d2z8J~-v)9(hn`IyZU#qKlIk=9^zXW)3Hoxr(NvFFiB968uPAh8=aHoZDD(eU9A zb@xdI;l({8CMLG#e@XBh0w*ggF%b_~`dXOq0Oskr7ip}Q9mlb>O_+!28EI=|Y+`>d zed-kgSn}%{x?UqN*?`3@9~~!nu+r4Ho_G1Cv&C&r3jG6DVPI_!R?@+d&FLwKjIs^}PcSfdOqZN(qO`L0^p-HIjg8dkQ@d?7v`E?*2Cskgcb6tz8A Mz5j222AXvL3+jb-3;+NC diff --git a/image/test/gtest/downscaled.png b/image/test/gtest/downscaled.png deleted file mode 100644 index b71b4652d5288450d91a28c1d8da4a51f16cfb85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1015 zcmeAS@N?(olHy`uVBq!ia0vp^DIm?;Zqle1Gx6p~WYGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0T;&&% zT$P<{nWAKG$7NGt1vDTxwIorYA~z?m*s8)-32d$vkPQ;nS5g2gDap1~itr6kaLzAE zRWQ{v)iY4C<5I9GN=dT{a&d!d2J&o`GD=Dctn~HE%ggo3jrH=2()A53EiLs8jP#9+ zbb%^#i!1X=5-W7`ij_e|K+JGSElw`VEGWs$&r<-InV6JcT4JlDqz|%0A8HHGx%zPT z0y%IWr{)2@Sp@Wtl-KH4z+h_2baoCX4sv%=@N{)HGqf}_(>2mFWMI&kSUPdPw^N|V zar?~u8p;~&ZEWos9X*>m7A@`B;H0v~VYTagJKimF?==N`dDrst{avuMW7@M@i|Q3P znzFhUm`ZU)DaAd{THrG8^xp5q`@hdAes3!-GqGpd)~w%(yQdi+X56nX6#L1eqtxB~964ui|okFJ_nGdsuyZ+y1`X-@jSr1WkYKWLdYD zK{t4M{%)a$>?28Jcq_i~}mP@TmWbd6{pvv`j`-Lqrt8TxyQ|I5X zf%TyD4f}??kNL4b8GjX}o32~ANe`GhISV`@iy0WWg+Z8+Vb&Z8px_5j7srr_Id5+t zEi%%oal*Ykqqpwxo76`=g;>FVdQ&MBb@0MulK7ytkO diff --git a/image/test/gtest/first-frame-green.gif b/image/test/gtest/first-frame-green.gif deleted file mode 100644 index cd3c7d3db89085bbdbcb41247792bfc5fde9c492..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 317 zcmZ?wbhEHbOkqf2_`txx@E?d76o0ZXaDnLm+bCU^SwR4`P&|OOncV3?A57l@3@bD^11%4_xZ1L-~aLRaJ3&<^s&Q7 zYxg(%)P8t~3SOWn5Zl3x8 diff --git a/image/test/gtest/first-frame-green.png b/image/test/gtest/first-frame-green.png deleted file mode 100644 index 115f035d897859b9ad8e47cb158d252e621096c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^DIm7q0dH}%P0@|lsk;Di3whd_g1)-eLv zU>|_30uf;Acs8Ye2eKX0QXE5oG!v4Q8~-i5{;1#r(=v8^wt?kN{!dx*-%nA(&o~BX zh;)f-L`iUdT1k0gQ7VHYFeDWmi;GiplX6mv6pZx@;#_rPfXWy=UHx3vIVCg!0L9y1 Aga7~l diff --git a/image/test/gtest/first-frame-padding.gif b/image/test/gtest/first-frame-padding.gif deleted file mode 100644 index e6d7c49322b6a0a4402d2ab9c7c1d64ce22d84f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmZ?wbhEHb6krfw_`t}(@SoxT|Nn|VSr|Y-hnazyfeQ#3m^fPcSDt>$pRCPb4FEkY B3~&Gd diff --git a/image/test/gtest/green-1x1-truncated.gif b/image/test/gtest/green-1x1-truncated.gif deleted file mode 100644 index 0829f9694d9ae8bf530c9b9e084dfe07526bc71d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmZ?wbhEHbWMp7uXkcVu_|NeF|9{1Qg3d*$i6yBi3gww484B*6z5xt63_t)<#=ykn F0syb;4X*$I diff --git a/image/test/gtest/green.bmp b/image/test/gtest/green.bmp deleted file mode 100644 index f79dd672adfd43be0906e2ce5bb600b215517d27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30138 zcmeIuuMUAx6aesR%!X(-$pkaesDdeyA`60jFJPLWD2l9k3=_SChmd7H*WWDv?(R9e z=bYUWeuL3*5#rgTd6~xS6`4?t{dPJpm!1(DG2KFV-bZyC49D};>DrneYL)u>lIeH5 z}D?{?)5OTjo-11)e+3i7q009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly KK!5;&zXa|~egVP& diff --git a/image/test/gtest/green.gif b/image/test/gtest/green.gif deleted file mode 100644 index ef215dfc94751a15cca5909a443632f5468041b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156 zcmZ?wbhEHbOkqf2_`txx@E?d76o0aSC0DsJgtdHOB?;yGJxb#K16=Qn@b zBadm%I+wjVwe21E@lQV2zx6)en^ZQ;t0ulgyQxa#q^j zZrPHdfAb8jE>C~}0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs p0RjXF5FkK+009C72oNAZfB*pk1PBlyK!Cs}5J!Lj0Rja63*4#e+dKdO diff --git a/image/test/gtest/green.icon b/image/test/gtest/green.icon deleted file mode 100644 index c74e62fee5f8638a051fea2806a55f2ceb402ed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40002 zcmeIuK@k7|3<98qwSR^AvIR#2l6wpoFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* t1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HV3Kmmf2*DL@4 diff --git a/image/test/gtest/green.jpg b/image/test/gtest/green.jpg deleted file mode 100644 index 48c454d27c9c46574597f80fdd64ecd4d254577d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmbV{Jr2S!3`RdUC5n@@by{Fz;vx)4mEas4hWjwGFmMQd7H$%pvEATBijpUPv6CP9 z138X|5kwU>x{%-4!&HT`8>O~&!CAYo?7U~k>|+;wXajSTnzj>3;$uJbGU!>#BUF;6 zb{dqxLG6#^83E)O5% diff --git a/image/test/gtest/green.png b/image/test/gtest/green.png deleted file mode 100644 index 7df25f33bdb26cc7f41138501ab399059839137d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^DImFdgVmrY2>Os;yW$XlS$JWm(LkcwMxFBmd1FmNz0$ozjU>fm{HrGS|QSGZD6PEz%r zro*}k!eEMoFdB8hjHM3Kz>FXTpcbCU^SwR4`P&|OOncV3?A57l@3@bD^11%4_xZ1L-~aLRaJ3&<^s&Q7 zYxg(%)P8t~3SOWmpOg})TnSOb?Wf!dwrMno=60lzDo_`zO>KCiE@P;SOpL1E3%b;`U# znn#M1eTsxRq06jvR_saZ;BBwmmANiGt+7@v1MHa-=7fAgU)QM)7itBljFH#uGnWs< zex;}}ID<8{HFKuxggK$dyke|ZT%cPRmp(c!_v6Kbmn`x3jxlkyTG_${7t;&IM zXpkvrp8$Q)zLX&w-#pZJEEZpR$2TGyqOc|Qxj_?!ubh8+dXi^(k&1kjBeRyPMT(D) z&(G9heXmqte?;Na(NV3I`|r< z=I!mRoN%^YuOA<8T$w|@+~42JEu?*Naw2u(v+>rWnR_&)ZhqENaFkNf{7#P=Tetn! zjU|#hnaVXvt#+&3I6FH#J>}F^hc&#uhP2=`Xq{?{f8cBu&m@K&MR(C1WC|G$hu0gb zv899rcTZ)Aa=+DTH5-kFmoJbRBo1S`kYGC95dD6uNyH<<8$Qft;Vh2hC=Q~C$cXzP zee5)wUbEqPo~NI~3d0%f5Va@>g3)L?8ufa;PN&}?w}Q8A;FXz~Pk3!@->p z7Du2Rrvux&xVX?d+;GBA7>WLaqwFsr6iiH5d$FlP>yv!8ekVdRlzQ g<)weQQUC7U?6Bzy9s3Or$M^k99{!wv_mDLH0PnoJF8}}l diff --git a/image/test/gtest/transparent-ico-with-and-mask.ico b/image/test/gtest/transparent-ico-with-and-mask.ico deleted file mode 100644 index ab0dc4bce1ebb02377bca48dae36775579e2414d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3262 zcmcJRUuYx89mjt&qtvs$wi;ca-c<_GxGiY*Qm}M=@m@;Lx)f?Tfm%)K&;C{tu&C+T_3axrD&CwXpUN| ztNPX#!@<%SegpG|?|kMrzxe}z#yJpxajC*Jy;ZMFs{_+I+;4J?0x5@5Pd+CH#De{PY$4 z!&~^`CjS05`QF?3JMZAx_wdYZ68tNE{2o?6#b54|iGN{4l;I zET3U3E56K&?8?iUM}?pv&Qqg58!VY9ow&^{AQ#*di#3G;TC@^?nCe+YhwG@GcF zqP2bgmR~#M+P={CLR#&dx_v?0jB4vKt^Az7l+^Mmf9`pICa0weTB4-I%i7{CZK0w? zw){p-3+<`mK;wsgt);QMD*c;E@U#P5BHl-Vu7|fL11%qKs=P7H>w@ou`SvWYT;S{T zfwd)Git|D;kW2AwHjv8kWFZhQ@>rSAn|yAQpR4k4jf*QlXH&scRwQ#Gp4VeVF<;i_ zOkr&3;i?cdeM~l9KWhqlJ4hfrgpfob8-=#>y{>jBfewi2J>RQ}u#+5(B3A#K)Nr{p+ zB)gDs>z`~wnZx%6hT*y zAv?fV`;fIz)~$XbtEV#jYF5i-*h^V@ErZeOzhQL%IU90awCYxWIj1LbJe||BIkvh= zf3-sJwILJ+P_Ut3LBVbOEamm(!gQjbUMYC5=9OO*Jf!46X#mAOlq@K@6U-? zrkFE%bX{9qXK{1ll1b3!5LG0ue1<9(RNU%^D!Q@3BNc7F!eSNW*$qOrhftNMYQvTV zRk!=AZ;5b~8{69XZ8pC}pQ#d58$wN@S|4f_s=4LowebVP&(_9|r7u#W->ng}cMN+H z>OH7iP_M{&O}G4$hvIaTYfUxK^opkP&87!`G=!FfmJLT1YPpU7M~(z-1z5{JHU5UQ zl&>FQbZ-dl0o?6D+k&=Re$>`IcLI}b&DUoBHvQ@y4|IoMN$B*z>O#jYKUhIzaZg8` zw3x4>JZcfrcfcOtejj=ru-jm_u-!zx1F-kN-a+;j^ef0Vk$nT%MPwJiUWI-Z>?>d= zz>b3*L%k@nBVZd~hmozL-ZZlPq{mM6lrQxNk`71-vInvYgEq*Ikh~4D0r%@5Yapv2 zD=;uYmXR!h%p;itnFX1G`$>??AeUee1$hAt3?$E@fsP~xsUqnk1L_$NGJ1fWV>J2< zJD+0b9vOX%oe%NoeeAr0M{gtN4eY#zoLj{CJs$mrIM=YVibgLG=jYh@2_8L%ooDgr q8SFfTohQlgTf}(+JKrGAW7s)OoJlhL!b$&vi3bnf{eRj2&iNl+(!q%U diff --git a/image/test/gtest/transparent-if-within-ico.bmp b/image/test/gtest/transparent-if-within-ico.bmp deleted file mode 100644 index 4dc04c181ba7d4ca9ac41fcb670f6f5fa3ca37dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4234 zcmciEF>ez=5CvdIAS9@e5N$+-Qj?k{4RS#NHFf>~ty`K%R_aLp1^EFHt!Z6HbZ%2n zq@q6V3wdaDEO%$eCdy`ZXJ+TUH?vN1^8W1kqx(crS{`hE4_!M5~$I-NF`mzV#I2kmg%x!z&h zhesdpUBqaI8_e_|=aR?1=2BwS@Ds;VuXf49tW%%u!%v=^UGVV6QZtsuavt&5?0i0N zR;$(4pOvn57<}rE<=~E9Z2A^!+SSrq3w~@(d+Eb>6MXNdrX41~-$51(XFO{8;UKmN zero4_EF610)Qdm9J|1K7y_d3X_R*fRnU9)9q$x)`~`x>xeRw{H&c-6?C>2iM*7SnqM@=H@J3euh$Gs0U>agRNFM z>tNth<14OCw>NT!{)gz!UyWL=V082OyV}EdsQ;Nw@?on5qo$vpT8yvT7w4hg!_Q3N zx$`gW(aC1EY&bQrh8a)N4wg5aQVy^kGwlEIooQl@uMR=)HYZ3 z?Ja$B#zPFZTAhdb@JPSmMJo>Udw<)!xlMV6hkGJl%@j^84t5lgZF@c&4c%VS>inmmKYDm>d&Kp zdBA5TAw4?f0Sg?N@-Q$*$df?&JY;sg$g{MbfO-|C7>N>xTrm=bj*uu5^i_us2CY`7 diff --git a/image/test/gtest/transparent.png b/image/test/gtest/transparent.png deleted file mode 100644 index fc8002053a39d720cec152a82a97ab068e14a366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 419 zcmV;U0bKrxP)fvE$HuR_SJSS z55Et?JTvoPh0AulLIih*akytD27~Tb;Xe$LE%nD4!n3xHfZuZ4Pj*<5|d*T#H!ESYk7m-HU8@5jnVrEpCx9QzA>j^IKr#L|fDVP9W`Og2!1Mm~*q* z55G_oeZ|SW=ug`&$i3kho&-p?HH33nlfnslU>nkL46N&>6^EB7TYn&gqWCOVz#0Gm N002ovPDHLkV1ktEtrY+O diff --git a/security/manager/ssl/tests/unit/moz.build b/security/manager/ssl/tests/unit/moz.build index 8a97120c28..3cca4c4fa6 100644 --- a/security/manager/ssl/tests/unit/moz.build +++ b/security/manager/ssl/tests/unit/moz.build @@ -31,7 +31,6 @@ TEST_DIRS += [ 'test_ocsp_fetch_method', 'test_ocsp_url', 'test_onecrl', - 'test_pinning_dynamic', 'test_startcom_wosign', 'test_validity', ] diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index 1cca83b5b9..52eaba21d1 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -11,8 +11,6 @@ else: updater_rel_path = '' include('updater-common.build') -if CONFIG['ENABLE_TESTS']: - DIRS += ['updater-xpcshell'] CXXFLAGS += CONFIG['MOZ_BZ2_CFLAGS'] diff --git a/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in b/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in deleted file mode 100644 index 01822b1861..0000000000 --- a/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in +++ /dev/null @@ -1,41 +0,0 @@ -# vim:set ts=8 sw=8 sts=8 noet: -# 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/. - -# For changes here, also consider ../Makefile.in - -XPCSHELLTESTROOT = $(topobjdir)/_tests/xpcshell/toolkit/mozapps/update/tests -MOCHITESTROOT = $(topobjdir)/_tests/testing/mochitest/chrome/toolkit/mozapps/update/tests - -include $(topsrcdir)/config/rules.mk - -ifndef MOZ_WINCONSOLE -ifdef MOZ_DEBUG -MOZ_WINCONSOLE = 1 -else -MOZ_WINCONSOLE = 0 -endif -endif - -ifdef COMPILE_ENVIRONMENT -tools:: -ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) - # Copy for xpcshell tests - $(NSINSTALL) -D $(XPCSHELLTESTROOT)/data/updater-xpcshell.app - rsync -a -C --exclude '*.in' $(srcdir)/../macbuild/Contents $(XPCSHELLTESTROOT)/data/updater-xpcshell.app - sed -e 's/%APP_NAME%/$(MOZ_APP_DISPLAYNAME)/' $(srcdir)/../macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \ - iconv -f UTF-8 -t UTF-16 > $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/Resources/English.lproj/InfoPlist.strings - $(NSINSTALL) -D $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/MacOS/updater-xpcshell - $(NSINSTALL) updater-xpcshell $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/MacOS - rm -Rf $(XPCSHELLTESTROOT)/data/updater.app - mv $(XPCSHELLTESTROOT)/data/updater-xpcshell.app $(XPCSHELLTESTROOT)/data/updater.app - mv $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/updater-xpcshell $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/org.mozilla.updater - - # Copy for mochitest chrome tests - rsync -a -C $(XPCSHELLTESTROOT)/data/updater.app $(MOCHITESTROOT)/data/ -else - cp $(PROGRAM) $(XPCSHELLTESTROOT)/data/updater$(BIN_SUFFIX) - cp $(PROGRAM) $(MOCHITESTROOT)/data/updater$(BIN_SUFFIX) -endif -endif # COMPILE_ENVIRONMENT diff --git a/toolkit/mozapps/update/updater/updater-xpcshell/moz.build b/toolkit/mozapps/update/updater/updater-xpcshell/moz.build deleted file mode 100644 index 710b7e1dec..0000000000 --- a/toolkit/mozapps/update/updater/updater-xpcshell/moz.build +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -Program('updater-xpcshell') - -updater_rel_path = '../' -DIST_INSTALL = False -DEFINES['TEST_UPDATER'] = True -include('../updater-common.build') - -CXXFLAGS += CONFIG['MOZ_BZ2_CFLAGS'] From cd1c94480d32cf2a7df61d67c48749897394426a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 9 Jun 2020 04:18:32 +0000 Subject: [PATCH 4/7] Issue #1560 - Always include speech synthesis IPDLs This is entangled with the IPC messaging configuration so we need these IPDLs even if sppech synthesis is otherwise not being built. This resolves #1560 --- dom/media/webspeech/moz.build | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dom/media/webspeech/moz.build b/dom/media/webspeech/moz.build index 677e0656f6..c61c63b720 100644 --- a/dom/media/webspeech/moz.build +++ b/dom/media/webspeech/moz.build @@ -3,5 +3,11 @@ # 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/. +# Due to IPC entanglement we always need the synthesis ipdls if CONFIG['MOZ_WEBSPEECH']: DIRS += ['synth'] +else: + IPDL_SOURCES += [ + 'synth/ipc/PSpeechSynthesis.ipdl', + 'synth/ipc/PSpeechSynthesisRequest.ipdl', + ] \ No newline at end of file From 564f1026d501c80c486b06f60f52313421716900 Mon Sep 17 00:00:00 2001 From: Lootyhoof Date: Sat, 6 Jun 2020 00:37:29 +0100 Subject: [PATCH 5/7] Issue MoonchildProductions/UXP#1578 - Add global menubar support for GTK --- layout/build/moz.build | 4 + layout/build/nsLayoutStatics.cpp | 7 + modules/libpref/init/all.js | 4 + toolkit/content/widgets/popup.xml | 10 +- toolkit/content/xul.css | 9 + widget/gtk/moz.build | 11 + widget/gtk/nsDbusmenu.cpp | 59 ++ widget/gtk/nsDbusmenu.h | 97 +++ widget/gtk/nsMenu.cpp | 800 +++++++++++++++++++++++++ widget/gtk/nsMenu.h | 120 ++++ widget/gtk/nsMenuBar.cpp | 541 +++++++++++++++++ widget/gtk/nsMenuBar.h | 103 ++++ widget/gtk/nsMenuContainer.cpp | 156 +++++ widget/gtk/nsMenuContainer.h | 66 ++ widget/gtk/nsMenuItem.cpp | 712 ++++++++++++++++++++++ widget/gtk/nsMenuItem.h | 77 +++ widget/gtk/nsMenuObject.cpp | 634 ++++++++++++++++++++ widget/gtk/nsMenuObject.h | 165 +++++ widget/gtk/nsMenuSeparator.cpp | 74 +++ widget/gtk/nsMenuSeparator.h | 33 + widget/gtk/nsNativeMenuAtomList.h | 9 + widget/gtk/nsNativeMenuAtoms.cpp | 35 ++ widget/gtk/nsNativeMenuAtoms.h | 23 + widget/gtk/nsNativeMenuDocListener.cpp | 329 ++++++++++ widget/gtk/nsNativeMenuDocListener.h | 146 +++++ widget/gtk/nsNativeMenuService.cpp | 485 +++++++++++++++ widget/gtk/nsNativeMenuService.h | 80 +++ widget/gtk/nsWidgetFactory.cpp | 8 + widget/gtk/nsWindow.cpp | 6 + widget/gtk/nsWindow.h | 6 + widget/moz.build | 4 +- xpfe/appshell/nsWebShellWindow.cpp | 2 +- 32 files changed, 4811 insertions(+), 4 deletions(-) create mode 100644 widget/gtk/nsDbusmenu.cpp create mode 100644 widget/gtk/nsDbusmenu.h create mode 100644 widget/gtk/nsMenu.cpp create mode 100644 widget/gtk/nsMenu.h create mode 100644 widget/gtk/nsMenuBar.cpp create mode 100644 widget/gtk/nsMenuBar.h create mode 100644 widget/gtk/nsMenuContainer.cpp create mode 100644 widget/gtk/nsMenuContainer.h create mode 100644 widget/gtk/nsMenuItem.cpp create mode 100644 widget/gtk/nsMenuItem.h create mode 100644 widget/gtk/nsMenuObject.cpp create mode 100644 widget/gtk/nsMenuObject.h create mode 100644 widget/gtk/nsMenuSeparator.cpp create mode 100644 widget/gtk/nsMenuSeparator.h create mode 100644 widget/gtk/nsNativeMenuAtomList.h create mode 100644 widget/gtk/nsNativeMenuAtoms.cpp create mode 100644 widget/gtk/nsNativeMenuAtoms.h create mode 100644 widget/gtk/nsNativeMenuDocListener.cpp create mode 100644 widget/gtk/nsNativeMenuDocListener.h create mode 100644 widget/gtk/nsNativeMenuService.cpp create mode 100644 widget/gtk/nsNativeMenuService.h diff --git a/layout/build/moz.build b/layout/build/moz.build index b98e8265a3..70b0754914 100644 --- a/layout/build/moz.build +++ b/layout/build/moz.build @@ -73,6 +73,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': '/dom/system', '/dom/system/android', ] +elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + LOCAL_INCLUDES += [ + '/widget/gtk', + ] if CONFIG['MOZ_WEBSPEECH']: LOCAL_INCLUDES += [ diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 75fae5398e..d81a8dfe2d 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -124,6 +124,10 @@ #include "mozilla/StaticPresData.h" #include "mozilla/dom/WebIDLGlobalNameHash.h" +#ifdef MOZ_WIDGET_GTK +#include "nsNativeMenuAtoms.h" +#endif + using namespace mozilla; using namespace mozilla::net; using namespace mozilla::dom; @@ -158,6 +162,9 @@ nsLayoutStatics::Initialize() nsTextServicesDocument::RegisterAtoms(); nsHTMLTags::RegisterAtoms(); nsRDFAtoms::RegisterAtoms(); +#ifdef MOZ_WIDGET_GTK + nsNativeMenuAtoms::RegisterAtoms(); +#endif NS_SealStaticAtomTable(); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 0f8b481387..ad5b77af24 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -251,6 +251,10 @@ pref("browser.sessionhistory.max_total_viewers", -1); pref("browser.newtabpage.add_to_session_history", false); pref("ui.use_native_colors", true); +#ifdef MOZ_WIDGET_GTK +// Determines whether the menubar is shown in the global menubar or not. +pref("ui.use_global_menubar", false); +#endif pref("ui.click_hold_context_menus", false); // Duration of timeout of incremental search in menus (ms). 0 means infinite. pref("ui.menu.incremental_search.timeout", 1000); diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml index bb1a5eeee8..43c529780f 100644 --- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -25,8 +25,14 @@ - + + + diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 24a6713f9b..0aa0d3a217 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -307,6 +307,15 @@ toolbar[type="menubar"][autohide="true"][inactive="true"]:not([customizing="true } %endif +%ifdef MOZ_WIDGET_GTK +window[shellshowingmenubar="true"] menubar, +window[shellshowingmenubar="true"] +toolbar[type="menubar"]:not([customizing="true"]) { + /* If a system-wide global menubar is in use, hide the XUL menubar. */ + display: none !important; +} +%endif + toolbarseparator { -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbardecoration"); } diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build index baccb6ccd9..8d621c0a0a 100644 --- a/widget/gtk/moz.build +++ b/widget/gtk/moz.build @@ -24,10 +24,18 @@ UNIFIED_SOURCES += [ 'nsAppShell.cpp', 'nsBidiKeyboard.cpp', 'nsColorPicker.cpp', + 'nsDbusmenu.cpp', 'nsFilePicker.cpp', 'nsGtkKeyUtils.cpp', 'nsImageToPixbuf.cpp', 'nsLookAndFeel.cpp', + 'nsMenuBar.cpp', + 'nsMenuContainer.cpp', + 'nsMenuItem.cpp', + 'nsMenuObject.cpp', + 'nsMenuSeparator.cpp', + 'nsNativeMenuAtoms.cpp', + 'nsNativeMenuDocListener.cpp', 'nsNativeThemeGTK.cpp', 'nsScreenGtk.cpp', 'nsScreenManagerGtk.cpp', @@ -40,6 +48,8 @@ UNIFIED_SOURCES += [ ] SOURCES += [ + 'nsMenu.cpp', # conflicts with X11 headers + 'nsNativeMenuService.cpp', 'nsWindow.cpp', # conflicts with X11 headers ] @@ -104,6 +114,7 @@ FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '/layout/generic', + '/layout/style', '/layout/xul', '/other-licenses/atk-1.0', '/widget', diff --git a/widget/gtk/nsDbusmenu.cpp b/widget/gtk/nsDbusmenu.cpp new file mode 100644 index 0000000000..2849536e9c --- /dev/null +++ b/widget/gtk/nsDbusmenu.cpp @@ -0,0 +1,59 @@ +/* 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 "nsDbusmenu.h" +#include "prlink.h" +#include "mozilla/ArrayUtils.h" + +#define FUNC(name, type, params) \ +nsDbusmenuFunctions::_##name##_fn nsDbusmenuFunctions::s_##name; +DBUSMENU_GLIB_FUNCTIONS +DBUSMENU_GTK_FUNCTIONS +#undef FUNC + +static PRLibrary *gDbusmenuGlib = nullptr; +static PRLibrary *gDbusmenuGtk = nullptr; + +typedef void (*nsDbusmenuFunc)(); +struct nsDbusmenuDynamicFunction { + const char *functionName; + nsDbusmenuFunc *function; +}; + +/* static */ nsresult +nsDbusmenuFunctions::Init() { +#define FUNC(name, type, params) \ + { #name, (nsDbusmenuFunc *)&nsDbusmenuFunctions::s_##name }, + static const nsDbusmenuDynamicFunction kDbusmenuGlibSymbols[] = { + DBUSMENU_GLIB_FUNCTIONS + }; + static const nsDbusmenuDynamicFunction kDbusmenuGtkSymbols[] = { + DBUSMENU_GTK_FUNCTIONS + }; + +#define LOAD_LIBRARY(symbol, name) \ + if (!g##symbol) { \ + g##symbol = PR_LoadLibrary(name); \ + if (!g##symbol) { \ + return NS_ERROR_FAILURE; \ + } \ + } \ + for (uint32_t i = 0; i < mozilla::ArrayLength(k##symbol##Symbols); ++i) { \ + *k##symbol##Symbols[i].function = \ + PR_FindFunctionSymbol(g##symbol, k##symbol##Symbols[i].functionName); \ + if (!*k##symbol##Symbols[i].function) { \ + return NS_ERROR_FAILURE; \ + } \ + } + + LOAD_LIBRARY(DbusmenuGlib, "libdbusmenu-glib.so.4") +#if (MOZ_WIDGET_GTK == 3) + LOAD_LIBRARY(DbusmenuGtk, "libdbusmenu-gtk3.so.4") +#else + LOAD_LIBRARY(DbusmenuGtk, "libdbusmenu-gtk.so.4") +#endif +#undef LOAD_LIBRARY + + return NS_OK; +} diff --git a/widget/gtk/nsDbusmenu.h b/widget/gtk/nsDbusmenu.h new file mode 100644 index 0000000000..c0d9e79790 --- /dev/null +++ b/widget/gtk/nsDbusmenu.h @@ -0,0 +1,97 @@ +/* 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 __nsDbusmenu_h__ +#define __nsDbusmenu_h__ + +#include "nsError.h" + +#include +#include + +#define DBUSMENU_GLIB_FUNCTIONS \ + FUNC(dbusmenu_menuitem_child_add_position, gboolean, (DbusmenuMenuitem* mi, DbusmenuMenuitem* child, guint position)) \ + FUNC(dbusmenu_menuitem_child_append, gboolean, (DbusmenuMenuitem* mi, DbusmenuMenuitem* child)) \ + FUNC(dbusmenu_menuitem_child_delete, gboolean, (DbusmenuMenuitem* mi, DbusmenuMenuitem* child)) \ + FUNC(dbusmenu_menuitem_get_children, GList*, (DbusmenuMenuitem* mi)) \ + FUNC(dbusmenu_menuitem_new, DbusmenuMenuitem*, (void)) \ + FUNC(dbusmenu_menuitem_property_get, const gchar*, (DbusmenuMenuitem* mi, const gchar* property)) \ + FUNC(dbusmenu_menuitem_property_get_bool, gboolean, (DbusmenuMenuitem* mi, const gchar* property)) \ + FUNC(dbusmenu_menuitem_property_remove, void, (DbusmenuMenuitem* mi, const gchar* property)) \ + FUNC(dbusmenu_menuitem_property_set, gboolean, (DbusmenuMenuitem* mi, const gchar* property, const gchar* value)) \ + FUNC(dbusmenu_menuitem_property_set_bool, gboolean, (DbusmenuMenuitem* mi, const gchar* property, const gboolean value)) \ + FUNC(dbusmenu_menuitem_property_set_int, gboolean, (DbusmenuMenuitem* mi, const gchar* property, const gint value)) \ + FUNC(dbusmenu_menuitem_show_to_user, void, (DbusmenuMenuitem* mi, guint timestamp)) \ + FUNC(dbusmenu_menuitem_take_children, GList*, (DbusmenuMenuitem* mi)) \ + FUNC(dbusmenu_server_new, DbusmenuServer*, (const gchar* object)) \ + FUNC(dbusmenu_server_set_root, void, (DbusmenuServer* server, DbusmenuMenuitem* root)) \ + FUNC(dbusmenu_server_set_status, void, (DbusmenuServer* server, DbusmenuStatus status)) + +#define DBUSMENU_GTK_FUNCTIONS \ + FUNC(dbusmenu_menuitem_property_set_image, gboolean, (DbusmenuMenuitem* menuitem, const gchar* property, const GdkPixbuf* data)) \ + FUNC(dbusmenu_menuitem_property_set_shortcut, gboolean, (DbusmenuMenuitem* menuitem, guint key, GdkModifierType modifier)) + +typedef struct _DbusmenuMenuitem DbusmenuMenuitem; +typedef struct _DbusmenuServer DbusmenuServer; + +enum DbusmenuStatus { + DBUSMENU_STATUS_NORMAL, + DBUSMENU_STATUS_NOTICE +}; + +#define DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU "submenu" +#define DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY "children-display" +#define DBUSMENU_MENUITEM_PROP_ENABLED "enabled" +#define DBUSMENU_MENUITEM_PROP_ICON_DATA "icon-data" +#define DBUSMENU_MENUITEM_PROP_LABEL "label" +#define DBUSMENU_MENUITEM_PROP_SHORTCUT "shortcut" +#define DBUSMENU_MENUITEM_PROP_TYPE "type" +#define DBUSMENU_MENUITEM_PROP_TOGGLE_STATE "toggle-state" +#define DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE "toggle-type" +#define DBUSMENU_MENUITEM_PROP_VISIBLE "visible" +#define DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW "about-to-show" +#define DBUSMENU_MENUITEM_SIGNAL_EVENT "event" +#define DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED "item-activated" +#define DBUSMENU_MENUITEM_TOGGLE_CHECK "checkmark" +#define DBUSMENU_MENUITEM_TOGGLE_RADIO "radio" +#define DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED 1 +#define DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED 0 +#define DBUSMENU_SERVER_PROP_DBUS_OBJECT "dbus-object" + +class nsDbusmenuFunctions { +public: + nsDbusmenuFunctions() = delete; + + static nsresult Init(); + +#define FUNC(name, type, params) \ + typedef type (*_##name##_fn) params; \ + static _##name##_fn s_##name; + DBUSMENU_GLIB_FUNCTIONS + DBUSMENU_GTK_FUNCTIONS +#undef FUNC + +}; + +#define dbusmenu_menuitem_child_add_position nsDbusmenuFunctions::s_dbusmenu_menuitem_child_add_position +#define dbusmenu_menuitem_child_append nsDbusmenuFunctions::s_dbusmenu_menuitem_child_append +#define dbusmenu_menuitem_child_delete nsDbusmenuFunctions::s_dbusmenu_menuitem_child_delete +#define dbusmenu_menuitem_get_children nsDbusmenuFunctions::s_dbusmenu_menuitem_get_children +#define dbusmenu_menuitem_new nsDbusmenuFunctions::s_dbusmenu_menuitem_new +#define dbusmenu_menuitem_property_get nsDbusmenuFunctions::s_dbusmenu_menuitem_property_get +#define dbusmenu_menuitem_property_get_bool nsDbusmenuFunctions::s_dbusmenu_menuitem_property_get_bool +#define dbusmenu_menuitem_property_remove nsDbusmenuFunctions::s_dbusmenu_menuitem_property_remove +#define dbusmenu_menuitem_property_set nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set +#define dbusmenu_menuitem_property_set_bool nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set_bool +#define dbusmenu_menuitem_property_set_int nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set_int +#define dbusmenu_menuitem_show_to_user nsDbusmenuFunctions::s_dbusmenu_menuitem_show_to_user +#define dbusmenu_menuitem_take_children nsDbusmenuFunctions::s_dbusmenu_menuitem_take_children +#define dbusmenu_server_new nsDbusmenuFunctions::s_dbusmenu_server_new +#define dbusmenu_server_set_root nsDbusmenuFunctions::s_dbusmenu_server_set_root +#define dbusmenu_server_set_status nsDbusmenuFunctions::s_dbusmenu_server_set_status + +#define dbusmenu_menuitem_property_set_image nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set_image +#define dbusmenu_menuitem_property_set_shortcut nsDbusmenuFunctions::s_dbusmenu_menuitem_property_set_shortcut + +#endif /* __nsDbusmenu_h__ */ diff --git a/widget/gtk/nsMenu.cpp b/widget/gtk/nsMenu.cpp new file mode 100644 index 0000000000..073a4acf65 --- /dev/null +++ b/widget/gtk/nsMenu.cpp @@ -0,0 +1,800 @@ +/* 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/. */ + +#define _IMPL_NS_LAYOUT + +#include "mozilla/dom/Element.h" +#include "mozilla/Assertions.h" +#include "mozilla/GuardObjects.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/Move.h" +#include "mozilla/StyleSetHandleInlines.h" +#include "nsAutoPtr.h" +#include "nsBindingManager.h" +#include "nsComponentManagerUtils.h" +#include "nsContentUtils.h" +#include "nsCSSValue.h" +#include "nsGkAtoms.h" +#include "nsGtkUtils.h" +#include "nsIAtom.h" +#include "nsIContent.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIRunnable.h" +#include "nsITimer.h" +#include "nsString.h" +#include "nsStyleContext.h" +#include "nsStyleSet.h" +#include "nsStyleStruct.h" +#include "nsThreadUtils.h" +#include "nsXBLBinding.h" +#include "nsXBLService.h" + +#include "nsNativeMenuAtoms.h" +#include "nsNativeMenuDocListener.h" + +#include + +#include "nsMenu.h" + +using namespace mozilla; + +class nsMenuContentInsertedEvent : public Runnable { +public: + nsMenuContentInsertedEvent(nsMenu* aMenu, + nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling) : + mWeakMenu(aMenu), + mContainer(aContainer), + mChild(aChild), + mPrevSibling(aPrevSibling) { } + + NS_IMETHODIMP Run() { + if (!mWeakMenu) { + return NS_OK; + } + + static_cast(mWeakMenu.get())->HandleContentInserted(mContainer, + mChild, + mPrevSibling); + return NS_OK; + } + +private: + nsWeakMenuObject mWeakMenu; + + nsCOMPtr mContainer; + nsCOMPtr mChild; + nsCOMPtr mPrevSibling; +}; + +class nsMenuContentRemovedEvent : public Runnable { +public: + nsMenuContentRemovedEvent(nsMenu* aMenu, + nsIContent* aContainer, + nsIContent* aChild) : + mWeakMenu(aMenu), + mContainer(aContainer), + mChild(aChild) { } + + NS_IMETHODIMP Run() { + if (!mWeakMenu) { + return NS_OK; + } + + static_cast(mWeakMenu.get())->HandleContentRemoved(mContainer, + mChild); + return NS_OK; + } + +private: + nsWeakMenuObject mWeakMenu; + + nsCOMPtr mContainer; + nsCOMPtr mChild; +}; + +static void +DispatchMouseEvent(nsIContent* aTarget, mozilla::EventMessage aMsg) { + if (!aTarget) { + return; + } + + WidgetMouseEvent event(true, aMsg, nullptr, WidgetMouseEvent::eReal); + aTarget->DispatchDOMEvent(&event, nullptr, nullptr, nullptr); +} + +static void +AttachXBLBindings(nsIContent* aContent) { + nsIDocument* doc = aContent->OwnerDoc(); + nsIPresShell* shell = doc->GetShell(); + if (!shell) { + return; + } + + RefPtr sc = + shell->StyleSet()->AsGecko()->ResolveStyleFor(aContent->AsElement(), + nullptr); + if (!sc) { + return; + } + + const nsStyleDisplay* display = sc->StyleDisplay(); + if (!display->mBinding) { + return; + } + + nsXBLService* xbl = nsXBLService::GetInstance(); + if (!xbl) { + return; + } + + RefPtr binding; + bool dummy; + nsresult rv = xbl->LoadBindings(aContent, display->mBinding->GetURI(), + display->mBinding->mOriginPrincipal, + getter_AddRefs(binding), &dummy); + if ((NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED) || !binding) { + return; + } + + doc->BindingManager()->AddToAttachedQueue(binding); +} + +void +nsMenu::SetPopupState(EPopupState aState) { + mPopupState = aState; + + if (!mPopupContent) { + return; + } + + nsAutoString state; + switch (aState) { + case ePopupState_Showing: + state.Assign(NS_LITERAL_STRING("showing")); + break; + case ePopupState_Open: + state.Assign(NS_LITERAL_STRING("open")); + break; + case ePopupState_Hiding: + state.Assign(NS_LITERAL_STRING("hiding")); + break; + default: + break; + } + + if (state.IsEmpty()) { + mPopupContent->UnsetAttr(kNameSpaceID_None, + nsNativeMenuAtoms::_moz_nativemenupopupstate, + false); + } else { + mPopupContent->SetAttr(kNameSpaceID_None, + nsNativeMenuAtoms::_moz_nativemenupopupstate, + state, false); + } +} + +/* static */ void +nsMenu::DoOpenCallback(nsITimer* aTimer, void* aClosure) { + nsMenu* self = static_cast(aClosure); + + dbusmenu_menuitem_show_to_user(self->GetNativeData(), 0); + + self->mOpenDelayTimer = nullptr; +} + +/* static */ void +nsMenu::menu_event_cb(DbusmenuMenuitem* menu, + const gchar* name, + GVariant* value, + guint timestamp, + gpointer user_data) { + nsMenu* self = static_cast(user_data); + + nsAutoCString event(name); + + if (event.Equals(NS_LITERAL_CSTRING("closed"))) { + self->OnClose(); + return; + } + + if (event.Equals(NS_LITERAL_CSTRING("opened"))) { + self->OnOpen(); + return; + } +} + +void +nsMenu::MaybeAddPlaceholderItem() { + MOZ_ASSERT(!IsInBatchedUpdate(), + "Shouldn't be modifying the native menu structure now"); + + GList* children = dbusmenu_menuitem_get_children(GetNativeData()); + if (!children) { + MOZ_ASSERT(!mPlaceholderItem); + + mPlaceholderItem = dbusmenu_menuitem_new(); + if (!mPlaceholderItem) { + return; + } + + dbusmenu_menuitem_property_set_bool(mPlaceholderItem, + DBUSMENU_MENUITEM_PROP_VISIBLE, + false); + + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_append(GetNativeData(), mPlaceholderItem)); + } +} + +void +nsMenu::EnsureNoPlaceholderItem() { + MOZ_ASSERT(!IsInBatchedUpdate(), + "Shouldn't be modifying the native menu structure now"); + + if (!mPlaceholderItem) { + return; + } + + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_delete(GetNativeData(), mPlaceholderItem)); + MOZ_ASSERT(!dbusmenu_menuitem_get_children(GetNativeData())); + + g_object_unref(mPlaceholderItem); + mPlaceholderItem = nullptr; +} + +void +nsMenu::OnOpen() { + if (mNeedsRebuild) { + Build(); + } + + nsWeakMenuObject self(this); + nsCOMPtr origPopupContent(mPopupContent); + { + nsNativeMenuDocListener::BlockUpdatesScope updatesBlocker; + + SetPopupState(ePopupState_Showing); + DispatchMouseEvent(mPopupContent, eXULPopupShowing); + + ContentNode()->SetAttr(kNameSpaceID_None, nsGkAtoms::open, + NS_LITERAL_STRING("true"), true); + } + + if (!self) { + // We were deleted! + return; + } + + // I guess that the popup could have changed + if (origPopupContent != mPopupContent) { + return; + } + + nsNativeMenuDocListener::BlockUpdatesScope updatesBlocker; + + size_t count = ChildCount(); + for (size_t i = 0; i < count; ++i) { + ChildAt(i)->ContainerIsOpening(); + } + + SetPopupState(ePopupState_Open); + DispatchMouseEvent(mPopupContent, eXULPopupShown); +} + +void +nsMenu::Build() { + mNeedsRebuild = false; + + while (ChildCount() > 0) { + RemoveChildAt(0); + } + + InitializePopup(); + + if (!mPopupContent) { + return; + } + + uint32_t count = mPopupContent->GetChildCount(); + for (uint32_t i = 0; i < count; ++i) { + nsIContent* childContent = mPopupContent->GetChildAt(i); + + UniquePtr child = CreateChild(childContent); + + if (!child) { + continue; + } + + AppendChild(Move(child)); + } +} + +void +nsMenu::InitializePopup() { + nsCOMPtr oldPopupContent; + oldPopupContent.swap(mPopupContent); + + for (uint32_t i = 0; i < ContentNode()->GetChildCount(); ++i) { + nsIContent* child = ContentNode()->GetChildAt(i); + + int32_t dummy; + nsCOMPtr tag = child->OwnerDoc()->BindingManager()->ResolveTag(child, &dummy); + if (tag == nsGkAtoms::menupopup) { + mPopupContent = child; + break; + } + } + + if (oldPopupContent == mPopupContent) { + return; + } + + // The popup has changed + + if (oldPopupContent) { + DocListener()->UnregisterForContentChanges(oldPopupContent); + } + + SetPopupState(ePopupState_Closed); + + if (!mPopupContent) { + return; + } + + AttachXBLBindings(mPopupContent); + + DocListener()->RegisterForContentChanges(mPopupContent, this); +} + +void +nsMenu::RemoveChildAt(size_t aIndex) { + MOZ_ASSERT(IsInBatchedUpdate() || !mPlaceholderItem, + "Shouldn't have a placeholder menuitem"); + + nsMenuContainer::RemoveChildAt(aIndex, !IsInBatchedUpdate()); + StructureMutated(); + + if (!IsInBatchedUpdate()) { + MaybeAddPlaceholderItem(); + } +} + +void +nsMenu::RemoveChild(nsIContent* aChild) { + size_t index = IndexOf(aChild); + if (index == NoIndex) { + return; + } + + RemoveChildAt(index); +} + +void +nsMenu::InsertChildAfter(UniquePtr aChild, + nsIContent* aPrevSibling) { + if (!IsInBatchedUpdate()) { + EnsureNoPlaceholderItem(); + } + + nsMenuContainer::InsertChildAfter(Move(aChild), aPrevSibling, + !IsInBatchedUpdate()); + StructureMutated(); +} + +void +nsMenu::AppendChild(UniquePtr aChild) { + if (!IsInBatchedUpdate()) { + EnsureNoPlaceholderItem(); + } + + nsMenuContainer::AppendChild(Move(aChild), !IsInBatchedUpdate()); + StructureMutated(); +} + +bool +nsMenu::IsInBatchedUpdate() const { + return mBatchedUpdateState != eBatchedUpdateState_Inactive; +} + +void +nsMenu::StructureMutated() { + if (!IsInBatchedUpdate()) { + return; + } + + mBatchedUpdateState = eBatchedUpdateState_DidMutate; +} + +bool +nsMenu::CanOpen() const { + bool isVisible = dbusmenu_menuitem_property_get_bool(GetNativeData(), + DBUSMENU_MENUITEM_PROP_VISIBLE); + bool isDisabled = ContentNode()->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::disabled, + nsGkAtoms::_true, + eCaseMatters); + + return (isVisible && !isDisabled); +} + +void +nsMenu::HandleContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling) { + if (aContainer == mPopupContent) { + UniquePtr child = CreateChild(aChild); + + if (child) { + InsertChildAfter(Move(child), aPrevSibling); + } + } else { + Build(); + } +} + +void +nsMenu::HandleContentRemoved(nsIContent* aContainer, nsIContent* aChild) { + if (aContainer == mPopupContent) { + RemoveChild(aChild); + } else { + Build(); + } +} + +void +nsMenu::InitializeNativeData() { + // Dbusmenu provides an "about-to-show" signal, and also "opened" and + // "closed" events. However, Unity is the only thing that sends + // both "about-to-show" and "opened" events. Unity 2D and the HUD only + // send "opened" events, so we ignore "about-to-show" (I don't think + // there's any real difference between them anyway). + // To complicate things, there are certain conditions where we don't + // get a "closed" event, so we need to be able to handle this :/ + g_signal_connect(G_OBJECT(GetNativeData()), "event", + G_CALLBACK(menu_event_cb), this); + + mNeedsRebuild = true; + mNeedsUpdate = true; + + MaybeAddPlaceholderItem(); + + AttachXBLBindings(ContentNode()); +} + +void +nsMenu::Update(nsStyleContext* aStyleContext) { + if (mNeedsUpdate) { + mNeedsUpdate = false; + + UpdateLabel(); + UpdateSensitivity(); + } + + UpdateVisibility(aStyleContext); + UpdateIcon(aStyleContext); +} + +nsMenuObject::PropertyFlags +nsMenu::SupportedProperties() const { + return static_cast( + nsMenuObject::ePropLabel | + nsMenuObject::ePropEnabled | + nsMenuObject::ePropVisible | + nsMenuObject::ePropIconData | + nsMenuObject::ePropChildDisplay + ); +} + +void +nsMenu::OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) { + MOZ_ASSERT(aContent == ContentNode() || aContent == mPopupContent, + "Received an event that wasn't meant for us!"); + + if (mNeedsUpdate) { + return; + } + + if (aContent != ContentNode()) { + return; + } + + if (!Parent()->IsBeingDisplayed()) { + mNeedsUpdate = true; + return; + } + + if (aAttribute == nsGkAtoms::disabled) { + UpdateSensitivity(); + } else if (aAttribute == nsGkAtoms::label || + aAttribute == nsGkAtoms::accesskey || + aAttribute == nsGkAtoms::crop) { + UpdateLabel(); + } else if (aAttribute == nsGkAtoms::hidden || + aAttribute == nsGkAtoms::collapsed) { + RefPtr sc = GetStyleContext(); + UpdateVisibility(sc); + } else if (aAttribute == nsGkAtoms::image) { + RefPtr sc = GetStyleContext(); + UpdateIcon(sc); + } +} + +void +nsMenu::OnContentInserted(nsIContent* aContainer, nsIContent* aChild, + nsIContent* aPrevSibling) { + MOZ_ASSERT(aContainer == ContentNode() || aContainer == mPopupContent, + "Received an event that wasn't meant for us!"); + + if (mNeedsRebuild) { + return; + } + + if (mPopupState == ePopupState_Closed) { + mNeedsRebuild = true; + return; + } + + nsContentUtils::AddScriptRunner( + new nsMenuContentInsertedEvent(this, aContainer, aChild, + aPrevSibling)); +} + +void +nsMenu::OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) { + MOZ_ASSERT(aContainer == ContentNode() || aContainer == mPopupContent, + "Received an event that wasn't meant for us!"); + + if (mNeedsRebuild) { + return; + } + + if (mPopupState == ePopupState_Closed) { + mNeedsRebuild = true; + return; + } + + nsContentUtils::AddScriptRunner( + new nsMenuContentRemovedEvent(this, aContainer, aChild)); +} + +/* + * Some menus (eg, the History menu in Firefox) refresh themselves on + * opening by removing all children and then re-adding new ones. As this + * happens whilst the menu is opening in Unity, it causes some flickering + * as the menu popup is resized multiple times. To avoid this, we try to + * reuse native menu items when the menu structure changes during a + * batched update. If we can handle menu structure changes from Goanna + * just by updating properties of native menu items (rather than destroying + * and creating new ones), then we eliminate any flickering that occurs as + * the menu is opened. To do this, we don't modify any native menu items + * until the end of the update batch. + */ + +void +nsMenu::OnBeginUpdates(nsIContent* aContent) { + MOZ_ASSERT(aContent == ContentNode() || aContent == mPopupContent, + "Received an event that wasn't meant for us!"); + MOZ_ASSERT(!IsInBatchedUpdate(), "Already in an update batch!"); + + if (aContent != mPopupContent) { + return; + } + + mBatchedUpdateState = eBatchedUpdateState_Active; +} + +void +nsMenu::OnEndUpdates() { + if (!IsInBatchedUpdate()) { + return; + } + + bool didMutate = mBatchedUpdateState == eBatchedUpdateState_DidMutate; + mBatchedUpdateState = eBatchedUpdateState_Inactive; + + /* Optimize for the case where we only had attribute changes */ + if (!didMutate) { + return; + } + + EnsureNoPlaceholderItem(); + + GList* nextNativeChild = dbusmenu_menuitem_get_children(GetNativeData()); + DbusmenuMenuitem* nextOwnedNativeChild = nullptr; + + size_t count = ChildCount(); + + // Find the first native menu item that is `owned` by a corresponding + // Goanna menuitem + for (size_t i = 0; i < count; ++i) { + if (ChildAt(i)->GetNativeData()) { + nextOwnedNativeChild = ChildAt(i)->GetNativeData(); + break; + } + } + + // Now iterate over all Goanna menuitems + for (size_t i = 0; i < count; ++i) { + nsMenuObject* child = ChildAt(i); + + if (child->GetNativeData()) { + // This child already has a corresponding native menuitem. + // Remove all preceding orphaned native items. At this point, we + // modify the native menu structure. + while (nextNativeChild && + nextNativeChild->data != nextOwnedNativeChild) { + + DbusmenuMenuitem* data = + static_cast(nextNativeChild->data); + nextNativeChild = nextNativeChild->next; + + MOZ_ALWAYS_TRUE(dbusmenu_menuitem_child_delete(GetNativeData(), + data)); + } + + if (nextNativeChild) { + nextNativeChild = nextNativeChild->next; + } + + // Now find the next native menu item that is `owned` + nextOwnedNativeChild = nullptr; + for (size_t j = i + 1; j < count; ++j) { + if (ChildAt(j)->GetNativeData()) { + nextOwnedNativeChild = ChildAt(j)->GetNativeData(); + break; + } + } + } else { + // This child is new, and doesn't have a native menu item. Find one! + if (nextNativeChild && + nextNativeChild->data != nextOwnedNativeChild) { + + DbusmenuMenuitem* data = + static_cast(nextNativeChild->data); + + if (NS_SUCCEEDED(child->AdoptNativeData(data))) { + nextNativeChild = nextNativeChild->next; + } + } + + // There wasn't a suitable one available, so create a new one. + // At this point, we modify the native menu structure. + if (!child->GetNativeData()) { + child->CreateNativeData(); + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_add_position(GetNativeData(), + child->GetNativeData(), + i)); + } + } + } + + while (nextNativeChild) { + DbusmenuMenuitem* data = + static_cast(nextNativeChild->data); + nextNativeChild = nextNativeChild->next; + + MOZ_ALWAYS_TRUE(dbusmenu_menuitem_child_delete(GetNativeData(), data)); + } + + MaybeAddPlaceholderItem(); +} + +nsMenu::nsMenu(nsMenuContainer* aParent, nsIContent* aContent) : + nsMenuContainer(aParent, aContent), + mNeedsRebuild(false), + mNeedsUpdate(false), + mPlaceholderItem(nullptr), + mPopupState(ePopupState_Closed), + mBatchedUpdateState(eBatchedUpdateState_Inactive) { + MOZ_COUNT_CTOR(nsMenu); +} + +nsMenu::~nsMenu() { + if (IsInBatchedUpdate()) { + OnEndUpdates(); + } + + // Although nsTArray will take care of this in its destructor, + // we have to manually ensure children are removed from our native menu + // item, just in case our parent recycles us + while (ChildCount() > 0) { + RemoveChildAt(0); + } + + EnsureNoPlaceholderItem(); + + if (DocListener() && mPopupContent) { + DocListener()->UnregisterForContentChanges(mPopupContent); + } + + if (GetNativeData()) { + g_signal_handlers_disconnect_by_func(GetNativeData(), + FuncToGpointer(menu_event_cb), + this); + } + + MOZ_COUNT_DTOR(nsMenu); +} + +nsMenuObject::EType +nsMenu::Type() const { + return eType_Menu; +} + +bool +nsMenu::IsBeingDisplayed() const { + return mPopupState == ePopupState_Open; +} + +bool +nsMenu::NeedsRebuild() const { + return mNeedsRebuild; +} + +void +nsMenu::OpenMenu() { + if (!CanOpen()) { + return; + } + + if (mOpenDelayTimer) { + return; + } + + // Here, we synchronously fire popupshowing and popupshown events and then + // open the menu after a short delay. This allows the menu to refresh before + // it's shown, and avoids an issue where keyboard focus is not on the first + // item of the history menu in Firefox when opening it with the keyboard, + // because extra items to appear at the top of the menu + + OnOpen(); + + mOpenDelayTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + if (!mOpenDelayTimer) { + return; + } + + if (NS_FAILED(mOpenDelayTimer->InitWithFuncCallback(DoOpenCallback, + this, + 100, + nsITimer::TYPE_ONE_SHOT))) { + mOpenDelayTimer = nullptr; + } +} + +void +nsMenu::OnClose() { + if (mPopupState == ePopupState_Closed) { + return; + } + + MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + + // We do this to avoid mutating our view of the menu until + // after we have finished + nsNativeMenuDocListener::BlockUpdatesScope updatesBlocker; + + SetPopupState(ePopupState_Hiding); + DispatchMouseEvent(mPopupContent, eXULPopupHiding); + + // Sigh, make sure all of our descendants are closed, as we don't + // always get closed events for submenus when scrubbing quickly through + // the menu + size_t count = ChildCount(); + for (size_t i = 0; i < count; ++i) { + if (ChildAt(i)->Type() == nsMenuObject::eType_Menu) { + static_cast(ChildAt(i))->OnClose(); + } + } + + SetPopupState(ePopupState_Closed); + DispatchMouseEvent(mPopupContent, eXULPopupHidden); + + ContentNode()->UnsetAttr(kNameSpaceID_None, nsGkAtoms::open, true); +} diff --git a/widget/gtk/nsMenu.h b/widget/gtk/nsMenu.h new file mode 100644 index 0000000000..a198a8e723 --- /dev/null +++ b/widget/gtk/nsMenu.h @@ -0,0 +1,120 @@ +/* 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 __nsMenu_h__ +#define __nsMenu_h__ + +#include "mozilla/Attributes.h" +#include "mozilla/UniquePtr.h" +#include "nsCOMPtr.h" + +#include "nsDbusmenu.h" +#include "nsMenuContainer.h" +#include "nsMenuObject.h" + +#include + +class nsIAtom; +class nsIContent; +class nsITimer; +class nsStyleContext; + +#define NSMENU_NUMBER_OF_POPUPSTATE_BITS 2U +#define NSMENU_NUMBER_OF_FLAGS 4U + +// This class represents a menu +class nsMenu final : public nsMenuContainer { +public: + nsMenu(nsMenuContainer* aParent, nsIContent* aContent); + ~nsMenu(); + + nsMenuObject::EType Type() const override; + + bool IsBeingDisplayed() const override; + bool NeedsRebuild() const override; + + // Tell the desktop shell to display this menu + void OpenMenu(); + + // Normally called via the shell, but it's public so that child + // menuitems can do the shells work. Sigh.... + void OnClose(); + +private: + friend class nsMenuContentInsertedEvent; + friend class nsMenuContentRemovedEvent; + + enum EPopupState { + ePopupState_Closed, + ePopupState_Showing, + ePopupState_Open, + ePopupState_Hiding + }; + + void SetPopupState(EPopupState aState); + + static void DoOpenCallback(nsITimer* aTimer, void* aClosure); + static void menu_event_cb(DbusmenuMenuitem* menu, + const gchar* name, + GVariant* value, + guint timestamp, + gpointer user_data); + + // We add a placeholder item to empty menus so that Unity actually treats + // us as a proper menu, rather than a menuitem without a submenu + void MaybeAddPlaceholderItem(); + + // Removes a placeholder item if it exists and asserts that this succeeds + void EnsureNoPlaceholderItem(); + + void OnOpen(); + void Build(); + void InitializePopup(); + void RemoveChildAt(size_t aIndex); + void RemoveChild(nsIContent* aChild); + void InsertChildAfter(mozilla::UniquePtr aChild, + nsIContent* aPrevSibling); + void AppendChild(mozilla::UniquePtr aChild); + bool IsInBatchedUpdate() const; + void StructureMutated(); + bool CanOpen() const; + + void HandleContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling); + void HandleContentRemoved(nsIContent* aContainer, + nsIContent* aChild); + + void InitializeNativeData() override; + void Update(nsStyleContext* aStyleContext) override; + nsMenuObject::PropertyFlags SupportedProperties() const override; + + void OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) override; + void OnContentInserted(nsIContent* aContainer, nsIContent* aChild, + nsIContent* aPrevSibling) override; + void OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) override; + void OnBeginUpdates(nsIContent* aContent) override; + void OnEndUpdates() override; + + bool mNeedsRebuild; + bool mNeedsUpdate; + + DbusmenuMenuitem* mPlaceholderItem; + + EPopupState mPopupState; + + enum EBatchedUpdateState { + eBatchedUpdateState_Inactive, + eBatchedUpdateState_Active, + eBatchedUpdateState_DidMutate + }; + + EBatchedUpdateState mBatchedUpdateState; + + nsCOMPtr mPopupContent; + + nsCOMPtr mOpenDelayTimer; +}; + +#endif /* __nsMenu_h__ */ diff --git a/widget/gtk/nsMenuBar.cpp b/widget/gtk/nsMenuBar.cpp new file mode 100644 index 0000000000..e7caf119c6 --- /dev/null +++ b/widget/gtk/nsMenuBar.cpp @@ -0,0 +1,541 @@ +/* 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 "mozilla/Assertions.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/dom/Element.h" +#include "mozilla/Move.h" +#include "mozilla/Preferences.h" +#include "nsAutoPtr.h" +#include "nsContentUtils.h" +#include "nsIDocument.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventListener.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMKeyEvent.h" +#include "nsIRunnable.h" +#include "nsIWidget.h" +#include "nsTArray.h" +#include "nsUnicharUtils.h" + +#include "nsMenu.h" +#include "nsNativeMenuAtoms.h" +#include "nsNativeMenuService.h" + +#include +#include +#include +#include + +#include "nsMenuBar.h" + +using namespace mozilla; + +static bool +ShouldHandleKeyEvent(nsIDOMEvent* aEvent) { + bool handled, trusted = false; + aEvent->GetPreventDefault(&handled); + aEvent->GetIsTrusted(&trusted); + + if (handled || !trusted) { + return false; + } + + return true; +} + +class nsMenuBarContentInsertedEvent : public Runnable { +public: + nsMenuBarContentInsertedEvent(nsMenuBar* aMenuBar, + nsIContent* aChild, + nsIContent* aPrevSibling) : + mWeakMenuBar(aMenuBar), + mChild(aChild), + mPrevSibling(aPrevSibling) { } + + NS_IMETHODIMP Run() + { + if (!mWeakMenuBar) { + return NS_OK; + } + + static_cast(mWeakMenuBar.get())->HandleContentInserted(mChild, + mPrevSibling); + return NS_OK; + } + +private: + nsWeakMenuObject mWeakMenuBar; + + nsCOMPtr mChild; + nsCOMPtr mPrevSibling; +}; + +class nsMenuBarContentRemovedEvent : public Runnable { +public: + nsMenuBarContentRemovedEvent(nsMenuBar* aMenuBar, + nsIContent* aChild) : + mWeakMenuBar(aMenuBar), + mChild(aChild) { } + + NS_IMETHODIMP Run() + { + if (!mWeakMenuBar) { + return NS_OK; + } + + static_cast(mWeakMenuBar.get())->HandleContentRemoved(mChild); + return NS_OK; + } + +private: + nsWeakMenuObject mWeakMenuBar; + + nsCOMPtr mChild; +}; + +class nsMenuBar::DocEventListener final : public nsIDOMEventListener { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMEVENTLISTENER + + DocEventListener(nsMenuBar* aOwner) : mOwner(aOwner) { }; + +private: + ~DocEventListener() { }; + + nsMenuBar* mOwner; +}; + +NS_IMPL_ISUPPORTS(nsMenuBar::DocEventListener, nsIDOMEventListener) + +NS_IMETHODIMP +nsMenuBar::DocEventListener::HandleEvent(nsIDOMEvent* aEvent) { + nsAutoString type; + nsresult rv = aEvent->GetType(type); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to determine event type"); + return rv; + } + + if (type.Equals(NS_LITERAL_STRING("focus"))) { + mOwner->Focus(); + } else if (type.Equals(NS_LITERAL_STRING("blur"))) { + mOwner->Blur(); + } else if (type.Equals(NS_LITERAL_STRING("keypress"))) { + rv = mOwner->Keypress(aEvent); + } else if (type.Equals(NS_LITERAL_STRING("keydown"))) { + rv = mOwner->KeyDown(aEvent); + } else if (type.Equals(NS_LITERAL_STRING("keyup"))) { + rv = mOwner->KeyUp(aEvent); + } + + return rv; +} + +nsMenuBar::nsMenuBar(nsIContent* aMenuBarNode) : + nsMenuContainer(new nsNativeMenuDocListener(aMenuBarNode), aMenuBarNode), + mTopLevel(nullptr), + mServer(nullptr), + mIsActive(false) { + MOZ_COUNT_CTOR(nsMenuBar); +} + +nsresult +nsMenuBar::Init(nsIWidget* aParent) { + MOZ_ASSERT(aParent); + + GdkWindow* gdkWin = static_cast( + aParent->GetNativeData(NS_NATIVE_WINDOW)); + if (!gdkWin) { + return NS_ERROR_FAILURE; + } + + gpointer user_data = nullptr; + gdk_window_get_user_data(gdkWin, &user_data); + if (!user_data || !GTK_IS_CONTAINER(user_data)) { + return NS_ERROR_FAILURE; + } + + mTopLevel = gtk_widget_get_toplevel(GTK_WIDGET(user_data)); + if (!mTopLevel) { + return NS_ERROR_FAILURE; + } + + g_object_ref(mTopLevel); + + nsAutoCString path; + path.Append(NS_LITERAL_CSTRING("/com/canonical/menu/")); + char xid[10]; + sprintf(xid, "%X", static_cast( + GDK_WINDOW_XID(gtk_widget_get_window(mTopLevel)))); + path.Append(xid); + + mServer = dbusmenu_server_new(path.get()); + if (!mServer) { + return NS_ERROR_FAILURE; + } + + CreateNativeData(); + if (!GetNativeData()) { + return NS_ERROR_FAILURE; + } + + dbusmenu_server_set_root(mServer, GetNativeData()); + + mEventListener = new DocEventListener(this); + + mDocument = do_QueryInterface(ContentNode()->OwnerDoc()); + + mAccessKey = Preferences::GetInt("ui.key.menuAccessKey"); + if (mAccessKey == nsIDOMKeyEvent::DOM_VK_SHIFT) { + mAccessKeyMask = eModifierShift; + } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_CONTROL) { + mAccessKeyMask = eModifierCtrl; + } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_ALT) { + mAccessKeyMask = eModifierAlt; + } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_META) { + mAccessKeyMask = eModifierMeta; + } else { + mAccessKeyMask = eModifierAlt; + } + + return NS_OK; +} + +void +nsMenuBar::Build() { + uint32_t count = ContentNode()->GetChildCount(); + for (uint32_t i = 0; i < count; ++i) { + nsIContent* childContent = ContentNode()->GetChildAt(i); + + UniquePtr child = CreateChild(childContent); + + if (!child) { + continue; + } + + AppendChild(Move(child)); + } +} + +void +nsMenuBar::DisconnectDocumentEventListeners() { + mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), + mEventListener, + true); + mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), + mEventListener, + true); + mDocument->RemoveEventListener(NS_LITERAL_STRING("keypress"), + mEventListener, + false); + mDocument->RemoveEventListener(NS_LITERAL_STRING("keydown"), + mEventListener, + false); + mDocument->RemoveEventListener(NS_LITERAL_STRING("keyup"), + mEventListener, + false); +} + +void +nsMenuBar::SetShellShowingMenuBar(bool aShowing) { + ContentNode()->OwnerDoc()->GetRootElement()->SetAttr( + kNameSpaceID_None, nsNativeMenuAtoms::shellshowingmenubar, + aShowing ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), + true); +} + +void +nsMenuBar::Focus() { + ContentNode()->SetAttr(kNameSpaceID_None, nsNativeMenuAtoms::openedwithkey, + NS_LITERAL_STRING("false"), true); +} + +void +nsMenuBar::Blur() { + // We do this here in case we lose focus before getting the + // keyup event, which leaves the menubar state looking like + // the alt key is stuck down + dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NORMAL); +} + +nsMenuBar::ModifierFlags +nsMenuBar::GetModifiersFromEvent(nsIDOMKeyEvent* aEvent) { + ModifierFlags modifiers = static_cast(0); + bool modifier; + + aEvent->GetAltKey(&modifier); + if (modifier) { + modifiers = static_cast(modifiers | eModifierAlt); + } + + aEvent->GetShiftKey(&modifier); + if (modifier) { + modifiers = static_cast(modifiers | eModifierShift); + } + + aEvent->GetCtrlKey(&modifier); + if (modifier) { + modifiers = static_cast(modifiers | eModifierCtrl); + } + + aEvent->GetMetaKey(&modifier); + if (modifier) { + modifiers = static_cast(modifiers | eModifierMeta); + } + + return modifiers; +} + +nsresult +nsMenuBar::Keypress(nsIDOMEvent* aEvent) { + if (!ShouldHandleKeyEvent(aEvent)) { + return NS_OK; + } + + nsCOMPtr keyEvent = do_QueryInterface(aEvent); + if (!keyEvent) { + return NS_OK; + } + + ModifierFlags modifiers = GetModifiersFromEvent(keyEvent); + if (((modifiers & mAccessKeyMask) == 0) || + ((modifiers & ~mAccessKeyMask) != 0)) { + return NS_OK; + } + + uint32_t charCode; + keyEvent->GetCharCode(&charCode); + if (charCode == 0) { + return NS_OK; + } + + char16_t ch = char16_t(charCode); + char16_t chl = ToLowerCase(ch); + char16_t chu = ToUpperCase(ch); + + nsMenuObject* found = nullptr; + uint32_t count = ChildCount(); + for (uint32_t i = 0; i < count; ++i) { + nsAutoString accesskey; + ChildAt(i)->ContentNode()->GetAttr(kNameSpaceID_None, + nsGkAtoms::accesskey, + accesskey); + const nsAutoString::char_type* key = accesskey.BeginReading(); + if (*key == chu ||* key == chl) { + found = ChildAt(i); + break; + } + } + + if (!found || found->Type() != nsMenuObject::eType_Menu) { + return NS_OK; + } + + ContentNode()->SetAttr(kNameSpaceID_None, nsNativeMenuAtoms::openedwithkey, + NS_LITERAL_STRING("true"), true); + static_cast(found)->OpenMenu(); + + aEvent->StopPropagation(); + aEvent->PreventDefault(); + + return NS_OK; +} + +nsresult +nsMenuBar::KeyDown(nsIDOMEvent* aEvent) { + if (!ShouldHandleKeyEvent(aEvent)) { + return NS_OK; + } + + nsCOMPtr keyEvent = do_QueryInterface(aEvent); + if (!keyEvent) { + return NS_OK; + } + + uint32_t keyCode; + keyEvent->GetKeyCode(&keyCode); + ModifierFlags modifiers = GetModifiersFromEvent(keyEvent); + if ((keyCode != mAccessKey) || ((modifiers & ~mAccessKeyMask) != 0)) { + return NS_OK; + } + + dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NOTICE); + + return NS_OK; +} + +nsresult +nsMenuBar::KeyUp(nsIDOMEvent* aEvent) { + if (!ShouldHandleKeyEvent(aEvent)) { + return NS_OK; + } + + nsCOMPtr keyEvent = do_QueryInterface(aEvent); + if (!keyEvent) { + return NS_OK; + } + + uint32_t keyCode; + keyEvent->GetKeyCode(&keyCode); + if (keyCode == mAccessKey) { + dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NORMAL); + } + + return NS_OK; +} + +void +nsMenuBar::HandleContentInserted(nsIContent* aChild, nsIContent* aPrevSibling) { + UniquePtr child = CreateChild(aChild); + + if (!child) { + return; + } + + InsertChildAfter(Move(child), aPrevSibling); +} + +void +nsMenuBar::HandleContentRemoved(nsIContent* aChild) { + RemoveChild(aChild); +} + +void +nsMenuBar::OnContentInserted(nsIContent* aContainer, nsIContent* aChild, + nsIContent* aPrevSibling) { + MOZ_ASSERT(aContainer == ContentNode(), + "Received an event that wasn't meant for us"); + + nsContentUtils::AddScriptRunner( + new nsMenuBarContentInsertedEvent(this, aChild, aPrevSibling)); +} + +void +nsMenuBar::OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) { + MOZ_ASSERT(aContainer == ContentNode(), + "Received an event that wasn't meant for us"); + + nsContentUtils::AddScriptRunner( + new nsMenuBarContentRemovedEvent(this, aChild)); +} + +nsMenuBar::~nsMenuBar() { + nsNativeMenuService* service = nsNativeMenuService::GetSingleton(); + if (service) { + service->NotifyNativeMenuBarDestroyed(this); + } + + if (ContentNode()) { + SetShellShowingMenuBar(false); + } + + // We want to destroy all children before dropping our reference + // to the doc listener + while (ChildCount() > 0) { + RemoveChildAt(0); + } + + if (mTopLevel) { + g_object_unref(mTopLevel); + } + + if (DocListener()) { + DocListener()->Stop(); + } + + if (mDocument) { + DisconnectDocumentEventListeners(); + } + + if (mServer) { + g_object_unref(mServer); + } + + MOZ_COUNT_DTOR(nsMenuBar); +} + +/* static */ UniquePtr +nsMenuBar::Create(nsIWidget* aParent, nsIContent* aMenuBarNode) { + UniquePtr menubar(new nsMenuBar(aMenuBarNode)); + if (NS_FAILED(menubar->Init(aParent))) { + return nullptr; + } + + return Move(menubar); +} + +nsMenuObject::EType +nsMenuBar::Type() const { + return eType_MenuBar; +} + +bool +nsMenuBar::IsBeingDisplayed() const { + return true; +} + +uint32_t +nsMenuBar::WindowId() const { + return static_cast(GDK_WINDOW_XID(gtk_widget_get_window(mTopLevel))); +} + +nsAdoptingCString +nsMenuBar::ObjectPath() const { + gchar* tmp; + g_object_get(mServer, DBUSMENU_SERVER_PROP_DBUS_OBJECT, &tmp, NULL); + nsAdoptingCString result(tmp); + + return result; +} + +void +nsMenuBar::Activate() { + if (mIsActive) { + return; + } + + mIsActive = true; + + mDocument->AddEventListener(NS_LITERAL_STRING("focus"), + mEventListener, + true); + mDocument->AddEventListener(NS_LITERAL_STRING("blur"), + mEventListener, + true); + mDocument->AddEventListener(NS_LITERAL_STRING("keypress"), + mEventListener, + false); + mDocument->AddEventListener(NS_LITERAL_STRING("keydown"), + mEventListener, + false); + mDocument->AddEventListener(NS_LITERAL_STRING("keyup"), + mEventListener, + false); + + // Clear this. Not sure if we really need to though + ContentNode()->SetAttr(kNameSpaceID_None, nsNativeMenuAtoms::openedwithkey, + NS_LITERAL_STRING("false"), true); + + DocListener()->Start(); + Build(); + SetShellShowingMenuBar(true); +} + +void +nsMenuBar::Deactivate() { + if (!mIsActive) { + return; + } + + mIsActive = false; + + SetShellShowingMenuBar(false); + while (ChildCount() > 0) { + RemoveChildAt(0); + } + DocListener()->Stop(); + DisconnectDocumentEventListeners(); +} diff --git a/widget/gtk/nsMenuBar.h b/widget/gtk/nsMenuBar.h new file mode 100644 index 0000000000..9ce1796512 --- /dev/null +++ b/widget/gtk/nsMenuBar.h @@ -0,0 +1,103 @@ +/* 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 __nsMenuBar_h__ +#define __nsMenuBar_h__ + +#include "mozilla/Attributes.h" +#include "mozilla/UniquePtr.h" +#include "nsCOMPtr.h" +#include "nsString.h" + +#include "nsDbusmenu.h" +#include "nsMenuContainer.h" +#include "nsMenuObject.h" + +#include + +class nsIAtom; +class nsIContent; +class nsIDOMEvent; +class nsIDOMKeyEvent; +class nsIWidget; +class nsMenuBarDocEventListener; + +/* + * The menubar class. There is one of these per window (and the window + * owns its menubar). Each menubar has an object path, and the service is + * responsible for telling the desktop shell which object path corresponds + * to a particular window. A menubar and its hierarchy also own a + * nsNativeMenuDocListener. + */ +class nsMenuBar final : public nsMenuContainer { +public: + ~nsMenuBar() override; + + static mozilla::UniquePtr Create(nsIWidget* aParent, + nsIContent* aMenuBarNode); + + nsMenuObject::EType Type() const override; + + bool IsBeingDisplayed() const override; + + // Get the native window ID for this menubar + uint32_t WindowId() const; + + // Get the object path for this menubar + nsAdoptingCString ObjectPath() const; + + // Get the top-level GtkWindow handle + GtkWidget* TopLevelWindow() { return mTopLevel; } + + // Called from the menuservice when the menubar is about to be registered. + // Causes the native menubar to be created, and the XUL menubar to be hidden + void Activate(); + + // Called from the menuservice when the menubar is no longer registered + // with the desktop shell. Will cause the XUL menubar to be shown again + void Deactivate(); + +private: + class DocEventListener; + friend class nsMenuBarContentInsertedEvent; + friend class nsMenuBarContentRemovedEvent; + + enum ModifierFlags { + eModifierShift = (1 << 0), + eModifierCtrl = (1 << 1), + eModifierAlt = (1 << 2), + eModifierMeta = (1 << 3) + }; + + nsMenuBar(nsIContent* aMenuBarNode); + nsresult Init(nsIWidget* aParent); + void Build(); + void DisconnectDocumentEventListeners(); + void SetShellShowingMenuBar(bool aShowing); + void Focus(); + void Blur(); + ModifierFlags GetModifiersFromEvent(nsIDOMKeyEvent* aEvent); + nsresult Keypress(nsIDOMEvent* aEvent); + nsresult KeyDown(nsIDOMEvent* aEvent); + nsresult KeyUp(nsIDOMEvent* aEvent); + + void HandleContentInserted(nsIContent* aChild, + nsIContent* aPrevSibling); + void HandleContentRemoved(nsIContent* aChild); + + void OnContentInserted(nsIContent* aContainer, nsIContent* aChild, + nsIContent* aPrevSibling) override; + void OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) override; + + GtkWidget* mTopLevel; + DbusmenuServer* mServer; + nsCOMPtr mDocument; + RefPtr mEventListener; + + uint32_t mAccessKey; + ModifierFlags mAccessKeyMask; + bool mIsActive; +}; + +#endif /* __nsMenuBar_h__ */ diff --git a/widget/gtk/nsMenuContainer.cpp b/widget/gtk/nsMenuContainer.cpp new file mode 100644 index 0000000000..081e98a6ae --- /dev/null +++ b/widget/gtk/nsMenuContainer.cpp @@ -0,0 +1,156 @@ +/* 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 "mozilla/DebugOnly.h" +#include "mozilla/Move.h" +#include "nsGkAtoms.h" +#include "nsIAtom.h" +#include "nsIContent.h" + +#include "nsDbusmenu.h" +#include "nsMenu.h" +#include "nsMenuItem.h" +#include "nsMenuSeparator.h" + +#include "nsMenuContainer.h" + +using namespace mozilla; + +const nsMenuContainer::ChildTArray::index_type nsMenuContainer::NoIndex = nsMenuContainer::ChildTArray::NoIndex; + +typedef UniquePtr (*nsMenuObjectConstructor)(nsMenuContainer*, + nsIContent*); + +template +static UniquePtr CreateMenuObject(nsMenuContainer* aContainer, + nsIContent* aContent) { + return UniquePtr(new T(aContainer, aContent)); +} + +static nsMenuObjectConstructor +GetMenuObjectConstructor(nsIContent* aContent) { + if (aContent->IsXULElement(nsGkAtoms::menuitem)) { + return CreateMenuObject; + } else if (aContent->IsXULElement(nsGkAtoms::menu)) { + return CreateMenuObject; + } else if (aContent->IsXULElement(nsGkAtoms::menuseparator)) { + return CreateMenuObject; + } + + return nullptr; +} + +static bool +ContentIsSupported(nsIContent* aContent) { + return GetMenuObjectConstructor(aContent) ? true : false; +} + +nsMenuContainer::nsMenuContainer(nsMenuContainer* aParent, + nsIContent* aContent) : + nsMenuObject(aParent, aContent) { +} + +nsMenuContainer::nsMenuContainer(nsNativeMenuDocListener* aListener, + nsIContent* aContent) : + nsMenuObject(aListener, aContent) { +} + +UniquePtr +nsMenuContainer::CreateChild(nsIContent* aContent) { + nsMenuObjectConstructor ctor = GetMenuObjectConstructor(aContent); + if (!ctor) { + // There are plenty of node types we might stumble across that + // aren't supported + return nullptr; + } + + UniquePtr res = ctor(this, aContent); + return Move(res); +} + +size_t +nsMenuContainer::IndexOf(nsIContent* aChild) const { + if (!aChild) { + return NoIndex; + } + + size_t count = ChildCount(); + for (size_t i = 0; i < count; ++i) { + if (ChildAt(i)->ContentNode() == aChild) { + return i; + } + } + + return NoIndex; +} + +void +nsMenuContainer::RemoveChildAt(size_t aIndex, bool aUpdateNative) { + MOZ_ASSERT(aIndex < ChildCount()); + + if (aUpdateNative) { + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_delete(GetNativeData(), + ChildAt(aIndex)->GetNativeData())); + } + + mChildren.RemoveElementAt(aIndex); +} + +void +nsMenuContainer::RemoveChild(nsIContent* aChild, bool aUpdateNative) { + size_t index = IndexOf(aChild); + if (index == NoIndex) { + return; + } + + RemoveChildAt(index, aUpdateNative); +} + +void +nsMenuContainer::InsertChildAfter(UniquePtr aChild, + nsIContent* aPrevSibling, + bool aUpdateNative) { + size_t index = IndexOf(aPrevSibling); + MOZ_ASSERT(!aPrevSibling || index != NoIndex); + + ++index; + + if (aUpdateNative) { + aChild->CreateNativeData(); + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_add_position(GetNativeData(), + aChild->GetNativeData(), + index)); + } + + MOZ_ALWAYS_TRUE(mChildren.InsertElementAt(index, Move(aChild))); +} + +void +nsMenuContainer::AppendChild(UniquePtr aChild, + bool aUpdateNative) { + if (aUpdateNative) { + aChild->CreateNativeData(); + MOZ_ALWAYS_TRUE( + dbusmenu_menuitem_child_append(GetNativeData(), + aChild->GetNativeData())); + } + + MOZ_ALWAYS_TRUE(mChildren.AppendElement(Move(aChild))); +} + +bool +nsMenuContainer::NeedsRebuild() const { + return false; +} + +/* static */ nsIContent* +nsMenuContainer::GetPreviousSupportedSibling(nsIContent* aContent) { + do { + aContent = aContent->GetPreviousSibling(); + } while (aContent && !ContentIsSupported(aContent)); + + return aContent; +} diff --git a/widget/gtk/nsMenuContainer.h b/widget/gtk/nsMenuContainer.h new file mode 100644 index 0000000000..95d65a2f1e --- /dev/null +++ b/widget/gtk/nsMenuContainer.h @@ -0,0 +1,66 @@ +/* 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 __nsMenuContainer_h__ +#define __nsMenuContainer_h__ + +#include "mozilla/UniquePtr.h" +#include "nsTArray.h" + +#include "nsMenuObject.h" + +class nsIContent; +class nsNativeMenuDocListener; + +// Base class for containers (menus and menubars) +class nsMenuContainer : public nsMenuObject { +public: + typedef nsTArray > ChildTArray; + + // Determine if this container is being displayed on screen. Must be + // implemented by subclasses. Must return true if the container is + // in the fully open state, or false otherwise + virtual bool IsBeingDisplayed() const = 0; + + // Determine if this container will be rebuilt the next time it opens. + // Returns false by default but can be overridden by subclasses + virtual bool NeedsRebuild() const; + + // Return the first previous sibling that is of a type supported by the + // menu system + static nsIContent* GetPreviousSupportedSibling(nsIContent* aContent); + + static const ChildTArray::index_type NoIndex; + +protected: + nsMenuContainer(nsMenuContainer* aParent, nsIContent* aContent); + nsMenuContainer(nsNativeMenuDocListener* aListener, nsIContent* aContent); + + // Create a new child element for the specified content node + mozilla::UniquePtr CreateChild(nsIContent* aContent); + + // Return the index of the child for the specified content node + size_t IndexOf(nsIContent* aChild) const; + + size_t ChildCount() const { return mChildren.Length(); } + nsMenuObject* ChildAt(size_t aIndex) const { return mChildren[aIndex].get(); } + + void RemoveChildAt(size_t aIndex, bool aUpdateNative = true); + + // Remove the child that owns the specified content node + void RemoveChild(nsIContent* aChild, bool aUpdateNative = true); + + // Insert a new child after the child that owns the specified content node + void InsertChildAfter(mozilla::UniquePtr aChild, + nsIContent* aPrevSibling, + bool aUpdateNative = true); + + void AppendChild(mozilla::UniquePtr aChild, + bool aUpdateNative = true); + +private: + ChildTArray mChildren; +}; + +#endif /* __nsMenuContainer_h__ */ diff --git a/widget/gtk/nsMenuItem.cpp b/widget/gtk/nsMenuItem.cpp new file mode 100644 index 0000000000..00cc5477c9 --- /dev/null +++ b/widget/gtk/nsMenuItem.cpp @@ -0,0 +1,712 @@ +/* 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 "mozilla/ArrayUtils.h" +#include "mozilla/Assertions.h" +#include "mozilla/dom/Element.h" +#include "mozilla/Move.h" +#include "mozilla/Preferences.h" +#include "mozilla/TextEvents.h" +#include "nsAutoPtr.h" +#include "nsContentUtils.h" +#include "nsCRT.h" +#include "nsGkAtoms.h" +#include "nsGtkUtils.h" +#include "nsIContent.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMKeyEvent.h" +#include "nsIDOMXULCommandEvent.h" +#include "nsIRunnable.h" +#include "nsReadableUtils.h" +#include "nsString.h" +#include "nsStyleContext.h" +#include "nsThreadUtils.h" + +#include "nsMenu.h" +#include "nsMenuBar.h" +#include "nsMenuContainer.h" +#include "nsNativeMenuDocListener.h" + +#include +#include +#if (MOZ_WIDGET_GTK == 3) +#include +#endif +#include +#include + +#include "nsMenuItem.h" + +using namespace mozilla; + +struct KeyCodeData { + const char* str; + size_t strlength; + uint32_t keycode; +}; + +static struct KeyCodeData gKeyCodes[] = { +#define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \ + { #aDOMKeyName, sizeof(#aDOMKeyName) - 1, aDOMKeyCode }, +#include "mozilla/VirtualKeyCodeList.h" +#undef NS_DEFINE_VK + { nullptr, 0, 0 } +}; + +struct KeyPair { + uint32_t DOMKeyCode; + guint GDKKeyval; +}; + +// +// Netscape keycodes are defined in widget/public/nsGUIEvent.h +// GTK keycodes are defined in +// +static const KeyPair gKeyPairs[] = { + { NS_VK_CANCEL, GDK_Cancel }, + { NS_VK_BACK, GDK_BackSpace }, + { NS_VK_TAB, GDK_Tab }, + { NS_VK_TAB, GDK_ISO_Left_Tab }, + { NS_VK_CLEAR, GDK_Clear }, + { NS_VK_RETURN, GDK_Return }, + { NS_VK_SHIFT, GDK_Shift_L }, + { NS_VK_SHIFT, GDK_Shift_R }, + { NS_VK_SHIFT, GDK_Shift_Lock }, + { NS_VK_CONTROL, GDK_Control_L }, + { NS_VK_CONTROL, GDK_Control_R }, + { NS_VK_ALT, GDK_Alt_L }, + { NS_VK_ALT, GDK_Alt_R }, + { NS_VK_META, GDK_Meta_L }, + { NS_VK_META, GDK_Meta_R }, + + // Assume that Super or Hyper is always mapped to physical Win key. + { NS_VK_WIN, GDK_Super_L }, + { NS_VK_WIN, GDK_Super_R }, + { NS_VK_WIN, GDK_Hyper_L }, + { NS_VK_WIN, GDK_Hyper_R }, + + // GTK's AltGraph key is similar to Mac's Option (Alt) key. However, + // unfortunately, browsers on Mac are using NS_VK_ALT for it even though + // it's really different from Alt key on Windows. + // On the other hand, GTK's AltGrapsh keys are really different from + // Alt key. However, there is no AltGrapsh key on Windows. On Windows, + // both Ctrl and Alt keys are pressed internally when AltGr key is pressed. + // For some languages' users, AltGraph key is important, so, web + // applications on such locale may want to know AltGraph key press. + // Therefore, we should map AltGr keycode for them only on GTK. + { NS_VK_ALTGR, GDK_ISO_Level3_Shift }, + { NS_VK_ALTGR, GDK_ISO_Level5_Shift }, + // We assume that Mode_switch is always used for level3 shift. + { NS_VK_ALTGR, GDK_Mode_switch }, + + { NS_VK_PAUSE, GDK_Pause }, + { NS_VK_CAPS_LOCK, GDK_Caps_Lock }, + { NS_VK_KANA, GDK_Kana_Lock }, + { NS_VK_KANA, GDK_Kana_Shift }, + { NS_VK_HANGUL, GDK_Hangul }, + // { NS_VK_JUNJA, GDK_XXX }, + // { NS_VK_FINAL, GDK_XXX }, + { NS_VK_HANJA, GDK_Hangul_Hanja }, + { NS_VK_KANJI, GDK_Kanji }, + { NS_VK_ESCAPE, GDK_Escape }, + { NS_VK_CONVERT, GDK_Henkan }, + { NS_VK_NONCONVERT, GDK_Muhenkan }, + // { NS_VK_ACCEPT, GDK_XXX }, + // { NS_VK_MODECHANGE, GDK_XXX }, + { NS_VK_SPACE, GDK_space }, + { NS_VK_PAGE_UP, GDK_Page_Up }, + { NS_VK_PAGE_DOWN, GDK_Page_Down }, + { NS_VK_END, GDK_End }, + { NS_VK_HOME, GDK_Home }, + { NS_VK_LEFT, GDK_Left }, + { NS_VK_UP, GDK_Up }, + { NS_VK_RIGHT, GDK_Right }, + { NS_VK_DOWN, GDK_Down }, + { NS_VK_SELECT, GDK_Select }, + { NS_VK_PRINT, GDK_Print }, + { NS_VK_EXECUTE, GDK_Execute }, + { NS_VK_PRINTSCREEN, GDK_Print }, + { NS_VK_INSERT, GDK_Insert }, + { NS_VK_DELETE, GDK_Delete }, + { NS_VK_HELP, GDK_Help }, + + // keypad keys + { NS_VK_LEFT, GDK_KP_Left }, + { NS_VK_RIGHT, GDK_KP_Right }, + { NS_VK_UP, GDK_KP_Up }, + { NS_VK_DOWN, GDK_KP_Down }, + { NS_VK_PAGE_UP, GDK_KP_Page_Up }, + // Not sure what these are + //{ NS_VK_, GDK_KP_Prior }, + //{ NS_VK_, GDK_KP_Next }, + { NS_VK_CLEAR, GDK_KP_Begin }, // Num-unlocked 5 + { NS_VK_PAGE_DOWN, GDK_KP_Page_Down }, + { NS_VK_HOME, GDK_KP_Home }, + { NS_VK_END, GDK_KP_End }, + { NS_VK_INSERT, GDK_KP_Insert }, + { NS_VK_DELETE, GDK_KP_Delete }, + { NS_VK_RETURN, GDK_KP_Enter }, + + { NS_VK_NUM_LOCK, GDK_Num_Lock }, + { NS_VK_SCROLL_LOCK,GDK_Scroll_Lock }, + + // Function keys + { NS_VK_F1, GDK_F1 }, + { NS_VK_F2, GDK_F2 }, + { NS_VK_F3, GDK_F3 }, + { NS_VK_F4, GDK_F4 }, + { NS_VK_F5, GDK_F5 }, + { NS_VK_F6, GDK_F6 }, + { NS_VK_F7, GDK_F7 }, + { NS_VK_F8, GDK_F8 }, + { NS_VK_F9, GDK_F9 }, + { NS_VK_F10, GDK_F10 }, + { NS_VK_F11, GDK_F11 }, + { NS_VK_F12, GDK_F12 }, + { NS_VK_F13, GDK_F13 }, + { NS_VK_F14, GDK_F14 }, + { NS_VK_F15, GDK_F15 }, + { NS_VK_F16, GDK_F16 }, + { NS_VK_F17, GDK_F17 }, + { NS_VK_F18, GDK_F18 }, + { NS_VK_F19, GDK_F19 }, + { NS_VK_F20, GDK_F20 }, + { NS_VK_F21, GDK_F21 }, + { NS_VK_F22, GDK_F22 }, + { NS_VK_F23, GDK_F23 }, + { NS_VK_F24, GDK_F24 }, + + // context menu key, keysym 0xff67, typically keycode 117 on 105-key (Microsoft) + // x86 keyboards, located between right 'Windows' key and right Ctrl key + { NS_VK_CONTEXT_MENU, GDK_Menu }, + { NS_VK_SLEEP, GDK_Sleep }, + + { NS_VK_ATTN, GDK_3270_Attn }, + { NS_VK_CRSEL, GDK_3270_CursorSelect }, + { NS_VK_EXSEL, GDK_3270_ExSelect }, + { NS_VK_EREOF, GDK_3270_EraseEOF }, + { NS_VK_PLAY, GDK_3270_Play }, + //{ NS_VK_ZOOM, GDK_XXX }, + { NS_VK_PA1, GDK_3270_PA1 }, +}; + +static guint +ConvertGeckoKeyNameToGDKKeyval(nsAString& aKeyName) { + NS_ConvertUTF16toUTF8 keyName(aKeyName); + ToUpperCase(keyName); // We want case-insensitive comparison with data + // stored as uppercase. + + uint32_t keyCode = 0; + + uint32_t keyNameLength = keyName.Length(); + const char* keyNameStr = keyName.get(); + for (uint16_t i = 0; i < ArrayLength(gKeyCodes); ++i) { + if (keyNameLength == gKeyCodes[i].strlength && + !nsCRT::strcmp(gKeyCodes[i].str, keyNameStr)) { + keyCode = gKeyCodes[i].keycode; + break; + } + } + + // First, try to handle alphanumeric input, not listed in nsKeycodes: + // most likely, more letters will be getting typed in than things in + // the key list, so we will look through these first. + + if (keyCode >= NS_VK_A && keyCode <= NS_VK_Z) { + // gdk and DOM both use the ASCII codes for these keys. + return keyCode; + } + + // numbers + if (keyCode >= NS_VK_0 && keyCode <= NS_VK_9) { + // gdk and DOM both use the ASCII codes for these keys. + return keyCode - NS_VK_0 + GDK_0; + } + + switch (keyCode) { + // keys in numpad + case NS_VK_MULTIPLY: return GDK_KP_Multiply; + case NS_VK_ADD: return GDK_KP_Add; + case NS_VK_SEPARATOR: return GDK_KP_Separator; + case NS_VK_SUBTRACT: return GDK_KP_Subtract; + case NS_VK_DECIMAL: return GDK_KP_Decimal; + case NS_VK_DIVIDE: return GDK_KP_Divide; + case NS_VK_NUMPAD0: return GDK_KP_0; + case NS_VK_NUMPAD1: return GDK_KP_1; + case NS_VK_NUMPAD2: return GDK_KP_2; + case NS_VK_NUMPAD3: return GDK_KP_3; + case NS_VK_NUMPAD4: return GDK_KP_4; + case NS_VK_NUMPAD5: return GDK_KP_5; + case NS_VK_NUMPAD6: return GDK_KP_6; + case NS_VK_NUMPAD7: return GDK_KP_7; + case NS_VK_NUMPAD8: return GDK_KP_8; + case NS_VK_NUMPAD9: return GDK_KP_9; + // other prinable keys + case NS_VK_SPACE: return GDK_space; + case NS_VK_COLON: return GDK_colon; + case NS_VK_SEMICOLON: return GDK_semicolon; + case NS_VK_LESS_THAN: return GDK_less; + case NS_VK_EQUALS: return GDK_equal; + case NS_VK_GREATER_THAN: return GDK_greater; + case NS_VK_QUESTION_MARK: return GDK_question; + case NS_VK_AT: return GDK_at; + case NS_VK_CIRCUMFLEX: return GDK_asciicircum; + case NS_VK_EXCLAMATION: return GDK_exclam; + case NS_VK_DOUBLE_QUOTE: return GDK_quotedbl; + case NS_VK_HASH: return GDK_numbersign; + case NS_VK_DOLLAR: return GDK_dollar; + case NS_VK_PERCENT: return GDK_percent; + case NS_VK_AMPERSAND: return GDK_ampersand; + case NS_VK_UNDERSCORE: return GDK_underscore; + case NS_VK_OPEN_PAREN: return GDK_parenleft; + case NS_VK_CLOSE_PAREN: return GDK_parenright; + case NS_VK_ASTERISK: return GDK_asterisk; + case NS_VK_PLUS: return GDK_plus; + case NS_VK_PIPE: return GDK_bar; + case NS_VK_HYPHEN_MINUS: return GDK_minus; + case NS_VK_OPEN_CURLY_BRACKET: return GDK_braceleft; + case NS_VK_CLOSE_CURLY_BRACKET: return GDK_braceright; + case NS_VK_TILDE: return GDK_asciitilde; + case NS_VK_COMMA: return GDK_comma; + case NS_VK_PERIOD: return GDK_period; + case NS_VK_SLASH: return GDK_slash; + case NS_VK_BACK_QUOTE: return GDK_grave; + case NS_VK_OPEN_BRACKET: return GDK_bracketleft; + case NS_VK_BACK_SLASH: return GDK_backslash; + case NS_VK_CLOSE_BRACKET: return GDK_bracketright; + case NS_VK_QUOTE: return GDK_apostrophe; + } + + // misc other things + for (uint32_t i = 0; i < ArrayLength(gKeyPairs); ++i) { + if (gKeyPairs[i].DOMKeyCode == keyCode) { + return gKeyPairs[i].GDKKeyval; + } + } + + return 0; +} + +class nsMenuItemUncheckSiblingsRunnable final : public Runnable { +public: + NS_IMETHODIMP Run() { + if (mMenuItem) { + static_cast(mMenuItem.get())->UncheckSiblings(); + } + return NS_OK; + } + + nsMenuItemUncheckSiblingsRunnable(nsMenuItem* aMenuItem) : + mMenuItem(aMenuItem) { }; + +private: + nsWeakMenuObject mMenuItem; +}; + +bool +nsMenuItem::IsCheckboxOrRadioItem() const { + return mType == eMenuItemType_Radio || + mType == eMenuItemType_CheckBox; +} + +/* static */ void +nsMenuItem::item_activated_cb(DbusmenuMenuitem* menuitem, + guint timestamp, + gpointer user_data) { + nsMenuItem* item = static_cast(user_data); + item->Activate(timestamp); +} + +void +nsMenuItem::Activate(uint32_t aTimestamp) { + GdkWindow* window = gtk_widget_get_window(MenuBar()->TopLevelWindow()); + gdk_x11_window_set_user_time( + window, std::min(aTimestamp, gdk_x11_get_server_time(window))); + + // We do this to avoid mutating our view of the menu until + // after we have finished + nsNativeMenuDocListener::BlockUpdatesScope updatesBlocker; + + if (!ContentNode()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocheck, + nsGkAtoms::_false, eCaseMatters) && + (mType == eMenuItemType_CheckBox || + (mType == eMenuItemType_Radio && !mIsChecked))) { + ContentNode()->SetAttr(kNameSpaceID_None, nsGkAtoms::checked, + mIsChecked ? + NS_LITERAL_STRING("false") : NS_LITERAL_STRING("true"), + true); + } + + nsIDocument* doc = ContentNode()->OwnerDoc(); + nsCOMPtr target = do_QueryInterface(ContentNode()); + nsCOMPtr domDoc = do_QueryInterface(doc); + if (domDoc && target) { + nsCOMPtr event; + domDoc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), + getter_AddRefs(event)); + nsCOMPtr command = do_QueryInterface(event); + if (command) { + command->InitCommandEvent(NS_LITERAL_STRING("command"), + true, true, doc->GetInnerWindow(), 0, + false, false, false, false, nullptr); + + event->SetTrusted(true); + bool dummy; + target->DispatchEvent(event, &dummy); + } + } + + // This kinda sucks, but Unity doesn't send a closed event + // after activating a menuitem + nsMenuObject* ancestor = Parent(); + while (ancestor && ancestor->Type() == eType_Menu) { + static_cast(ancestor)->OnClose(); + ancestor = ancestor->Parent(); + } +} + +void +nsMenuItem::CopyAttrFromNodeIfExists(nsIContent* aContent, nsIAtom* aAttribute) { + nsAutoString value; + if (aContent->GetAttr(kNameSpaceID_None, aAttribute, value)) { + ContentNode()->SetAttr(kNameSpaceID_None, aAttribute, value, true); + } +} + +void +nsMenuItem::UpdateState() { + if (!IsCheckboxOrRadioItem()) { + return; + } + + mIsChecked = ContentNode()->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::checked, + nsGkAtoms::_true, + eCaseMatters); + dbusmenu_menuitem_property_set_int(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, + mIsChecked ? + DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : + DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); +} + +void +nsMenuItem::UpdateTypeAndState() { + static nsIContent::AttrValuesArray attrs[] = + { &nsGkAtoms::checkbox, &nsGkAtoms::radio, nullptr }; + int32_t type = ContentNode()->FindAttrValueIn(kNameSpaceID_None, + nsGkAtoms::type, + attrs, eCaseMatters); + + if (type >= 0 && type < 2) { + if (type == 0) { + dbusmenu_menuitem_property_set(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, + DBUSMENU_MENUITEM_TOGGLE_CHECK); + mType = eMenuItemType_CheckBox; + } else if (type == 1) { + dbusmenu_menuitem_property_set(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, + DBUSMENU_MENUITEM_TOGGLE_RADIO); + mType = eMenuItemType_Radio; + } + + UpdateState(); + } else { + dbusmenu_menuitem_property_remove(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE); + dbusmenu_menuitem_property_remove(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TOGGLE_STATE); + mType = eMenuItemType_Normal; + } +} + +void +nsMenuItem::UpdateAccel() { + nsIDocument* doc = ContentNode()->GetUncomposedDoc(); + if (doc) { + nsCOMPtr oldKeyContent; + oldKeyContent.swap(mKeyContent); + + nsAutoString key; + ContentNode()->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key); + if (!key.IsEmpty()) { + mKeyContent = doc->GetElementById(key); + } + + if (mKeyContent != oldKeyContent) { + if (oldKeyContent) { + DocListener()->UnregisterForContentChanges(oldKeyContent); + } + if (mKeyContent) { + DocListener()->RegisterForContentChanges(mKeyContent, this); + } + } + } + + if (!mKeyContent) { + dbusmenu_menuitem_property_remove(GetNativeData(), + DBUSMENU_MENUITEM_PROP_SHORTCUT); + return; + } + + nsAutoString modifiers; + mKeyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiers); + + uint32_t modifier = 0; + + if (!modifiers.IsEmpty()) { + char* str = ToNewUTF8String(modifiers); + char* token = strtok(str, ", \t"); + while(token) { + if (nsCRT::strcmp(token, "shift") == 0) { + modifier |= GDK_SHIFT_MASK; + } else if (nsCRT::strcmp(token, "alt") == 0) { + modifier |= GDK_MOD1_MASK; + } else if (nsCRT::strcmp(token, "meta") == 0) { + modifier |= GDK_META_MASK; + } else if (nsCRT::strcmp(token, "control") == 0) { + modifier |= GDK_CONTROL_MASK; + } else if (nsCRT::strcmp(token, "accel") == 0) { + int32_t accel = Preferences::GetInt("ui.key.accelKey"); + if (accel == nsIDOMKeyEvent::DOM_VK_META) { + modifier |= GDK_META_MASK; + } else if (accel == nsIDOMKeyEvent::DOM_VK_ALT) { + modifier |= GDK_MOD1_MASK; + } else { + modifier |= GDK_CONTROL_MASK; + } + } + + token = strtok(nullptr, ", \t"); + } + + free(str); + } + + nsAutoString keyStr; + mKeyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr); + + guint key = 0; + if (!keyStr.IsEmpty()) { + key = gdk_unicode_to_keyval(*keyStr.BeginReading()); + } + + if (key == 0) { + mKeyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyStr); + if (!keyStr.IsEmpty()) { + key = ConvertGeckoKeyNameToGDKKeyval(keyStr); + } + } + + if (key == 0) { + key = GDK_VoidSymbol; + } + + if (key != GDK_VoidSymbol) { + dbusmenu_menuitem_property_set_shortcut(GetNativeData(), key, + static_cast(modifier)); + } else { + dbusmenu_menuitem_property_remove(GetNativeData(), + DBUSMENU_MENUITEM_PROP_SHORTCUT); + } +} + +nsMenuBar* +nsMenuItem::MenuBar() { + nsMenuObject* tmp = this; + while (tmp->Parent()) { + tmp = tmp->Parent(); + } + + MOZ_ASSERT(tmp->Type() == eType_MenuBar, "The top-level should be a menubar"); + + return static_cast(tmp); +} + +void +nsMenuItem::UncheckSiblings() { + if (!ContentNode()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, + nsGkAtoms::radio, eCaseMatters)) { + // If we're not a radio button, we don't care + return; + } + + nsAutoString name; + ContentNode()->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name); + + nsIContent* parent = ContentNode()->GetParent(); + if (!parent) { + return; + } + + uint32_t count = parent->GetChildCount(); + for (uint32_t i = 0; i < count; ++i) { + nsIContent* sibling = parent->GetChildAt(i); + + nsAutoString otherName; + sibling->GetAttr(kNameSpaceID_None, nsGkAtoms::name, otherName); + + if (sibling != ContentNode() && otherName == name && + sibling->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, + nsGkAtoms::radio, eCaseMatters)) { + sibling->UnsetAttr(kNameSpaceID_None, nsGkAtoms::checked, true); + } + } +} + +void +nsMenuItem::InitializeNativeData() { + g_signal_connect(G_OBJECT(GetNativeData()), + DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(item_activated_cb), this); + mNeedsUpdate = true; +} + +void +nsMenuItem::UpdateContentAttributes() { + nsIDocument* doc = ContentNode()->GetUncomposedDoc(); + if (!doc) { + return; + } + + nsAutoString command; + ContentNode()->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command); + if (command.IsEmpty()) { + return; + } + + nsCOMPtr commandContent = doc->GetElementById(command); + if (!commandContent) { + return; + } + + if (commandContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, + nsGkAtoms::_true, eCaseMatters)) { + ContentNode()->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, + NS_LITERAL_STRING("true"), true); + } else { + ContentNode()->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true); + } + + CopyAttrFromNodeIfExists(commandContent, nsGkAtoms::checked); + CopyAttrFromNodeIfExists(commandContent, nsGkAtoms::accesskey); + CopyAttrFromNodeIfExists(commandContent, nsGkAtoms::label); + CopyAttrFromNodeIfExists(commandContent, nsGkAtoms::hidden); +} + +void +nsMenuItem::Update(nsStyleContext* aStyleContext) { + if (mNeedsUpdate) { + mNeedsUpdate = false; + + UpdateTypeAndState(); + UpdateAccel(); + UpdateLabel(); + UpdateSensitivity(); + } + + UpdateVisibility(aStyleContext); + UpdateIcon(aStyleContext); +} + +bool +nsMenuItem::IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const { + return nsCRT::strcmp(dbusmenu_menuitem_property_get(aNativeData, + DBUSMENU_MENUITEM_PROP_TYPE), + "separator") != 0; +} + +nsMenuObject::PropertyFlags +nsMenuItem::SupportedProperties() const { + return static_cast( + nsMenuObject::ePropLabel | + nsMenuObject::ePropEnabled | + nsMenuObject::ePropVisible | + nsMenuObject::ePropIconData | + nsMenuObject::ePropShortcut | + nsMenuObject::ePropToggleType | + nsMenuObject::ePropToggleState + ); +} + +void +nsMenuItem::OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) { + MOZ_ASSERT(aContent == ContentNode() || aContent == mKeyContent, + "Received an event that wasn't meant for us!"); + + if (aContent == ContentNode() && aAttribute == nsGkAtoms::checked && + aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, + nsGkAtoms::_true, eCaseMatters)) { + nsContentUtils::AddScriptRunner( + new nsMenuItemUncheckSiblingsRunnable(this)); + } + + if (mNeedsUpdate) { + return; + } + + if (!Parent()->IsBeingDisplayed()) { + mNeedsUpdate = true; + return; + } + + if (aContent == ContentNode()) { + if (aAttribute == nsGkAtoms::key) { + UpdateAccel(); + } else if (aAttribute == nsGkAtoms::label || + aAttribute == nsGkAtoms::accesskey || + aAttribute == nsGkAtoms::crop) { + UpdateLabel(); + } else if (aAttribute == nsGkAtoms::disabled) { + UpdateSensitivity(); + } else if (aAttribute == nsGkAtoms::type) { + UpdateTypeAndState(); + } else if (aAttribute == nsGkAtoms::checked) { + UpdateState(); + } else if (aAttribute == nsGkAtoms::hidden || + aAttribute == nsGkAtoms::collapsed) { + RefPtr sc = GetStyleContext(); + UpdateVisibility(sc); + } else if (aAttribute == nsGkAtoms::image) { + RefPtr sc = GetStyleContext(); + UpdateIcon(sc); + } + } else if (aContent == mKeyContent && + (aAttribute == nsGkAtoms::key || + aAttribute == nsGkAtoms::keycode || + aAttribute == nsGkAtoms::modifiers)) { + UpdateAccel(); + } +} + +nsMenuItem::nsMenuItem(nsMenuContainer* aParent, nsIContent* aContent) : + nsMenuObject(aParent, aContent), + mType(eMenuItemType_Normal), + mIsChecked(false), + mNeedsUpdate(false) { + MOZ_COUNT_CTOR(nsMenuItem); +} + +nsMenuItem::~nsMenuItem() { + if (DocListener() && mKeyContent) { + DocListener()->UnregisterForContentChanges(mKeyContent); + } + + if (GetNativeData()) { + g_signal_handlers_disconnect_by_func(GetNativeData(), + FuncToGpointer(item_activated_cb), + this); + } + + MOZ_COUNT_DTOR(nsMenuItem); +} + +nsMenuObject::EType +nsMenuItem::Type() const { + return eType_MenuItem; +} diff --git a/widget/gtk/nsMenuItem.h b/widget/gtk/nsMenuItem.h new file mode 100644 index 0000000000..e81b6e3086 --- /dev/null +++ b/widget/gtk/nsMenuItem.h @@ -0,0 +1,77 @@ +/* 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 __nsMenuItem_h__ +#define __nsMenuItem_h__ + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" + +#include "nsDbusmenu.h" +#include "nsMenuObject.h" + +#include + +class nsIAtom; +class nsIContent; +class nsStyleContext; +class nsMenuBar; +class nsMenuContainer; + +/* + * This class represents 3 main classes of menuitems: labels, checkboxes and + * radio buttons (with/without an icon) + */ +class nsMenuItem final : public nsMenuObject { +public: + nsMenuItem(nsMenuContainer* aParent, nsIContent* aContent); + ~nsMenuItem() override; + + nsMenuObject::EType Type() const override; + +private: + friend class nsMenuItemUncheckSiblingsRunnable; + + enum { + eMenuItemFlag_ToggleState = (1 << 0) + }; + + enum EMenuItemType { + eMenuItemType_Normal, + eMenuItemType_Radio, + eMenuItemType_CheckBox + }; + + bool IsCheckboxOrRadioItem() const; + + static void item_activated_cb(DbusmenuMenuitem* menuitem, + guint timestamp, + gpointer user_data); + void Activate(uint32_t aTimestamp); + + void CopyAttrFromNodeIfExists(nsIContent* aContent, nsIAtom* aAtom); + void UpdateState(); + void UpdateTypeAndState(); + void UpdateAccel(); + nsMenuBar* MenuBar(); + void UncheckSiblings(); + + void InitializeNativeData() override; + void UpdateContentAttributes() override; + void Update(nsStyleContext* aStyleContext) override; + bool IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const override; + nsMenuObject::PropertyFlags SupportedProperties() const override; + + void OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) override; + + EMenuItemType mType; + + bool mIsChecked; + + bool mNeedsUpdate; + + nsCOMPtr mKeyContent; +}; + +#endif /* __nsMenuItem_h__ */ diff --git a/widget/gtk/nsMenuObject.cpp b/widget/gtk/nsMenuObject.cpp new file mode 100644 index 0000000000..58d1716fd2 --- /dev/null +++ b/widget/gtk/nsMenuObject.cpp @@ -0,0 +1,634 @@ +/* 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 "ImageOps.h" +#include "imgIContainer.h" +#include "imgINotificationObserver.h" +#include "imgLoader.h" +#include "imgRequestProxy.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/Assertions.h" +#include "mozilla/dom/Element.h" +#include "mozilla/Preferences.h" +#include "nsAttrValue.h" +#include "nsComputedDOMStyle.h" +#include "nsContentUtils.h" +#include "nsGkAtoms.h" +#include "nsIContent.h" +#include "nsIContentPolicy.h" +#include "nsIDocument.h" +#include "nsILoadGroup.h" +#include "nsImageToPixbuf.h" +#include "nsIPresShell.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsPresContext.h" +#include "nsRect.h" +#include "nsServiceManagerUtils.h" +#include "nsString.h" +#include "nsStyleConsts.h" +#include "nsStyleContext.h" +#include "nsStyleStruct.h" +#include "nsUnicharUtils.h" + +#include "nsMenuContainer.h" +#include "nsNativeMenuAtoms.h" +#include "nsNativeMenuDocListener.h" + +#include +#include +#include + +#include "nsMenuObject.h" + +// X11's None clashes with StyleDisplay::None +#include "X11UndefineNone.h" + +#undef None + +using namespace mozilla; +using mozilla::image::ImageOps; + +#define MAX_WIDTH 350000 + +const char* gPropertyStrings[] = { +#define DBUSMENU_PROPERTY(e, s, b) s, + DBUSMENU_PROPERTIES +#undef DBUSMENU_PROPERTY + nullptr +}; + +nsWeakMenuObject* nsWeakMenuObject::sHead; +PangoLayout* gPangoLayout = nullptr; + +class nsMenuObjectIconLoader final : public imgINotificationObserver { +public: + NS_DECL_ISUPPORTS + NS_DECL_IMGINOTIFICATIONOBSERVER + + nsMenuObjectIconLoader(nsMenuObject* aOwner) : mOwner(aOwner) { }; + + void LoadIcon(nsStyleContext* aStyleContext); + void Destroy(); + +private: + ~nsMenuObjectIconLoader() { }; + + nsMenuObject* mOwner; + RefPtr mImageRequest; + nsCOMPtr mURI; + nsIntRect mImageRect; +}; + +NS_IMPL_ISUPPORTS(nsMenuObjectIconLoader, imgINotificationObserver) + +NS_IMETHODIMP +nsMenuObjectIconLoader::Notify(imgIRequest* aProxy, + int32_t aType, const nsIntRect* aRect) { + if (!mOwner) { + return NS_OK; + } + + if (aProxy != mImageRequest) { + return NS_ERROR_FAILURE; + } + + if (aType == imgINotificationObserver::LOAD_COMPLETE) { + uint32_t status = imgIRequest::STATUS_ERROR; + if (NS_FAILED(mImageRequest->GetImageStatus(&status)) || + (status & imgIRequest::STATUS_ERROR)) { + mImageRequest->Cancel(NS_BINDING_ABORTED); + mImageRequest = nullptr; + return NS_ERROR_FAILURE; + } + + nsCOMPtr image; + mImageRequest->GetImage(getter_AddRefs(image)); + MOZ_ASSERT(image); + + // Ask the image to decode at its intrinsic size. + int32_t width = 0, height = 0; + image->GetWidth(&width); + image->GetHeight(&height); + image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE); + return NS_OK; + } + + if (aType == imgINotificationObserver::DECODE_COMPLETE) { + mImageRequest->Cancel(NS_BINDING_ABORTED); + mImageRequest = nullptr; + return NS_OK; + } + + if (aType != imgINotificationObserver::FRAME_COMPLETE) { + return NS_OK; + } + + nsCOMPtr img; + mImageRequest->GetImage(getter_AddRefs(img)); + if (!img) { + return NS_ERROR_FAILURE; + } + + if (!mImageRect.IsEmpty()) { + img = ImageOps::Clip(img, mImageRect); + } + + int32_t width, height; + img->GetWidth(&width); + img->GetHeight(&height); + + if (width <= 0 || height <= 0) { + mOwner->ClearIcon(); + return NS_OK; + } + + if (width > 100 || height > 100) { + // The icon data needs to go across DBus. Make sure the icon + // data isn't too large, else our connection gets terminated and + // GDbus helpfully aborts the application. Thank you :) + NS_WARNING("Icon data too large"); + mOwner->ClearIcon(); + return NS_OK; + } + + GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(img); + if (pixbuf) { + dbusmenu_menuitem_property_set_image(mOwner->GetNativeData(), + DBUSMENU_MENUITEM_PROP_ICON_DATA, + pixbuf); + g_object_unref(pixbuf); + } + + return NS_OK; +} + +void +nsMenuObjectIconLoader::LoadIcon(nsStyleContext* aStyleContext) { + nsIDocument* doc = mOwner->ContentNode()->OwnerDoc(); + + nsCOMPtr uri; + nsIntRect imageRect; + imgRequestProxy* imageRequest = nullptr; + + nsAutoString uriString; + if (mOwner->ContentNode()->GetAttr(kNameSpaceID_None, nsGkAtoms::image, + uriString)) { + NS_NewURI(getter_AddRefs(uri), uriString); + } else { + nsIPresShell* shell = doc->GetShell(); + if (!shell) { + return; + } + + nsPresContext* pc = shell->GetPresContext(); + if (!pc || !aStyleContext) { + return; + } + + const nsStyleList* list = aStyleContext->StyleList(); + imageRequest = list->GetListStyleImage(); + if (imageRequest) { + imageRequest->GetURI(getter_AddRefs(uri)); + imageRect = list->mImageRegion.ToNearestPixels( + pc->AppUnitsPerDevPixel()); + } + } + + if (!uri) { + mOwner->ClearIcon(); + mURI = nullptr; + + if (mImageRequest) { + mImageRequest->Cancel(NS_BINDING_ABORTED); + mImageRequest = nullptr; + } + + return; + } + + bool same; + if (mURI && NS_SUCCEEDED(mURI->Equals(uri, &same)) && same && + (!imageRequest || imageRect == mImageRect)) { + return; + } + + if (mImageRequest) { + mImageRequest->Cancel(NS_BINDING_ABORTED); + mImageRequest = nullptr; + } + + mURI = uri; + + if (imageRequest) { + mImageRect = imageRect; + imageRequest->Clone(this, getter_AddRefs(mImageRequest)); + } else { + mImageRect.SetEmpty(); + nsCOMPtr loadGroup = doc->GetDocumentLoadGroup(); + RefPtr loader = + nsContentUtils::GetImgLoaderForDocument(doc); + if (!loader || !loadGroup) { + NS_WARNING("Failed to get loader or load group for image load"); + return; + } + + loader->LoadImage(uri, nullptr, nullptr, mozilla::net::RP_Unset, + nullptr, loadGroup, this, nullptr, nullptr, + nsIRequest::LOAD_NORMAL, nullptr, + nsIContentPolicy::TYPE_IMAGE, EmptyString(), + getter_AddRefs(mImageRequest)); + } +} + +void +nsMenuObjectIconLoader::Destroy() { + if (mImageRequest) { + mImageRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); + mImageRequest = nullptr; + } + + mOwner = nullptr; +} + +static int +CalculateTextWidth(const nsAString& aText) { + if (!gPangoLayout) { + PangoFontMap* fontmap = pango_cairo_font_map_get_default(); + PangoContext* ctx = pango_font_map_create_context(fontmap); + gPangoLayout = pango_layout_new(ctx); + g_object_unref(ctx); + } + + pango_layout_set_text(gPangoLayout, NS_ConvertUTF16toUTF8(aText).get(), -1); + + int width, dummy; + pango_layout_get_size(gPangoLayout, &width, &dummy); + + return width; +} + +static const nsDependentString +GetEllipsis() { + static char16_t sBuf[4] = { 0, 0, 0, 0 }; + if (!sBuf[0]) { + nsAdoptingString ellipsis = Preferences::GetLocalizedString("intl.ellipsis"); + if (!ellipsis.IsEmpty()) { + uint32_t l = ellipsis.Length(); + const nsAdoptingString::char_type* c = ellipsis.BeginReading(); + uint32_t i = 0; + while (i < 3 && i < l) { + sBuf[i++] =* (c++); + } + } else { + sBuf[0] = '.'; + sBuf[1] = '.'; + sBuf[2] = '.'; + } + } + + return nsDependentString(sBuf); +} + +static int +GetEllipsisWidth() { + static int sEllipsisWidth = -1; + + if (sEllipsisWidth == -1) { + sEllipsisWidth = CalculateTextWidth(GetEllipsis()); + } + + return sEllipsisWidth; +} + +nsMenuObject::nsMenuObject(nsMenuContainer* aParent, nsIContent* aContent) : + mContent(aContent), + mListener(aParent->DocListener()), + mParent(aParent), + mNativeData(nullptr) { + MOZ_ASSERT(mContent); + MOZ_ASSERT(mListener); + MOZ_ASSERT(mParent); +} + +nsMenuObject::nsMenuObject(nsNativeMenuDocListener* aListener, + nsIContent* aContent) : + mContent(aContent), + mListener(aListener), + mParent(nullptr), + mNativeData(nullptr) { + MOZ_ASSERT(mContent); + MOZ_ASSERT(mListener); +} + +void +nsMenuObject::UpdateLabel() { + // Goanna stores the label and access key in separate attributes + // so we need to convert label="Foo_Bar"/accesskey="F" in to + // label="_Foo__Bar" for dbusmenu + + nsAutoString label; + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, label); + + nsAutoString accesskey; + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accesskey); + + const nsAutoString::char_type* akey = accesskey.BeginReading(); + char16_t keyLower = ToLowerCase(*akey); + char16_t keyUpper = ToUpperCase(*akey); + + const nsAutoString::char_type* iter = label.BeginReading(); + const nsAutoString::char_type* end = label.EndReading(); + uint32_t length = label.Length(); + uint32_t pos = 0; + bool foundAccessKey = false; + + while (iter != end) { + if (*iter != char16_t('_')) { + if ((*iter != keyLower &&* iter != keyUpper) || foundAccessKey) { + ++iter; + ++pos; + continue; + } + foundAccessKey = true; + } + + label.SetLength(++length); + + iter = label.BeginReading() + pos; + end = label.EndReading(); + nsAutoString::char_type* cur = label.BeginWriting() + pos; + + memmove(cur + 1, cur, (length - 1 - pos)* sizeof(nsAutoString::char_type)); + * cur = nsAutoString::char_type('_'); + + iter += 2; + pos += 2; + } + + if (CalculateTextWidth(label) <= MAX_WIDTH) { + dbusmenu_menuitem_property_set(mNativeData, + DBUSMENU_MENUITEM_PROP_LABEL, + NS_ConvertUTF16toUTF8(label).get()); + return; + } + + // This sucks. + // This should be done at the point where the menu is drawn (hello Unity), + // but unfortunately it doesn't do that and will happily fill your entire + // screen width with a menu if you have a bookmark with a really long title. + // This leaves us with no other option but to ellipsize here, with no proper + // knowledge of Unity's render path, font size etc. This is better than nothing + nsAutoString truncated; + int target = MAX_WIDTH - GetEllipsisWidth(); + length = label.Length(); + + static nsIContent::AttrValuesArray strings[] = { + &nsGkAtoms::left, &nsGkAtoms::start, + &nsGkAtoms::center, &nsGkAtoms::right, + &nsGkAtoms::end, nullptr + }; + + int32_t type = mContent->FindAttrValueIn(kNameSpaceID_None, + nsGkAtoms::crop, + strings, eCaseMatters); + + switch (type) { + case 0: + case 1: + // FIXME: Implement left cropping + case 2: + // FIXME: Implement center cropping + case 3: + case 4: + default: + for (uint32_t i = 0; i < length; i++) { + truncated.Append(label.CharAt(i)); + if (CalculateTextWidth(truncated) > target) { + break; + } + } + + truncated.Append(GetEllipsis()); + } + + dbusmenu_menuitem_property_set(mNativeData, + DBUSMENU_MENUITEM_PROP_LABEL, + NS_ConvertUTF16toUTF8(truncated).get()); +} + +void +nsMenuObject::UpdateVisibility(nsStyleContext* aStyleContext) { + bool vis = true; + + if (aStyleContext && + (aStyleContext->StyleDisplay()->mDisplay == StyleDisplay::None || + aStyleContext->StyleVisibility()->mVisible == + NS_STYLE_VISIBILITY_COLLAPSE)) { + vis = false; + } + + dbusmenu_menuitem_property_set_bool(mNativeData, + DBUSMENU_MENUITEM_PROP_VISIBLE, + vis); +} + +void +nsMenuObject::UpdateSensitivity() { + bool disabled = mContent->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::disabled, + nsGkAtoms::_true, eCaseMatters); + + dbusmenu_menuitem_property_set_bool(mNativeData, + DBUSMENU_MENUITEM_PROP_ENABLED, + !disabled); + +} + +void +nsMenuObject::UpdateIcon(nsStyleContext* aStyleContext) { + if (ShouldShowIcon()) { + if (!mIconLoader) { + mIconLoader = new nsMenuObjectIconLoader(this); + } + + mIconLoader->LoadIcon(aStyleContext); + } else { + if (mIconLoader) { + mIconLoader->Destroy(); + mIconLoader = nullptr; + } + + ClearIcon(); + } +} + +already_AddRefed +nsMenuObject::GetStyleContext() { + nsIPresShell* shell = mContent->OwnerDoc()->GetShell(); + if (!shell) { + return nullptr; + } + + RefPtr sc = + nsComputedDOMStyle::GetStyleContextForElementNoFlush( + mContent->AsElement(), nullptr, shell); + + return sc.forget(); +} + +void +nsMenuObject::InitializeNativeData() { +} + +nsMenuObject::PropertyFlags +nsMenuObject::SupportedProperties() const { + return static_cast(0); +} + +bool +nsMenuObject::IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const { + return true; +} + +void +nsMenuObject::UpdateContentAttributes() { +} + +void +nsMenuObject::Update(nsStyleContext* aStyleContext) { +} + +bool +nsMenuObject::ShouldShowIcon() const { + // Ideally we want to know the visibility of the anonymous XUL image in + // our menuitem, but this isn't created because we don't have a frame. + // The following works by default (because xul.css hides images in menuitems + // that don't have the "menuitem-with-favicon" class). It's possible a third + // party theme could override this, but, oh well... + const nsAttrValue* classes = mContent->AsElement()->GetClasses(); + if (!classes) { + return false; + } + + for (uint32_t i = 0; i < classes->GetAtomCount(); ++i) { + if (classes->AtomAt(i) == nsNativeMenuAtoms::menuitem_with_favicon) { + return true; + } + } + + return false; +} + +void +nsMenuObject::ClearIcon() { + dbusmenu_menuitem_property_remove(mNativeData, + DBUSMENU_MENUITEM_PROP_ICON_DATA); +} + +nsMenuObject::~nsMenuObject() { + nsWeakMenuObject::NotifyDestroyed(this); + + if (mIconLoader) { + mIconLoader->Destroy(); + } + + if (mListener) { + mListener->UnregisterForContentChanges(mContent); + } + + if (mNativeData) { + g_object_unref(mNativeData); + mNativeData = nullptr; + } +} + +void +nsMenuObject::CreateNativeData() { + MOZ_ASSERT(mNativeData == nullptr, "This node already has a DbusmenuMenuitem. The old one will be leaked"); + + mNativeData = dbusmenu_menuitem_new(); + InitializeNativeData(); + if (mParent && mParent->IsBeingDisplayed()) { + ContainerIsOpening(); + } + + mListener->RegisterForContentChanges(mContent, this); +} + +nsresult +nsMenuObject::AdoptNativeData(DbusmenuMenuitem* aNativeData) { + MOZ_ASSERT(mNativeData == nullptr, "This node already has a DbusmenuMenuitem. The old one will be leaked"); + + if (!IsCompatibleWithNativeData(aNativeData)) { + return NS_ERROR_FAILURE; + } + + mNativeData = aNativeData; + g_object_ref(mNativeData); + + PropertyFlags supported = SupportedProperties(); + PropertyFlags mask = static_cast(1); + + for (uint32_t i = 0; gPropertyStrings[i]; ++i) { + if (!(mask & supported)) { + dbusmenu_menuitem_property_remove(mNativeData, gPropertyStrings[i]); + } + mask = static_cast(mask << 1); + } + + InitializeNativeData(); + if (mParent && mParent->IsBeingDisplayed()) { + ContainerIsOpening(); + } + + mListener->RegisterForContentChanges(mContent, this); + + return NS_OK; +} + +void +nsMenuObject::ContainerIsOpening() { + MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + + UpdateContentAttributes(); + + RefPtr sc = GetStyleContext(); + Update(sc); +} + +/* static */ void +nsWeakMenuObject::AddWeakReference(nsWeakMenuObject* aWeak) { + aWeak->mPrev = sHead; + sHead = aWeak; +} + +/* static */ void +nsWeakMenuObject::RemoveWeakReference(nsWeakMenuObject* aWeak) { + if (aWeak == sHead) { + sHead = aWeak->mPrev; + return; + } + + nsWeakMenuObject* weak = sHead; + while (weak && weak->mPrev != aWeak) { + weak = weak->mPrev; + } + + if (weak) { + weak->mPrev = aWeak->mPrev; + } +} + +/* static */ void +nsWeakMenuObject::NotifyDestroyed(nsMenuObject* aMenuObject) { + nsWeakMenuObject* weak = sHead; + while (weak) { + if (weak->mMenuObject == aMenuObject) { + weak->mMenuObject = nullptr; + } + + weak = weak->mPrev; + } +} diff --git a/widget/gtk/nsMenuObject.h b/widget/gtk/nsMenuObject.h new file mode 100644 index 0000000000..c7637cd052 --- /dev/null +++ b/widget/gtk/nsMenuObject.h @@ -0,0 +1,165 @@ +/* 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 __nsMenuObject_h__ +#define __nsMenuObject_h__ + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" + +#include "nsDbusmenu.h" +#include "nsNativeMenuDocListener.h" + +class nsIAtom; +class nsIContent; +class nsStyleContext; +class nsMenuContainer; +class nsMenuObjectIconLoader; + +#define DBUSMENU_PROPERTIES \ + DBUSMENU_PROPERTY(Label, DBUSMENU_MENUITEM_PROP_LABEL, 0) \ + DBUSMENU_PROPERTY(Enabled, DBUSMENU_MENUITEM_PROP_ENABLED, 1) \ + DBUSMENU_PROPERTY(Visible, DBUSMENU_MENUITEM_PROP_VISIBLE, 2) \ + DBUSMENU_PROPERTY(IconData, DBUSMENU_MENUITEM_PROP_ICON_DATA, 3) \ + DBUSMENU_PROPERTY(Type, DBUSMENU_MENUITEM_PROP_TYPE, 4) \ + DBUSMENU_PROPERTY(Shortcut, DBUSMENU_MENUITEM_PROP_SHORTCUT, 5) \ + DBUSMENU_PROPERTY(ToggleType, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, 6) \ + DBUSMENU_PROPERTY(ToggleState, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, 7) \ + DBUSMENU_PROPERTY(ChildDisplay, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, 8) + +/* + * This is the base class for all menu nodes. Each instance represents + * a single node in the menu hierarchy. It wraps the corresponding DOM node and + * native menu node, keeps them in sync and transfers events between the two. + * It is not reference counted - each node is owned by its parent (the top + * level menubar is owned by the window) and keeps a weak pointer to its + * parent (which is guaranteed to always be valid because a node will never + * outlive its parent). It is not safe to keep a reference to nsMenuObject + * externally. + */ +class nsMenuObject : public nsNativeMenuChangeObserver { +public: + enum EType { + eType_MenuBar, + eType_Menu, + eType_MenuItem + }; + + virtual ~nsMenuObject(); + + // Get the native menu item node + DbusmenuMenuitem* GetNativeData() const { return mNativeData; } + + // Get the parent menu object + nsMenuContainer* Parent() const { return mParent; } + + // Get the content node + nsIContent* ContentNode() const { return mContent; } + + // Get the type of this node. Must be provided by subclasses + virtual EType Type() const = 0; + + // Get the document listener + nsNativeMenuDocListener* DocListener() const { return mListener; } + + // Create the native menu item node (called by containers) + void CreateNativeData(); + + // Adopt the specified native menu item node (called by containers) + nsresult AdoptNativeData(DbusmenuMenuitem* aNativeData); + + // Called by the container to tell us that it's opening + void ContainerIsOpening(); + +protected: + nsMenuObject(nsMenuContainer* aParent, nsIContent* aContent); + nsMenuObject(nsNativeMenuDocListener* aListener, nsIContent* aContent); + + enum PropertyFlags { +#define DBUSMENU_PROPERTY(e, s, b) eProp##e = (1 << b), + DBUSMENU_PROPERTIES +#undef DBUSMENU_PROPERTY + }; + + void UpdateLabel(); + void UpdateVisibility(nsStyleContext* aStyleContext); + void UpdateSensitivity(); + void UpdateIcon(nsStyleContext* aStyleContext); + + already_AddRefed GetStyleContext(); + +private: + friend class nsMenuObjectIconLoader; + + // Set up initial properties on the native data, connect to signals etc. + // This should be implemented by subclasses + virtual void InitializeNativeData(); + + // Return the properties that this menu object type supports + // This should be implemented by subclasses + virtual PropertyFlags SupportedProperties() const; + + // Determine whether this menu object could use the specified + // native item. Returns true by default but can be overridden by subclasses + virtual bool + IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const; + + // Update attributes on this objects content node when the container opens. + // This is called before style resolution, and should be implemented by + // subclasses who want to modify attributes that might affect style. + // This will not be called when there are script blockers + virtual void UpdateContentAttributes(); + + // Update properties that should be refreshed when the container opens. + // This should be implemented by subclasses that have properties which + // need refreshing + virtual void Update(nsStyleContext* aStyleContext); + + bool ShouldShowIcon() const; + void ClearIcon(); + + nsCOMPtr mContent; + // mListener is a strong ref for simplicity - someone in the tree needs to + // own it, and this only really needs to be the top-level object (as no + // children outlives their parent). However, we need to keep it alive until + // after running the nsMenuObject destructor for the top-level menu object, + // hence the strong ref + RefPtr mListener; + nsMenuContainer* mParent; // [weak] + DbusmenuMenuitem* mNativeData; // [strong] + RefPtr mIconLoader; +}; + +// Keep a weak pointer to a menu object +class nsWeakMenuObject { +public: + nsWeakMenuObject() : mPrev(nullptr), mMenuObject(nullptr) {} + + nsWeakMenuObject(nsMenuObject* aMenuObject) : + mPrev(nullptr), mMenuObject(aMenuObject) + { + AddWeakReference(this); + } + + ~nsWeakMenuObject() { RemoveWeakReference(this); } + + nsMenuObject* get() const { return mMenuObject; } + + nsMenuObject* operator->() const { return mMenuObject; } + + explicit operator bool() const { return !!mMenuObject; } + + static void NotifyDestroyed(nsMenuObject* aMenuObject); + +private: + static void AddWeakReference(nsWeakMenuObject* aWeak); + static void RemoveWeakReference(nsWeakMenuObject* aWeak); + + nsWeakMenuObject* mPrev; + static nsWeakMenuObject* sHead; + + nsMenuObject* mMenuObject; +}; + +#endif /* __nsMenuObject_h__ */ diff --git a/widget/gtk/nsMenuSeparator.cpp b/widget/gtk/nsMenuSeparator.cpp new file mode 100644 index 0000000000..893c5c7f00 --- /dev/null +++ b/widget/gtk/nsMenuSeparator.cpp @@ -0,0 +1,74 @@ +/* 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 "mozilla/Assertions.h" +#include "mozilla/Move.h" +#include "nsAutoPtr.h" +#include "nsCRT.h" +#include "nsGkAtoms.h" +#include "nsStyleContext.h" + +#include "nsDbusmenu.h" + +#include "nsMenuContainer.h" +#include "nsMenuSeparator.h" + +using namespace mozilla; + +void +nsMenuSeparator::InitializeNativeData() { + dbusmenu_menuitem_property_set(GetNativeData(), + DBUSMENU_MENUITEM_PROP_TYPE, + "separator"); +} + +void +nsMenuSeparator::Update(nsStyleContext* aContext) { + UpdateVisibility(aContext); +} + +bool +nsMenuSeparator::IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const { + return nsCRT::strcmp(dbusmenu_menuitem_property_get(aNativeData, + DBUSMENU_MENUITEM_PROP_TYPE), + "separator") == 0; +} + +nsMenuObject::PropertyFlags +nsMenuSeparator::SupportedProperties() const { + return static_cast( + nsMenuObject::ePropVisible | + nsMenuObject::ePropType + ); +} + +void +nsMenuSeparator::OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) { + MOZ_ASSERT(aContent == ContentNode(), "Received an event that wasn't meant for us!"); + + if (!Parent()->IsBeingDisplayed()) { + return; + } + + if (aAttribute == nsGkAtoms::hidden || + aAttribute == nsGkAtoms::collapsed) { + RefPtr sc = GetStyleContext(); + UpdateVisibility(sc); + } +} + +nsMenuSeparator::nsMenuSeparator(nsMenuContainer* aParent, + nsIContent* aContent) : + nsMenuObject(aParent, aContent) { + MOZ_COUNT_CTOR(nsMenuSeparator); +} + +nsMenuSeparator::~nsMenuSeparator() { + MOZ_COUNT_DTOR(nsMenuSeparator); +} + +nsMenuObject::EType +nsMenuSeparator::Type() const { + return eType_MenuItem; +} diff --git a/widget/gtk/nsMenuSeparator.h b/widget/gtk/nsMenuSeparator.h new file mode 100644 index 0000000000..9ba770a85d --- /dev/null +++ b/widget/gtk/nsMenuSeparator.h @@ -0,0 +1,33 @@ +/* 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 __nsMenuSeparator_h__ +#define __nsMenuSeparator_h__ + +#include "mozilla/Attributes.h" + +#include "nsMenuObject.h" + +class nsIContent; +class nsIAtom; +class nsMenuContainer; + +// Menu separator class +class nsMenuSeparator final : public nsMenuObject { +public: + nsMenuSeparator(nsMenuContainer* aParent, nsIContent* aContent); + ~nsMenuSeparator(); + + nsMenuObject::EType Type() const override; + +private: + void InitializeNativeData() override; + void Update(nsStyleContext* aStyleContext) override; + bool IsCompatibleWithNativeData(DbusmenuMenuitem* aNativeData) const override; + nsMenuObject::PropertyFlags SupportedProperties() const override; + + void OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) override; +}; + +#endif /* __nsMenuSeparator_h__ */ diff --git a/widget/gtk/nsNativeMenuAtomList.h b/widget/gtk/nsNativeMenuAtomList.h new file mode 100644 index 0000000000..4a8b3869a8 --- /dev/null +++ b/widget/gtk/nsNativeMenuAtomList.h @@ -0,0 +1,9 @@ +/* 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/. */ + +WIDGET_ATOM2(menuitem_with_favicon, "menuitem-with-favicon") +WIDGET_ATOM2(_moz_menubarkeeplocal, "_moz-menubarkeeplocal") +WIDGET_ATOM2(_moz_nativemenupopupstate, "_moz-nativemenupopupstate") +WIDGET_ATOM(openedwithkey) +WIDGET_ATOM(shellshowingmenubar) diff --git a/widget/gtk/nsNativeMenuAtoms.cpp b/widget/gtk/nsNativeMenuAtoms.cpp new file mode 100644 index 0000000000..f43d8b24b1 --- /dev/null +++ b/widget/gtk/nsNativeMenuAtoms.cpp @@ -0,0 +1,35 @@ +/* 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 "nsIAtom.h" +#include "nsStaticAtom.h" + +#include "nsNativeMenuAtoms.h" + +using namespace mozilla; + +#define WIDGET_ATOM(_name) nsIAtom* nsNativeMenuAtoms::_name; +#define WIDGET_ATOM2(_name, _value) nsIAtom* nsNativeMenuAtoms::_name; +#include "nsNativeMenuAtomList.h" +#undef WIDGET_ATOM +#undef WIDGET_ATOM2 + +#define WIDGET_ATOM(name_) NS_STATIC_ATOM_BUFFER(name_##_buffer, #name_) +#define WIDGET_ATOM2(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_) +#include "nsNativeMenuAtomList.h" +#undef WIDGET_ATOM +#undef WIDGET_ATOM2 + +static const nsStaticAtom gAtoms[] = { +#define WIDGET_ATOM(name_) NS_STATIC_ATOM(name_##_buffer, &nsNativeMenuAtoms::name_), +#define WIDGET_ATOM2(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsNativeMenuAtoms::name_), +#include "nsNativeMenuAtomList.h" +#undef WIDGET_ATOM +#undef WIDGET_ATOM2 +}; + +/* static */ void +nsNativeMenuAtoms::RegisterAtoms() { + NS_RegisterStaticAtoms(gAtoms); +} diff --git a/widget/gtk/nsNativeMenuAtoms.h b/widget/gtk/nsNativeMenuAtoms.h new file mode 100644 index 0000000000..4a9766ee8b --- /dev/null +++ b/widget/gtk/nsNativeMenuAtoms.h @@ -0,0 +1,23 @@ +/* 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 __nsNativeMenuAtoms_h__ +#define __nsNativeMenuAtoms_h__ + +class nsIAtom; + +class nsNativeMenuAtoms { +public: + nsNativeMenuAtoms() = delete; + + static void RegisterAtoms(); + +#define WIDGET_ATOM(_name) static nsIAtom* _name; +#define WIDGET_ATOM2(_name, _value) static nsIAtom* _name; +#include "nsNativeMenuAtomList.h" +#undef WIDGET_ATOM +#undef WIDGET_ATOM2 +}; + +#endif /* __nsNativeMenuAtoms_h__ */ diff --git a/widget/gtk/nsNativeMenuDocListener.cpp b/widget/gtk/nsNativeMenuDocListener.cpp new file mode 100644 index 0000000000..46a9c3aa92 --- /dev/null +++ b/widget/gtk/nsNativeMenuDocListener.cpp @@ -0,0 +1,329 @@ +/* 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 "mozilla/Assertions.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/dom/Element.h" +#include "nsContentUtils.h" +#include "nsIAtom.h" +#include "nsIContent.h" +#include "nsIDocument.h" + +#include "nsMenuContainer.h" + +#include "nsNativeMenuDocListener.h" + +using namespace mozilla; + +uint32_t nsNativeMenuDocListener::sUpdateBlockersCount = 0; + +nsNativeMenuDocListenerTArray* gPendingListeners; + +/* + * Small helper which caches a single listener, so that consecutive + * events which go to the same node avoid multiple hash table lookups + */ +class MOZ_STACK_CLASS DispatchHelper { +public: + DispatchHelper(nsNativeMenuDocListener* aListener, + nsIContent* aContent + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : + mObserver(nullptr) { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + if (aContent == aListener->mLastSource) { + mObserver = aListener->mLastTarget; + } else { + mObserver = aListener->mContentToObserverTable.Get(aContent); + if (mObserver) { + aListener->mLastSource = aContent; + aListener->mLastTarget = mObserver; + } + } + } + + ~DispatchHelper() { }; + + nsNativeMenuChangeObserver* Observer() const { + return mObserver; + } + + bool HasObserver() const { + return !!mObserver; + } + +private: + nsNativeMenuChangeObserver* mObserver; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +NS_IMPL_ISUPPORTS(nsNativeMenuDocListener, nsIMutationObserver) + +nsNativeMenuDocListener::~nsNativeMenuDocListener() { + MOZ_ASSERT(mContentToObserverTable.Count() == 0, + "Some nodes forgot to unregister listeners. This is bad! (and we're lucky we made it this far)"); + MOZ_COUNT_DTOR(nsNativeMenuDocListener); +} + +void +nsNativeMenuDocListener::AttributeChanged(nsIDocument* aDocument, + mozilla::dom::Element* aElement, + int32_t aNameSpaceID, + nsIAtom* aAttribute, + int32_t aModType, + const nsAttrValue* aOldValue) { + if (sUpdateBlockersCount == 0) { + DoAttributeChanged(aElement, aAttribute); + return; + } + + MutationRecord* m =* mPendingMutations.AppendElement(new MutationRecord); + m->mType = MutationRecord::eAttributeChanged; + m->mTarget = aElement; + m->mAttribute = aAttribute; + + ScheduleFlush(this); +} + +void +nsNativeMenuDocListener::ContentAppended(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aFirstNewContent, + int32_t aNewIndexInContainer) { + for (nsIContent* c = aFirstNewContent; c; c = c->GetNextSibling()) { + ContentInserted(aDocument, aContainer, c, 0); + } +} + +void +nsNativeMenuDocListener::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer) { + nsIContent* prevSibling = nsMenuContainer::GetPreviousSupportedSibling(aChild); + + if (sUpdateBlockersCount == 0) { + DoContentInserted(aContainer, aChild, prevSibling); + return; + } + + MutationRecord* m =* mPendingMutations.AppendElement(new MutationRecord); + m->mType = MutationRecord::eContentInserted; + m->mTarget = aContainer; + m->mChild = aChild; + m->mPrevSibling = prevSibling; + + ScheduleFlush(this); +} + +void +nsNativeMenuDocListener::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer, + nsIContent* aPreviousSibling) { + if (sUpdateBlockersCount == 0) { + DoContentRemoved(aContainer, aChild); + return; + } + + MutationRecord* m =* mPendingMutations.AppendElement(new MutationRecord); + m->mType = MutationRecord::eContentRemoved; + m->mTarget = aContainer; + m->mChild = aChild; + + ScheduleFlush(this); +} + +void +nsNativeMenuDocListener::NodeWillBeDestroyed(const nsINode* aNode) { + mDocument = nullptr; +} + +void +nsNativeMenuDocListener::DoAttributeChanged(nsIContent* aContent, + nsIAtom* aAttribute) { + DispatchHelper h(this, aContent); + if (h.HasObserver()) { + h.Observer()->OnAttributeChanged(aContent, aAttribute); + } +} + +void +nsNativeMenuDocListener::DoContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling) { + DispatchHelper h(this, aContainer); + if (h.HasObserver()) { + h.Observer()->OnContentInserted(aContainer, aChild, aPrevSibling); + } +} + +void +nsNativeMenuDocListener::DoContentRemoved(nsIContent* aContainer, + nsIContent* aChild) { + DispatchHelper h(this, aContainer); + if (h.HasObserver()) { + h.Observer()->OnContentRemoved(aContainer, aChild); + } +} + +void +nsNativeMenuDocListener::DoBeginUpdates(nsIContent* aTarget) { + DispatchHelper h(this, aTarget); + if (h.HasObserver()) { + h.Observer()->OnBeginUpdates(aTarget); + } +} + +void +nsNativeMenuDocListener::DoEndUpdates(nsIContent* aTarget) { + DispatchHelper h(this, aTarget); + if (h.HasObserver()) { + h.Observer()->OnEndUpdates(); + } +} + +void +nsNativeMenuDocListener::FlushPendingMutations() { + nsIContent* currentTarget = nullptr; + bool inUpdateSequence = false; + + while (mPendingMutations.Length() > 0) { + MutationRecord* m = mPendingMutations[0]; + + if (m->mTarget != currentTarget) { + if (inUpdateSequence) { + DoEndUpdates(currentTarget); + inUpdateSequence = false; + } + + currentTarget = m->mTarget; + + if (mPendingMutations.Length() > 1 && + mPendingMutations[1]->mTarget == currentTarget) { + DoBeginUpdates(currentTarget); + inUpdateSequence = true; + } + } + + switch (m->mType) { + case MutationRecord::eAttributeChanged: + DoAttributeChanged(m->mTarget, m->mAttribute); + break; + case MutationRecord::eContentInserted: + DoContentInserted(m->mTarget, m->mChild, m->mPrevSibling); + break; + case MutationRecord::eContentRemoved: + DoContentRemoved(m->mTarget, m->mChild); + break; + default: + NS_NOTREACHED("Invalid type"); + } + + mPendingMutations.RemoveElementAt(0); + } + + if (inUpdateSequence) { + DoEndUpdates(currentTarget); + } +} + +/* static */ void +nsNativeMenuDocListener::ScheduleFlush(nsNativeMenuDocListener* aListener) { + MOZ_ASSERT(sUpdateBlockersCount > 0, "Shouldn't be doing this now"); + + if (!gPendingListeners) { + gPendingListeners = new nsNativeMenuDocListenerTArray; + } + + if (gPendingListeners->IndexOf(aListener) == + nsNativeMenuDocListenerTArray::NoIndex) { + gPendingListeners->AppendElement(aListener); + } +} + +/* static */ void +nsNativeMenuDocListener::CancelFlush(nsNativeMenuDocListener* aListener) { + if (!gPendingListeners) { + return; + } + + gPendingListeners->RemoveElement(aListener); +} + +/* static */ void +nsNativeMenuDocListener::RemoveUpdateBlocker() { + if (sUpdateBlockersCount == 1 && gPendingListeners) { + while (gPendingListeners->Length() > 0) { + (*gPendingListeners)[0]->FlushPendingMutations(); + gPendingListeners->RemoveElementAt(0); + } + } + + MOZ_ASSERT(sUpdateBlockersCount > 0, "Negative update blockers count!"); + sUpdateBlockersCount--; +} + +nsNativeMenuDocListener::nsNativeMenuDocListener(nsIContent* aRootNode) : + mRootNode(aRootNode), + mDocument(nullptr), + mLastSource(nullptr), + mLastTarget(nullptr) { + MOZ_COUNT_CTOR(nsNativeMenuDocListener); +} + +void +nsNativeMenuDocListener::RegisterForContentChanges(nsIContent* aContent, + nsNativeMenuChangeObserver* aObserver) { + MOZ_ASSERT(aContent, "Need content parameter"); + MOZ_ASSERT(aObserver, "Need observer parameter"); + if (!aContent || !aObserver) { + return; + } + + DebugOnly old; + MOZ_ASSERT(!mContentToObserverTable.Get(aContent, &old) || old == aObserver, + "Multiple observers for the same content node are not supported"); + + mContentToObserverTable.Put(aContent, aObserver); +} + +void +nsNativeMenuDocListener::UnregisterForContentChanges(nsIContent* aContent) { + MOZ_ASSERT(aContent, "Need content parameter"); + if (!aContent) { + return; + } + + mContentToObserverTable.Remove(aContent); + if (aContent == mLastSource) { + mLastSource = nullptr; + mLastTarget = nullptr; + } +} + +void +nsNativeMenuDocListener::Start() { + if (mDocument) { + return; + } + + mDocument = mRootNode->OwnerDoc(); + if (!mDocument) { + return; + } + + mDocument->AddMutationObserver(this); +} + +void +nsNativeMenuDocListener::Stop() { + if (mDocument) { + mDocument->RemoveMutationObserver(this); + mDocument = nullptr; + } + + CancelFlush(this); + mPendingMutations.Clear(); +} diff --git a/widget/gtk/nsNativeMenuDocListener.h b/widget/gtk/nsNativeMenuDocListener.h new file mode 100644 index 0000000000..c0a503da1b --- /dev/null +++ b/widget/gtk/nsNativeMenuDocListener.h @@ -0,0 +1,146 @@ +/* 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 __nsNativeMenuDocListener_h__ +#define __nsNativeMenuDocListener_h__ + +#include "mozilla/Attributes.h" +#include "mozilla/GuardObjects.h" +#include "mozilla/RefPtr.h" +#include "nsAutoPtr.h" +#include "nsDataHashtable.h" +#include "nsStubMutationObserver.h" +#include "nsTArray.h" + +class nsIAtom; +class nsIContent; +class nsIDocument; +class nsNativeMenuChangeObserver; + +/* + * This class keeps a mapping of content nodes to observers and forwards DOM + * mutations to these. There is exactly one of these for every menubar. + */ +class nsNativeMenuDocListener final : nsStubMutationObserver { +public: + NS_DECL_ISUPPORTS + + nsNativeMenuDocListener(nsIContent* aRootNode); + + // Register an observer to receive mutation events for the specified + // content node. The caller must keep the observer alive until + // UnregisterForContentChanges is called. + void RegisterForContentChanges(nsIContent* aContent, + nsNativeMenuChangeObserver* aObserver); + + // Unregister the registered observer for the specified content node + void UnregisterForContentChanges(nsIContent* aContent); + + // Start listening to the document and forwarding DOM mutations to + // registered observers. + void Start(); + + // Stop listening to the document. No DOM mutations will be forwarded + // to registered observers. + void Stop(); + + /* + * This class is intended to be used inside GObject signal handlers. + * It allows us to queue updates until we have finished delivering + * events to Goanna, and then we can batch updates to our view of the + * menu. This allows us to do menu updates without altering the structure + * seen by the OS. + */ + class MOZ_STACK_CLASS BlockUpdatesScope { + public: + BlockUpdatesScope(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + nsNativeMenuDocListener::AddUpdateBlocker(); + } + + ~BlockUpdatesScope() { + nsNativeMenuDocListener::RemoveUpdateBlocker(); + } + + private: + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + }; + +private: + friend class DispatchHelper; + + struct MutationRecord { + enum RecordType { + eAttributeChanged, + eContentInserted, + eContentRemoved + } mType; + + nsCOMPtr mTarget; + nsCOMPtr mChild; + nsCOMPtr mPrevSibling; + nsCOMPtr mAttribute; + }; + + ~nsNativeMenuDocListener(); + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + void DoAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute); + void DoContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling); + void DoContentRemoved(nsIContent* aContainer, nsIContent* aChild); + void DoBeginUpdates(nsIContent* aTarget); + void DoEndUpdates(nsIContent* aTarget); + + void FlushPendingMutations(); + static void ScheduleFlush(nsNativeMenuDocListener* aListener); + static void CancelFlush(nsNativeMenuDocListener* aListener); + + static void AddUpdateBlocker() { + ++sUpdateBlockersCount; + } + static void RemoveUpdateBlocker(); + + nsCOMPtr mRootNode; + nsIDocument* mDocument; + nsIContent* mLastSource; + nsNativeMenuChangeObserver* mLastTarget; + nsTArray > mPendingMutations; + nsDataHashtable, nsNativeMenuChangeObserver* > mContentToObserverTable; + + static uint32_t sUpdateBlockersCount; +}; + +typedef nsTArray > nsNativeMenuDocListenerTArray; + +/* + * Implemented by classes that want to listen to mutation events from content + * nodes. + */ +class nsNativeMenuChangeObserver { +public: + virtual void OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) {} + + virtual void OnContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling) {} + + virtual void OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) {} + + // Signals the start of a sequence of more than 1 event for the specified + // node. This only happens when events are flushed as all BlockUpdatesScope + // instances go out of scope + virtual void OnBeginUpdates(nsIContent* aContent) {}; + + // Signals the end of a sequence of events + virtual void OnEndUpdates() {}; +}; + +#endif /* __nsNativeMenuDocListener_h__ */ diff --git a/widget/gtk/nsNativeMenuService.cpp b/widget/gtk/nsNativeMenuService.cpp new file mode 100644 index 0000000000..eabe77ca80 --- /dev/null +++ b/widget/gtk/nsNativeMenuService.cpp @@ -0,0 +1,485 @@ +/* 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 "mozilla/Assertions.h" +#include "mozilla/Move.h" +#include "mozilla/Preferences.h" +#include "mozilla/UniquePtr.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include "nsGtkUtils.h" +#include "nsIContent.h" +#include "nsIWidget.h" +#include "nsServiceManagerUtils.h" +#include "nsWindow.h" +#include "prlink.h" + +#include "nsDbusmenu.h" +#include "nsMenuBar.h" +#include "nsNativeMenuAtoms.h" +#include "nsNativeMenuDocListener.h" + +#include +#include +#include + +#include "nsNativeMenuService.h" + +using namespace mozilla; + +nsNativeMenuService* nsNativeMenuService::sService = nullptr; + +extern PangoLayout* gPangoLayout; +extern nsNativeMenuDocListenerTArray* gPendingListeners; + +static const nsTArray::index_type NoIndex = nsTArray::NoIndex; + +#if not GLIB_CHECK_VERSION(2,26,0) +enum GBusType { + G_BUS_TYPE_STARTER = -1, + G_BUS_TYPE_NONE = 0, + G_BUS_TYPE_SYSTEM = 1, + G_BUS_TYPE_SESSION = 2 +}; + +enum GDBusProxyFlags { + G_DBUS_PROXY_FLAGS_NONE = 0, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES = 1 << 0, + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = 1 << 1, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = 1 << 2, + G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES = 1 << 3 +}; + +enum GDBusCallFlags { + G_DBUS_CALL_FLAGS_NONE = 0, + G_DBUS_CALL_FLAGS_NO_AUTO_START = 1 << 0 +}; + +typedef _GDBusInterfaceInfo GDBusInterfaceInfo; +typedef _GDBusProxy GDBusProxy; +typedef _GVariant GVariant; +#endif + +#undef g_dbus_proxy_new_for_bus +#undef g_dbus_proxy_new_for_bus_finish +#undef g_dbus_proxy_call +#undef g_dbus_proxy_call_finish +#undef g_dbus_proxy_get_name_owner + +typedef void (*_g_dbus_proxy_new_for_bus_fn)(GBusType, GDBusProxyFlags, + GDBusInterfaceInfo*, + const gchar*, const gchar*, + const gchar*, GCancellable*, + GAsyncReadyCallback, gpointer); + +typedef GDBusProxy* (*_g_dbus_proxy_new_for_bus_finish_fn)(GAsyncResult*, + GError**); +typedef void (*_g_dbus_proxy_call_fn)(GDBusProxy*, const gchar*, GVariant*, + GDBusCallFlags, gint, GCancellable*, + GAsyncReadyCallback, gpointer); +typedef GVariant* (*_g_dbus_proxy_call_finish_fn)(GDBusProxy*, GAsyncResult*, + GError**); +typedef gchar* (*_g_dbus_proxy_get_name_owner_fn)(GDBusProxy*); + +static _g_dbus_proxy_new_for_bus_fn _g_dbus_proxy_new_for_bus; +static _g_dbus_proxy_new_for_bus_finish_fn _g_dbus_proxy_new_for_bus_finish; +static _g_dbus_proxy_call_fn _g_dbus_proxy_call; +static _g_dbus_proxy_call_finish_fn _g_dbus_proxy_call_finish; +static _g_dbus_proxy_get_name_owner_fn _g_dbus_proxy_get_name_owner; + +#define g_dbus_proxy_new_for_bus _g_dbus_proxy_new_for_bus +#define g_dbus_proxy_new_for_bus_finish _g_dbus_proxy_new_for_bus_finish +#define g_dbus_proxy_call _g_dbus_proxy_call +#define g_dbus_proxy_call_finish _g_dbus_proxy_call_finish +#define g_dbus_proxy_get_name_owner _g_dbus_proxy_get_name_owner + +static PRLibrary* gGIOLib = nullptr; + +static nsresult +GDBusInit() { + gGIOLib = PR_LoadLibrary("libgio-2.0.so.0"); + if (!gGIOLib) { + return NS_ERROR_FAILURE; + } + + g_dbus_proxy_new_for_bus = (_g_dbus_proxy_new_for_bus_fn)PR_FindFunctionSymbol(gGIOLib, "g_dbus_proxy_new_for_bus"); + g_dbus_proxy_new_for_bus_finish = (_g_dbus_proxy_new_for_bus_finish_fn)PR_FindFunctionSymbol(gGIOLib, "g_dbus_proxy_new_for_bus_finish"); + g_dbus_proxy_call = (_g_dbus_proxy_call_fn)PR_FindFunctionSymbol(gGIOLib, "g_dbus_proxy_call"); + g_dbus_proxy_call_finish = (_g_dbus_proxy_call_finish_fn)PR_FindFunctionSymbol(gGIOLib, "g_dbus_proxy_call_finish"); + g_dbus_proxy_get_name_owner = (_g_dbus_proxy_get_name_owner_fn)PR_FindFunctionSymbol(gGIOLib, "g_dbus_proxy_get_name_owner"); + + if (!g_dbus_proxy_new_for_bus || + !g_dbus_proxy_new_for_bus_finish || + !g_dbus_proxy_call || + !g_dbus_proxy_call_finish || + !g_dbus_proxy_get_name_owner) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +NS_IMPL_ISUPPORTS(nsNativeMenuService, nsINativeMenuService) + +nsNativeMenuService::nsNativeMenuService() : + mCreateProxyCancellable(nullptr), mDbusProxy(nullptr), mOnline(false) { +} + +nsNativeMenuService::~nsNativeMenuService() { + SetOnline(false); + + if (mCreateProxyCancellable) { + g_cancellable_cancel(mCreateProxyCancellable); + g_object_unref(mCreateProxyCancellable); + mCreateProxyCancellable = nullptr; + } + + // Make sure we disconnect map-event handlers + while (mMenuBars.Length() > 0) { + NotifyNativeMenuBarDestroyed(mMenuBars[0]); + } + + Preferences::UnregisterCallback(PrefChangedCallback, + "ui.use_global_menubar"); + + if (mDbusProxy) { + g_signal_handlers_disconnect_by_func(mDbusProxy, + FuncToGpointer(name_owner_changed_cb), + NULL); + g_object_unref(mDbusProxy); + } + + if (gPendingListeners) { + delete gPendingListeners; + gPendingListeners = nullptr; + } + if (gPangoLayout) { + g_object_unref(gPangoLayout); + gPangoLayout = nullptr; + } + + MOZ_ASSERT(sService == this); + sService = nullptr; +} + +nsresult +nsNativeMenuService::Init() { + nsresult rv = nsDbusmenuFunctions::Init(); + if (NS_FAILED(rv)) { + return rv; + } + + rv = GDBusInit(); + if (NS_FAILED(rv)) { + return rv; + } + + Preferences::RegisterCallback(PrefChangedCallback, + "ui.use_global_menubar"); + + mCreateProxyCancellable = g_cancellable_new(); + + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, + static_cast( + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START), + nullptr, + "com.canonical.AppMenu.Registrar", + "/com/canonical/AppMenu/Registrar", + "com.canonical.AppMenu.Registrar", + mCreateProxyCancellable, proxy_created_cb, + nullptr); + + /* We don't technically know that the shell will draw the menubar until + * we know whether anybody owns the name of the menubar service on the + * session bus. However, discovering this happens asynchronously so + * we optimize for the common case here by assuming that the shell will + * draw window menubars if we are running inside Unity. This should + * mean that we avoid temporarily displaying the window menubar ourselves + */ + const char* desktop = getenv("XDG_CURRENT_DESKTOP"); + if (nsCRT::strcmp(desktop, "Unity") == 0) { + SetOnline(true); + } + + return NS_OK; +} + +/* static */ void +nsNativeMenuService::EnsureInitialized() { + if (sService) { + return; + } + nsCOMPtr service = + do_GetService("@mozilla.org/widget/nativemenuservice;1"); +} + +void +nsNativeMenuService::SetOnline(bool aOnline) { + if (!Preferences::GetBool("ui.use_global_menubar", true)) { + aOnline = false; + } + + mOnline = aOnline; + if (aOnline) { + for (uint32_t i = 0; i < mMenuBars.Length(); ++i) { + RegisterNativeMenuBar(mMenuBars[i]); + } + } else { + for (uint32_t i = 0; i < mMenuBars.Length(); ++i) { + mMenuBars[i]->Deactivate(); + } + } +} + +void +nsNativeMenuService::RegisterNativeMenuBar(nsMenuBar* aMenuBar) { + if (!mOnline) { + return; + } + + // This will effectively create the native menubar for + // exporting over the session bus, and hide the XUL menubar + aMenuBar->Activate(); + + if (!mDbusProxy || + !gtk_widget_get_mapped(aMenuBar->TopLevelWindow()) || + mMenuBarRegistrationCancellables.Get(aMenuBar, nullptr)) { + // Don't go further if we don't have a proxy for the shell menu + // service, the window isn't mapped or there is a request in progress. + return; + } + + uint32_t xid = aMenuBar->WindowId(); + nsAdoptingCString path = aMenuBar->ObjectPath(); + if (xid == 0 || path.IsEmpty()) { + NS_WARNING("Menubar has invalid XID or object path"); + return; + } + + GCancellable* cancellable = g_cancellable_new(); + mMenuBarRegistrationCancellables.Put(aMenuBar, cancellable); + + // We keep a weak ref because we can't assume that GDBus cancellation + // is reliable (see https://launchpad.net/bugs/953562) + + g_dbus_proxy_call(mDbusProxy, "RegisterWindow", + g_variant_new("(uo)", xid, path.get()), + G_DBUS_CALL_FLAGS_NONE, -1, + cancellable, + register_native_menubar_cb, aMenuBar); +} + +/* static */ void +nsNativeMenuService::name_owner_changed_cb(GObject* gobject, + GParamSpec* pspec, + gpointer user_data) { + nsNativeMenuService::GetSingleton()->OnNameOwnerChanged(); +} + +/* static */ void +nsNativeMenuService::proxy_created_cb(GObject* source_object, + GAsyncResult* res, + gpointer user_data) { + GError* error = nullptr; + GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + if (error && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; + } + + if (error) { + g_error_free(error); + } + + // We need this check because we can't assume that GDBus cancellation + // is reliable (see https://launchpad.net/bugs/953562) + nsNativeMenuService* self = nsNativeMenuService::GetSingleton(); + if (!self) { + if (proxy) { + g_object_unref(proxy); + } + return; + } + + self->OnProxyCreated(proxy); +} + +/* static */ void +nsNativeMenuService::register_native_menubar_cb(GObject* source_object, + GAsyncResult* res, + gpointer user_data) { + nsMenuBar* menuBar = static_cast(user_data); + + GError* error = nullptr; + GVariant* results = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), + res, &error); + if (results) { + // There's nothing useful in the response + g_variant_unref(results); + } + + bool success = error ? false : true; + if (error && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; + } + + if (error) { + g_error_free(error); + } + + nsNativeMenuService* self = nsNativeMenuService::GetSingleton(); + if (!self) { + return; + } + + self->OnNativeMenuBarRegistered(menuBar, success); +} + +/* static */ gboolean +nsNativeMenuService::map_event_cb(GtkWidget* widget, + GdkEvent* event, + gpointer user_data) { + nsMenuBar* menubar = static_cast(user_data); + nsNativeMenuService::GetSingleton()->RegisterNativeMenuBar(menubar); + + return FALSE; +} + +void +nsNativeMenuService::OnNameOwnerChanged() { + char* owner = g_dbus_proxy_get_name_owner(mDbusProxy); + SetOnline(owner ? true : false); + g_free(owner); +} + +void +nsNativeMenuService::OnProxyCreated(GDBusProxy* aProxy) { + mDbusProxy = aProxy; + + g_object_unref(mCreateProxyCancellable); + mCreateProxyCancellable = nullptr; + + if (!mDbusProxy) { + SetOnline(false); + return; + } + + g_signal_connect(mDbusProxy, "notify::g-name-owner", + G_CALLBACK(name_owner_changed_cb), nullptr); + + OnNameOwnerChanged(); +} + +void +nsNativeMenuService::OnNativeMenuBarRegistered(nsMenuBar* aMenuBar, + bool aSuccess) { + // Don't assume that GDBus cancellation is reliable (ie, |aMenuBar| might + // have already been deleted (see https://launchpad.net/bugs/953562) + GCancellable* cancellable = nullptr; + if (!mMenuBarRegistrationCancellables.Get(aMenuBar, &cancellable)) { + return; + } + + g_object_unref(cancellable); + mMenuBarRegistrationCancellables.Remove(aMenuBar); + + if (!aSuccess) { + aMenuBar->Deactivate(); + } +} + +/* static */ void +nsNativeMenuService::PrefChangedCallback(const char* aPref, + void* aClosure) { + nsNativeMenuService::GetSingleton()->PrefChanged(); +} + +void +nsNativeMenuService::PrefChanged() { + if (!mDbusProxy) { + SetOnline(false); + return; + } + + OnNameOwnerChanged(); +} + +NS_IMETHODIMP +nsNativeMenuService::CreateNativeMenuBar(nsIWidget* aParent, + nsIContent* aMenuBarNode) { + NS_ENSURE_ARG(aParent); + NS_ENSURE_ARG(aMenuBarNode); + + if (aMenuBarNode->AttrValueIs(kNameSpaceID_None, + nsNativeMenuAtoms::_moz_menubarkeeplocal, + nsGkAtoms::_true, + eCaseMatters)) { + return NS_OK; + } + + UniquePtr menubar(nsMenuBar::Create(aParent, aMenuBarNode)); + if (!menubar) { + NS_WARNING("Failed to create menubar"); + return NS_ERROR_FAILURE; + } + + // Unity forgets our window if it is unmapped by the application, which + // happens with some extensions that add "minimize to tray" type + // functionality. We hook on to the MapNotify event to re-register our menu + // with Unity + g_signal_connect(G_OBJECT(menubar->TopLevelWindow()), + "map-event", G_CALLBACK(map_event_cb), + menubar.get()); + + mMenuBars.AppendElement(menubar.get()); + RegisterNativeMenuBar(menubar.get()); + + static_cast(aParent)->SetMenuBar(Move(menubar)); + + return NS_OK; +} + +/* static */ already_AddRefed +nsNativeMenuService::GetInstanceForServiceManager() { + RefPtr service(sService); + + if (service) { + return service.forget(); + } + + service = new nsNativeMenuService(); + + if (NS_FAILED(service->Init())) { + return nullptr; + } + + sService = service.get(); + return service.forget(); +} + +/* static */ nsNativeMenuService* +nsNativeMenuService::GetSingleton() { + EnsureInitialized(); + return sService; +} + +void +nsNativeMenuService::NotifyNativeMenuBarDestroyed(nsMenuBar* aMenuBar) { + g_signal_handlers_disconnect_by_func(aMenuBar->TopLevelWindow(), + FuncToGpointer(map_event_cb), + aMenuBar); + + mMenuBars.RemoveElement(aMenuBar); + + GCancellable* cancellable = nullptr; + if (mMenuBarRegistrationCancellables.Get(aMenuBar, &cancellable)) { + mMenuBarRegistrationCancellables.Remove(aMenuBar); + g_cancellable_cancel(cancellable); + g_object_unref(cancellable); + } +} diff --git a/widget/gtk/nsNativeMenuService.h b/widget/gtk/nsNativeMenuService.h new file mode 100644 index 0000000000..5ce022526d --- /dev/null +++ b/widget/gtk/nsNativeMenuService.h @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __nsNativeMenuService_h__ +#define __nsNativeMenuService_h__ + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" +#include "nsDataHashtable.h" +#include "nsINativeMenuService.h" +#include "nsTArray.h" + +#include +#include +#include + +class nsMenuBar; + +/* + * The main native menu service singleton. nsWebShellWindow calls in to this when + * a new top level window is created. + * + * Menubars are owned by their nsWindow. This service holds a weak reference to + * each menubar for the purpose of re-registering them with the shell if it + * needs to. The menubar is responsible for notifying the service when the last + * reference to it is dropped. + */ +class nsNativeMenuService final : public nsINativeMenuService { +public: + NS_DECL_ISUPPORTS + + NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode) override; + + // Returns the singleton addref'd for the service manager + static already_AddRefed GetInstanceForServiceManager(); + + // Returns the singleton without increasing the reference count + static nsNativeMenuService* GetSingleton(); + + // Called by a menubar when it is deleted + void NotifyNativeMenuBarDestroyed(nsMenuBar* aMenuBar); + +private: + nsNativeMenuService(); + ~nsNativeMenuService(); + nsresult Init(); + + static void EnsureInitialized(); + void SetOnline(bool aOnline); + void RegisterNativeMenuBar(nsMenuBar* aMenuBar); + static void name_owner_changed_cb(GObject* gobject, + GParamSpec* pspec, + gpointer user_data); + static void proxy_created_cb(GObject* source_object, + GAsyncResult* res, + gpointer user_data); + static void register_native_menubar_cb(GObject* source_object, + GAsyncResult* res, + gpointer user_data); + static gboolean map_event_cb(GtkWidget* widget, GdkEvent* event, + gpointer user_data); + void OnNameOwnerChanged(); + void OnProxyCreated(GDBusProxy* aProxy); + void OnNativeMenuBarRegistered(nsMenuBar* aMenuBar, + bool aSuccess); + static void PrefChangedCallback(const char* aPref, void* aClosure); + void PrefChanged(); + + GCancellable* mCreateProxyCancellable; + GDBusProxy* mDbusProxy; + bool mOnline; + nsTArray mMenuBars; + nsDataHashtable, GCancellable*> mMenuBarRegistrationCancellables; + + static bool sShutdown; + static nsNativeMenuService* sService; +}; + +#endif /* __nsNativeMenuService_h__ */ diff --git a/widget/gtk/nsWidgetFactory.cpp b/widget/gtk/nsWidgetFactory.cpp index 7e4274377d..a1508d1d6d 100644 --- a/widget/gtk/nsWidgetFactory.cpp +++ b/widget/gtk/nsWidgetFactory.cpp @@ -49,6 +49,8 @@ #include "GfxInfoX11.h" #endif +#include "nsNativeMenuService.h" + #include "nsNativeThemeGTK.h" #include "nsIComponentRegistrar.h" @@ -121,6 +123,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) } #endif +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsNativeMenuService, + nsNativeMenuService::GetInstanceForServiceManager) + #ifdef NS_PRINTING NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecGTK) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsGTK, Init) @@ -223,6 +228,7 @@ NS_DEFINE_NAMED_CID(NS_IMAGE_TO_PIXBUF_CID); NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); #endif +NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID); static const mozilla::Module::CIDEntry kWidgetCIDs[] = { @@ -258,6 +264,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceGTKConstructor }, { &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor }, #endif + { &kNS_NATIVEMENUSERVICE_CID, true, NULL, nsNativeMenuServiceConstructor }, { nullptr } }; @@ -295,6 +302,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID }, { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, #endif + { "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID }, { nullptr } }; diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index e4e69c1b4d..6f222a7059 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -67,6 +67,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Likely.h" +#include "mozilla/Move.h" #include "mozilla/Preferences.h" #include "nsIPrefService.h" #include "nsIGConfService.h" @@ -5175,6 +5176,11 @@ nsWindow::HideWindowChrome(bool aShouldHide) return NS_OK; } +void +nsWindow::SetMenuBar(UniquePtr aMenuBar) { + mMenuBar = mozilla::Move(aMenuBar); +} + bool nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel, bool aAlwaysRollup) diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 49a8d4baf3..c45176ceab 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -35,6 +35,8 @@ #include "IMContextWrapper.h" +#include "nsMenuBar.h" + #undef LOG #ifdef MOZ_LOGGING @@ -162,6 +164,8 @@ public: nsIScreen* aTargetScreen = nullptr) override; NS_IMETHOD HideWindowChrome(bool aShouldHide) override; + void SetMenuBar(mozilla::UniquePtr aMenuBar); + /** * GetLastUserInputTime returns a timestamp for the most recent user input * event. This is intended for pointer grab requests (including drags). @@ -569,6 +573,8 @@ private: RefPtr mIMContext; mozilla::UniquePtr mCurrentTimeGetter; + + mozilla::UniquePtr mMenuBar; }; class nsChildWindow : public nsWindow { diff --git a/widget/moz.build b/widget/moz.build index 3ca4c9785c..3a52805b07 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -38,10 +38,12 @@ elif toolkit == 'cocoa': 'nsITaskbarProgress.idl', ] EXPORTS += [ - 'nsINativeMenuService.h', 'nsIPrintDialogService.h', ] +if toolkit in ('cocoa', 'gtk2', 'gtk3'): + EXPORTS += ['nsINativeMenuService.h'] + # Don't build the DSO under the 'build' directory as windows does. # # The DSOs get built in the toolkit dir itself. Do this so that diff --git a/xpfe/appshell/nsWebShellWindow.cpp b/xpfe/appshell/nsWebShellWindow.cpp index f703be7289..2893e78682 100644 --- a/xpfe/appshell/nsWebShellWindow.cpp +++ b/xpfe/appshell/nsWebShellWindow.cpp @@ -73,7 +73,7 @@ #include "nsPIWindowRoot.h" -#ifdef XP_MACOSX +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) #include "nsINativeMenuService.h" #define USE_NATIVE_MENUS #endif From 7359f904566a8ab7d562f28f6cc136a6beef8e0b Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 9 Jun 2020 10:42:36 -0400 Subject: [PATCH 6/7] Follow up to Issue #1578 - Preprocess the popup binding --- toolkit/content/jar.mn | 2 +- toolkit/content/widgets/popup.xml | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index a3764d3bc6..18eebb990e 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -96,7 +96,7 @@ toolkit.jar: content/global/bindings/menulist.xml (widgets/menulist.xml) content/global/bindings/notification.xml (widgets/notification.xml) content/global/bindings/numberbox.xml (widgets/numberbox.xml) - content/global/bindings/popup.xml (widgets/popup.xml) +* content/global/bindings/popup.xml (widgets/popup.xml) * content/global/bindings/preferences.xml (widgets/preferences.xml) content/global/bindings/progressmeter.xml (widgets/progressmeter.xml) content/global/bindings/radio.xml (widgets/radio.xml) diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml index 43c529780f..c8a395c401 100644 --- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -25,14 +25,21 @@ +#ifdef MOZ_WIDGET_GTK - + + ]]> + +#else + +#endif From 7900742344f15dd8f93b2fbeea2ce0ee6e8f09c8 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 10 Jun 2020 01:19:37 +0000 Subject: [PATCH 7/7] Issue #1585 - Replace node.rootNode with node.getRootNode() This removes the (default disabled) node.rootNode readonly attribute and replaces it with a node.getRootNode() function per WhatWG spec discussion. Based on work by John Dai --- dom/base/nsINode.cpp | 25 ++++++ dom/base/nsINode.h | 10 ++- .../mochitest/webcomponents/mochitest.ini | 1 + .../webcomponents/test_bug1269155.html | 89 +++++++++++++++++++ dom/webidl/Node.webidl | 9 +- modules/libpref/init/all.js | 7 -- .../web-platform/meta/dom/historical.html.ini | 4 - .../web-platform/meta/dom/interfaces.html.ini | 57 ------------ .../meta/dom/nodes/rootNode.html.ini | 15 ---- 9 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 dom/tests/mochitest/webcomponents/test_bug1269155.html delete mode 100644 testing/web-platform/meta/dom/nodes/rootNode.html.ini diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index d0cbdb454d..da30bed5c3 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -107,6 +107,7 @@ #include "GeometryUtils.h" #include "nsIAnimationObserver.h" #include "nsChildContentList.h" +#include "mozilla/dom/NodeBinding.h" #ifdef ACCESSIBILITY #include "mozilla/dom/AccessibleNode.h" @@ -250,6 +251,30 @@ nsINode::GetTextEditorRootContent(nsIEditor** aEditor) return nullptr; } +nsINode* nsINode::GetRootNode(const GetRootNodeOptions& aOptions) +{ + if (aOptions.mComposed) { + if (IsInComposedDoc() && GetComposedDoc()) { + return OwnerDoc(); + } + + nsINode* node = this; + ShadowRoot* shadowRootParent = nullptr; + while(node) { + node = node->SubtreeRoot(); + shadowRootParent = ShadowRoot::FromNode(node); + if (!shadowRootParent) { + break; + } + node = shadowRootParent->GetHost(); + } + + return node; + } + + return SubtreeRoot(); +} + nsINode* nsINode::SubtreeRoot() const { diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index 7fb5357016..5ae3a1da96 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -84,6 +84,7 @@ template class Sequence; class Text; class TextOrElementOrDocument; struct DOMPointInit; +struct GetRootNodeOptions; } // namespace dom } // namespace mozilla @@ -982,10 +983,11 @@ public: */ nsINode* SubtreeRoot() const; - nsINode* RootNode() const - { - return SubtreeRoot(); - } + /* + * Get context object's shadow-including root if options's composed is true, + * and context object's root otherwise. + */ + nsINode* GetRootNode(const mozilla::dom::GetRootNodeOptions& aOptions); /** * See nsIDOMEventTarget diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini index 428cc0e73f..7b6ec97241 100644 --- a/dom/tests/mochitest/webcomponents/mochitest.ini +++ b/dom/tests/mochitest/webcomponents/mochitest.ini @@ -40,3 +40,4 @@ skip-if = true # disabled - See bug 1390396 [test_shadowroot_style_order.html] [test_style_fallback_content.html] [test_link_prefetch.html] +[test_bug1269155.html] diff --git a/dom/tests/mochitest/webcomponents/test_bug1269155.html b/dom/tests/mochitest/webcomponents/test_bug1269155.html new file mode 100644 index 0000000000..f280ae1d2a --- /dev/null +++ b/dom/tests/mochitest/webcomponents/test_bug1269155.html @@ -0,0 +1,89 @@ + + + + + Test for Bug 1269155 + + + + + +Mozilla Bug 1269155 +

+ +
+
+
+ + + diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl index 8b6dca788c..c9fb7e77e2 100644 --- a/dom/webidl/Node.webidl +++ b/dom/webidl/Node.webidl @@ -38,8 +38,8 @@ interface Node : EventTarget { readonly attribute boolean isConnected; [Pure] readonly attribute Document? ownerDocument; - [Pure, Pref="dom.node.rootNode.enabled"] - readonly attribute Node rootNode; + [Pure] + Node getRootNode(optional GetRootNodeOptions options); [Pure] readonly attribute Node? parentNode; [Pure] @@ -113,3 +113,8 @@ interface Node : EventTarget { readonly attribute AccessibleNode? accessibleNode; #endif }; + +dictionary GetRootNodeOptions { + boolean composed = false; +}; + diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ad5b77af24..c82ccf0775 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5393,13 +5393,6 @@ pref("layout.css.color-adjust.enabled", true); pref("dom.audiochannel.audioCompeting", false); pref("dom.audiochannel.audioCompeting.allAgents", false); -// Disable Node.rootNode in release builds. -#ifdef RELEASE_OR_BETA -pref("dom.node.rootNode.enabled", false); -#else -pref("dom.node.rootNode.enabled", true); -#endif - // Default media volume pref("media.default_volume", "1.0"); diff --git a/testing/web-platform/meta/dom/historical.html.ini b/testing/web-platform/meta/dom/historical.html.ini index 6894d48686..42c737606a 100644 --- a/testing/web-platform/meta/dom/historical.html.ini +++ b/testing/web-platform/meta/dom/historical.html.ini @@ -12,7 +12,3 @@ expected: FAIL bug: 660660 - [Node member must be nuked: rootNode] - disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1303802 - bug: 1269155 - diff --git a/testing/web-platform/meta/dom/interfaces.html.ini b/testing/web-platform/meta/dom/interfaces.html.ini index 988efdf978..a9aa4a34ed 100644 --- a/testing/web-platform/meta/dom/interfaces.html.ini +++ b/testing/web-platform/meta/dom/interfaces.html.ini @@ -1,6 +1,5 @@ [interfaces.html] type: testharness - prefs: [dom.node.rootNode.enabled:true] [Document interface: attribute origin] expected: FAIL @@ -42,60 +41,4 @@ [Text interface: document.createTextNode("abc") must inherit property "assignedSlot" with the proper type (2)] expected: FAIL - [Node interface: operation getRootNode(GetRootNodeOptions)] - expected: FAIL - - [Node interface: new Document() must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: xmlDoc must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.doctype must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.doctype with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createDocumentFragment() must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createDocumentFragment() with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: element must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on element with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.querySelector("[id\]").attributes[0\] must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.querySelector("[id\]").attributes[0\] with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createTextNode("abc") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createTextNode("abc") with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createComment("abc") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createComment("abc") with too few arguments must throw TypeError] - expected: FAIL diff --git a/testing/web-platform/meta/dom/nodes/rootNode.html.ini b/testing/web-platform/meta/dom/nodes/rootNode.html.ini deleted file mode 100644 index 59533aebba..0000000000 --- a/testing/web-platform/meta/dom/nodes/rootNode.html.ini +++ /dev/null @@ -1,15 +0,0 @@ -[rootNode.html] - type: testharness - prefs: [dom.node.rootNode.enabled:true] - [getRootNode() must return the context object when it does not have any parent] - expected: FAIL - - [getRootNode() must return the parent node of the context object when the context object has a single ancestor not in a document] - expected: FAIL - - [getRootNode() must return the document when a node is in document] - expected: FAIL - - [getRootNode() must return a document fragment when a node is in the fragment] - expected: FAIL -