From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- dom/base/AbstractRange.cpp | 398 + dom/base/AbstractRange.h | 208 + dom/base/AncestorIterator.h | 107 + dom/base/AnimationFrameProvider.cpp | 53 + dom/base/AnimationFrameProvider.h | 78 + dom/base/AnonymousContent.cpp | 47 + dom/base/AnonymousContent.h | 45 + dom/base/Attr.cpp | 221 + dom/base/Attr.h | 111 + dom/base/AttrArray.cpp | 377 + dom/base/AttrArray.h | 246 + dom/base/AutoPrintEventDispatcher.h | 65 + dom/base/AutoSuppressEventHandlingAndSuspend.h | 66 + dom/base/AutocompleteFieldList.h | 238 + dom/base/BarProps.cpp | 242 + dom/base/BarProps.h | 133 + dom/base/BindContext.cpp | 51 + dom/base/BindContext.h | 101 + dom/base/BodyConsumer.cpp | 833 + dom/base/BodyConsumer.h | 142 + dom/base/BodyUtil.cpp | 475 + dom/base/BodyUtil.h | 75 + dom/base/BorrowedAttrInfo.cpp | 22 + dom/base/BorrowedAttrInfo.h | 39 + dom/base/CCGCScheduler.cpp | 1128 + dom/base/CCGCScheduler.h | 541 + dom/base/CORSMode.h | 38 + dom/base/CallState.h | 23 + dom/base/CharacterData.cpp | 591 + dom/base/CharacterData.h | 226 + dom/base/ChildIterator.cpp | 305 + dom/base/ChildIterator.h | 202 + dom/base/ChildProcessMessageManager.h | 35 + dom/base/ChromeMessageBroadcaster.cpp | 21 + dom/base/ChromeMessageBroadcaster.h | 55 + dom/base/ChromeMessageSender.cpp | 19 + dom/base/ChromeMessageSender.h | 44 + dom/base/ChromeNodeList.cpp | 57 + dom/base/ChromeNodeList.h | 36 + dom/base/ChromeUtils.cpp | 2220 ++ dom/base/ChromeUtils.h | 329 + dom/base/Comment.cpp | 71 + dom/base/Comment.h | 62 + dom/base/CompressionStream.cpp | 259 + dom/base/CompressionStream.h | 59 + dom/base/ContentAreaDropListener.sys.mjs | 329 + dom/base/ContentFrameMessageManager.cpp | 28 + dom/base/ContentFrameMessageManager.h | 62 + dom/base/ContentIterator.cpp | 1144 + dom/base/ContentIterator.h | 287 + dom/base/ContentProcessMessageManager.cpp | 125 + dom/base/ContentProcessMessageManager.h | 104 + dom/base/Crypto.cpp | 111 + dom/base/Crypto.h | 52 + dom/base/CustomElementRegistry.cpp | 1629 + dom/base/CustomElementRegistry.h | 599 + dom/base/DOMArena.h | 59 + dom/base/DOMException.cpp | 448 + dom/base/DOMException.h | 197 + dom/base/DOMImplementation.cpp | 213 + dom/base/DOMImplementation.h | 73 + dom/base/DOMIntersectionObserver.cpp | 821 + dom/base/DOMIntersectionObserver.h | 204 + dom/base/DOMMatrix.cpp | 1049 + dom/base/DOMMatrix.h | 348 + dom/base/DOMMozPromiseRequestHolder.h | 112 + dom/base/DOMParser.cpp | 324 + dom/base/DOMParser.h | 97 + dom/base/DOMPoint.cpp | 133 + dom/base/DOMPoint.h | 107 + dom/base/DOMQuad.cpp | 151 + dom/base/DOMQuad.h | 89 + dom/base/DOMRect.cpp | 160 + dom/base/DOMRect.h | 179 + dom/base/DOMRequest.cpp | 256 + dom/base/DOMRequest.h | 103 + dom/base/DOMRequestHelper.sys.mjs | 335 + dom/base/DOMStringList.cpp | 29 + dom/base/DOMStringList.h | 84 + dom/base/DOMTokenListSupportedTokens.h | 29 + dom/base/DecompressionStream.cpp | 301 + dom/base/DecompressionStream.h | 59 + dom/base/DirectionalityUtils.cpp | 1279 + dom/base/DirectionalityUtils.h | 174 + dom/base/DocGroup.cpp | 157 + dom/base/DocGroup.h | 136 + dom/base/Document.cpp | 19019 +++++++++ dom/base/Document.h | 5564 +++ dom/base/DocumentFragment.cpp | 122 + dom/base/DocumentFragment.h | 113 + dom/base/DocumentInlines.h | 67 + dom/base/DocumentOrShadowRoot.cpp | 693 + dom/base/DocumentOrShadowRoot.h | 292 + dom/base/DocumentType.cpp | 80 + dom/base/DocumentType.h | 73 + dom/base/Element.cpp | 5051 +++ dom/base/Element.h | 2291 ++ dom/base/ElementInlines.h | 45 + dom/base/EventSource.cpp | 2148 + dom/base/EventSource.h | 104 + dom/base/EventSourceEventService.cpp | 312 + dom/base/EventSourceEventService.h | 76 + dom/base/External.cpp | 17 + dom/base/External.h | 39 + dom/base/FilteredNodeIterator.h | 57 + dom/base/FlushType.h | 70 + dom/base/FormData.cpp | 409 + dom/base/FormData.h | 171 + dom/base/FragmentOrElement.cpp | 2066 + dom/base/FragmentOrElement.h | 381 + dom/base/FromParser.h | 25 + dom/base/FullscreenChange.h | 164 + dom/base/FuzzingFunctions.cpp | 388 + dom/base/FuzzingFunctions.h | 80 + dom/base/GeneratedImageContent.cpp | 43 + dom/base/GeneratedImageContent.h | 63 + dom/base/GlobalTeardownObserver.cpp | 73 + dom/base/GlobalTeardownObserver.h | 87 + dom/base/HTMLSplitOnSpacesTokenizer.h | 16 + dom/base/Highlight.cpp | 169 + dom/base/Highlight.h | 213 + dom/base/HighlightRegistry.cpp | 216 + dom/base/HighlightRegistry.h | 164 + dom/base/IDTracker.cpp | 283 + dom/base/IDTracker.h | 206 + dom/base/IdentifierMapEntry.h | 230 + dom/base/IdleDeadline.cpp | 76 + dom/base/IdleDeadline.h | 54 + dom/base/IdleRequest.cpp | 60 + dom/base/IdleRequest.h | 51 + dom/base/IframeSandboxKeywordList.h | 35 + dom/base/ImageEncoder.cpp | 458 + dom/base/ImageEncoder.h | 126 + dom/base/ImageTracker.cpp | 161 + dom/base/ImageTracker.h | 71 + dom/base/InProcessBrowserChildMessageManager.cpp | 294 + dom/base/InProcessBrowserChildMessageManager.h | 129 + dom/base/IndexedDBHelper.sys.mjs | 253 + dom/base/IntlUtils.cpp | 95 + dom/base/IntlUtils.h | 51 + dom/base/JSExecutionContext.cpp | 297 + dom/base/JSExecutionContext.h | 171 + dom/base/Link.cpp | 497 + dom/base/Link.h | 149 + dom/base/LinkStyle.cpp | 349 + dom/base/LinkStyle.h | 293 + dom/base/Location.cpp | 651 + dom/base/Location.h | 138 + dom/base/LocationBase.cpp | 278 + dom/base/LocationBase.h | 65 + dom/base/LocationHelper.sys.mjs | 51 + dom/base/MaybeCrossOriginObject.cpp | 483 + dom/base/MaybeCrossOriginObject.h | 354 + dom/base/MessageBroadcaster.cpp | 38 + dom/base/MessageBroadcaster.h | 50 + dom/base/MessageListenerManager.cpp | 48 + dom/base/MessageListenerManager.h | 52 + dom/base/MessageManagerCallback.h | 69 + dom/base/MessageManagerGlobal.cpp | 52 + dom/base/MessageManagerGlobal.h | 118 + dom/base/MessageSender.cpp | 31 + dom/base/MessageSender.h | 32 + dom/base/MimeType.cpp | 432 + dom/base/MimeType.h | 92 + dom/base/MozQueryInterface.cpp | 92 + dom/base/MozQueryInterface.h | 54 + dom/base/MutationObservers.cpp | 250 + dom/base/MutationObservers.h | 150 + dom/base/NameSpaceConstants.h | 32 + dom/base/Navigator.cpp | 2317 ++ dom/base/Navigator.h | 310 + dom/base/NodeInfo.cpp | 183 + dom/base/NodeInfo.h | 308 + dom/base/NodeInfoInlines.h | 102 + dom/base/NodeIterator.cpp | 212 + dom/base/NodeIterator.h | 83 + dom/base/NodeUbiReporting.cpp | 77 + dom/base/NodeUbiReporting.h | 89 + dom/base/ParentProcessMessageManager.cpp | 31 + dom/base/ParentProcessMessageManager.h | 49 + dom/base/PlacesBookmark.h | 44 + dom/base/PlacesBookmarkAddition.h | 93 + dom/base/PlacesBookmarkChanged.h | 29 + dom/base/PlacesBookmarkGuid.h | 49 + dom/base/PlacesBookmarkKeyword.h | 53 + dom/base/PlacesBookmarkMoved.h | 86 + dom/base/PlacesBookmarkRemoved.h | 60 + dom/base/PlacesBookmarkTags.h | 54 + dom/base/PlacesBookmarkTime.h | 53 + dom/base/PlacesBookmarkTitle.h | 54 + dom/base/PlacesBookmarkUrl.h | 47 + dom/base/PlacesEvent.cpp | 26 + dom/base/PlacesEvent.h | 78 + dom/base/PlacesFavicon.h | 50 + dom/base/PlacesHistoryCleared.h | 42 + dom/base/PlacesObservers.cpp | 392 + dom/base/PlacesObservers.h | 65 + dom/base/PlacesPurgeCaches.h | 39 + dom/base/PlacesRanking.h | 39 + dom/base/PlacesVisit.h | 68 + dom/base/PlacesVisitRemoved.h | 69 + dom/base/PlacesVisitTitle.h | 51 + dom/base/PlacesWeakCallbackWrapper.cpp | 41 + dom/base/PlacesWeakCallbackWrapper.h | 43 + dom/base/PointerLockManager.cpp | 442 + dom/base/PointerLockManager.h | 82 + dom/base/PopoverData.cpp | 30 + dom/base/PopoverData.h | 107 + dom/base/PopupBlocker.cpp | 438 + dom/base/PopupBlocker.h | 117 + dom/base/Pose.cpp | 63 + dom/base/Pose.h | 67 + dom/base/PostMessageEvent.cpp | 289 + dom/base/PostMessageEvent.h | 126 + dom/base/ProcessMessageManager.cpp | 42 + dom/base/ProcessMessageManager.h | 56 + dom/base/ProcessSelector.sys.mjs | 58 + dom/base/RadioGroupContainer.cpp | 202 + dom/base/RadioGroupContainer.h | 53 + dom/base/RangeBoundary.h | 467 + dom/base/RangeUtils.cpp | 233 + dom/base/RangeUtils.h | 127 + dom/base/RemoteOuterWindowProxy.cpp | 172 + dom/base/ResizeObserver.cpp | 590 + dom/base/ResizeObserver.h | 321 + dom/base/ResponsiveImageSelector.cpp | 743 + dom/base/ResponsiveImageSelector.h | 205 + dom/base/RustTypes.h | 40 + dom/base/SameProcessMessageQueue.cpp | 60 + dom/base/SameProcessMessageQueue.h | 49 + dom/base/ScreenLuminance.cpp | 19 + dom/base/ScreenLuminance.h | 49 + dom/base/ScreenOrientation.cpp | 883 + dom/base/ScreenOrientation.h | 113 + dom/base/ScriptableContentIterator.cpp | 189 + dom/base/ScriptableContentIterator.h | 35 + dom/base/ScrollingMetrics.cpp | 124 + dom/base/ScrollingMetrics.h | 51 + dom/base/Selection.cpp | 4191 ++ dom/base/Selection.h | 1134 + dom/base/SelectionChangeEventDispatcher.cpp | 175 + dom/base/SelectionChangeEventDispatcher.h | 69 + dom/base/SerializedStackHolder.cpp | 154 + dom/base/SerializedStackHolder.h | 81 + dom/base/ShadowIncludingTreeIterator.h | 118 + dom/base/ShadowRoot.cpp | 884 + dom/base/ShadowRoot.h | 299 + dom/base/SlowScriptDebug.sys.mjs | 24 + dom/base/StaticRange.cpp | 144 + dom/base/StaticRange.h | 138 + dom/base/StorageAccessPermissionRequest.cpp | 166 + dom/base/StorageAccessPermissionRequest.h | 80 + dom/base/StructuredCloneBlob.cpp | 255 + dom/base/StructuredCloneBlob.h | 89 + dom/base/StructuredCloneHolder.cpp | 1779 + dom/base/StructuredCloneHolder.h | 405 + dom/base/StructuredCloneTags.h | 166 + dom/base/StructuredCloneTester.cpp | 92 + dom/base/StructuredCloneTester.h | 66 + dom/base/StyleSheetList.cpp | 47 + dom/base/StyleSheetList.h | 68 + dom/base/StyledRange.cpp | 11 + dom/base/StyledRange.h | 24 + dom/base/SubtleCrypto.cpp | 125 + dom/base/SubtleCrypto.h | 111 + dom/base/SyncMessageSender.h | 23 + dom/base/TestUtils.cpp | 50 + dom/base/TestUtils.h | 30 + dom/base/Text.cpp | 157 + dom/base/Text.h | 61 + dom/base/TextInputProcessor.cpp | 1857 + dom/base/TextInputProcessor.h | 251 + dom/base/ThirdPartyUtil.cpp | 532 + dom/base/ThirdPartyUtil.h | 57 + dom/base/Timeout.cpp | 86 + dom/base/Timeout.h | 198 + dom/base/TimeoutBudgetManager.cpp | 35 + dom/base/TimeoutBudgetManager.h | 31 + dom/base/TimeoutExecutor.cpp | 257 + dom/base/TimeoutExecutor.h | 89 + dom/base/TimeoutHandler.cpp | 179 + dom/base/TimeoutHandler.h | 104 + dom/base/TimeoutManager.cpp | 1329 + dom/base/TimeoutManager.h | 250 + dom/base/TreeIterator.h | 147 + dom/base/TreeOrderedArray.h | 64 + dom/base/TreeOrderedArrayInlines.h | 49 + dom/base/TreeWalker.cpp | 329 + dom/base/TreeWalker.h | 79 + dom/base/UIDirectionManager.cpp | 94 + dom/base/UIDirectionManager.h | 30 + dom/base/UseCounter.h | 80 + dom/base/UseCounterMetrics.h | 40 + dom/base/UseCounters.conf | 467 + dom/base/UseCountersWorker.conf | 77 + dom/base/UserActivation.cpp | 165 + dom/base/UserActivation.h | 182 + dom/base/ViewportMetaData.cpp | 115 + dom/base/ViewportMetaData.h | 48 + dom/base/VisualViewport.cpp | 327 + dom/base/VisualViewport.h | 110 + dom/base/WindowDestroyedEvent.cpp | 157 + dom/base/WindowDestroyedEvent.h | 40 + dom/base/WindowFeatures.cpp | 241 + dom/base/WindowFeatures.h | 130 + dom/base/WindowNamedPropertiesHandler.cpp | 277 + dom/base/WindowNamedPropertiesHandler.h | 63 + dom/base/WindowProxyHolder.h | 77 + dom/base/XPathGenerator.cpp | 192 + dom/base/XPathGenerator.h | 30 + dom/base/ZLibHelper.h | 46 + dom/base/components.conf | 33 + dom/base/crashtests/1024428-1.html | 11 + dom/base/crashtests/1027461-1.html | 9 + dom/base/crashtests/1027461-inner.xhtml | 2 + dom/base/crashtests/1029710.html | 11 + dom/base/crashtests/1154598.xhtml | 9 + dom/base/crashtests/1157995.html | 9 + dom/base/crashtests/1158412.html | 22 + dom/base/crashtests/116848-1.html | 30 + dom/base/crashtests/1181619.html | 14 + dom/base/crashtests/1228882.html | 6 + dom/base/crashtests/1230422.html | 28 + dom/base/crashtests/1251361.html | 33 + dom/base/crashtests/1281715.html | 24 + dom/base/crashtests/1291535-iframe.html | 4 + dom/base/crashtests/1291535.html | 1 + dom/base/crashtests/1304437.html | 13 + dom/base/crashtests/1324209.html | 27 + dom/base/crashtests/1324500.html | 4 + dom/base/crashtests/1326194-1.html | 20 + dom/base/crashtests/1326194-2.html | 20 + dom/base/crashtests/1332939.html | 16 + dom/base/crashtests/1341693.html | 13 + dom/base/crashtests/1352453.html | 22 + dom/base/crashtests/1353529-inner.html | 12 + dom/base/crashtests/1353529.xhtml | 8 + dom/base/crashtests/1368327-iframe.html | 10 + dom/base/crashtests/1368327.html | 24 + dom/base/crashtests/1369363.xhtml | 16 + dom/base/crashtests/1370072.html | 18 + dom/base/crashtests/1370737.html | 41 + dom/base/crashtests/1370968-inner.xhtml | 6 + dom/base/crashtests/1370968.html | 14 + dom/base/crashtests/1373750.html | 14 + dom/base/crashtests/1377826.html | 5 + dom/base/crashtests/1383478.html | 49 + dom/base/crashtests/1383780.html | 21 + dom/base/crashtests/1385272-1.html | 29 + dom/base/crashtests/1393806.html | 17 + dom/base/crashtests/1396466.html | 20 + dom/base/crashtests/1397795.html | 23 + dom/base/crashtests/1400701.html | 15 + dom/base/crashtests/1403377.html | 18 + dom/base/crashtests/1405771.html | 20 + dom/base/crashtests/1406109-1.html | 10 + dom/base/crashtests/1411473.html | 12 + dom/base/crashtests/1413815.html | 20 + dom/base/crashtests/1419799.html | 17 + dom/base/crashtests/1419902.html | 23 + dom/base/crashtests/1422883.html | 10 + dom/base/crashtests/1428053.html | 23 + dom/base/crashtests/1441029.html | 1 + dom/base/crashtests/1445670.html | 20 + dom/base/crashtests/1449601.html | 16 + dom/base/crashtests/1458016.html | 12 + dom/base/crashtests/1459688.html | 6 + dom/base/crashtests/1460794.html | 19 + dom/base/crashtests/1462548.html | 13 + dom/base/crashtests/149320-1.html | 16 + dom/base/crashtests/1505811.html | 24 + dom/base/crashtests/1505875.html | 10 + dom/base/crashtests/1508845.html | 17 + dom/base/crashtests/1516289.html | 14 + dom/base/crashtests/1516560.html | 3 + dom/base/crashtests/1517025.html | 5 + dom/base/crashtests/1528675.html | 28 + dom/base/crashtests/1529203-1.html | 17 + dom/base/crashtests/1529203-2.html | 21 + dom/base/crashtests/1529203-3.html | 21 + dom/base/crashtests/1555786.html | 23 + dom/base/crashtests/1566310.html | 24 + dom/base/crashtests/1577191.html | 15 + dom/base/crashtests/1588259.html | 21 + dom/base/crashtests/1611853.html | 19 + dom/base/crashtests/1619322.html | 17 + dom/base/crashtests/1623918.html | 16 + dom/base/crashtests/1656925.html | 18 + dom/base/crashtests/1665792.html | 30 + dom/base/crashtests/1681729-inner1.html | 1 + dom/base/crashtests/1681729-inner2.html | 1 + dom/base/crashtests/1681729.html | 30 + dom/base/crashtests/1693049.html | 30 + dom/base/crashtests/1697256.html | 14 + dom/base/crashtests/1697525.html | 17 + dom/base/crashtests/1700237.html | 31 + dom/base/crashtests/1712198.html | 25 + dom/base/crashtests/1728670-1-child.html | 12 + dom/base/crashtests/1728670-1.html | 3 + dom/base/crashtests/1757923.html | 22 + dom/base/crashtests/1766472.html | 20 + dom/base/crashtests/1780790.html | 15 + dom/base/crashtests/1811939.html | 7 + dom/base/crashtests/1822717-module.js | 56 + dom/base/crashtests/1822717.html | 1 + dom/base/crashtests/1835886.html | 17 + dom/base/crashtests/1835886.js | 1 + dom/base/crashtests/1836824.html | 9 + dom/base/crashtests/1838484.html | 23 + dom/base/crashtests/1840191.html | 68 + dom/base/crashtests/205225-1.html | 9 + dom/base/crashtests/231475-1.html | 12 + dom/base/crashtests/244933-1.html | 13 + dom/base/crashtests/275912-1.html | 2 + dom/base/crashtests/293388-1.html | 26 + dom/base/crashtests/325730-1.html | 27 + dom/base/crashtests/326618-1.html | 14 + dom/base/crashtests/326646-1.html | 22 + dom/base/crashtests/326865-1.html | 12 + dom/base/crashtests/327571-1.html | 22 + dom/base/crashtests/327694.html | 17 + dom/base/crashtests/327695-1.html | 10 + dom/base/crashtests/329481-1.xhtml | 12 + dom/base/crashtests/336381-1.xhtml | 29 + dom/base/crashtests/336715-1.xhtml | 40 + dom/base/crashtests/338391-1.xhtml | 33 + dom/base/crashtests/338674-1.xhtml | 36 + dom/base/crashtests/340733-1.html | 28 + dom/base/crashtests/343730-1.xhtml | 35 + dom/base/crashtests/343850-1.xhtml | 28 + dom/base/crashtests/343889-1.html | 18 + dom/base/crashtests/344434-1.xhtml | 24 + dom/base/crashtests/344882-1.html | 33 + dom/base/crashtests/345837-1.xhtml | 35 + dom/base/crashtests/346381-1.html | 16 + dom/base/crashtests/349355-1.html | 41 + dom/base/crashtests/359432-1.xhtml | 27 + dom/base/crashtests/360599-1.html | 25 + dom/base/crashtests/366200-1.xhtml | 34 + dom/base/crashtests/369219-1.xhtml | 19 + dom/base/crashtests/369413-1.html | 12 + dom/base/crashtests/371124-1-inner.html | 21 + dom/base/crashtests/371124-1.html | 9 + dom/base/crashtests/371124-2-inner.html | 10 + dom/base/crashtests/371124-2.html | 9 + dom/base/crashtests/371466-1.xhtml | 24 + dom/base/crashtests/372554-1.html | 22 + dom/base/crashtests/375399-1-inner.xhtml | 12 + dom/base/crashtests/375399-1.html | 11 + dom/base/crashtests/377360-1.xhtml | 19 + dom/base/crashtests/377960-1.html | 12 + dom/base/crashtests/377960-2.html | 7 + dom/base/crashtests/384663-1-inner.xhtml | 18 + dom/base/crashtests/384663-1.html | 9 + dom/base/crashtests/386000-1.html | 36 + dom/base/crashtests/386794-1.html | 17 + dom/base/crashtests/387460-1-inner.xhtml | 22 + dom/base/crashtests/387460-1.html | 9 + dom/base/crashtests/399712-1.html | 29 + dom/base/crashtests/400763-1.html | 7 + dom/base/crashtests/407818.html | 5 + dom/base/crashtests/410860-1.xml | 8 + dom/base/crashtests/411882-1.xhtml | 1 + dom/base/crashtests/416734-1.html | 13 + dom/base/crashtests/417852-1.html | 13 + dom/base/crashtests/418928-1.html | 10 + dom/base/crashtests/420620-1.html | 29 + dom/base/crashtests/424276-1.html | 17 + dom/base/crashtests/426987-1.html | 7 + dom/base/crashtests/43040-1.html | 19 + dom/base/crashtests/439206-1.html | 19 + dom/base/crashtests/443538-1.svg | 7 + dom/base/crashtests/448615-1.html | 13 + dom/base/crashtests/450383-1.html | 9 + dom/base/crashtests/450385-1.html | 11 + dom/base/crashtests/458637-1-inner.xhtml | 4 + dom/base/crashtests/458637-1.html | 29 + dom/base/crashtests/462947.html | 13 + dom/base/crashtests/467392.html | 4 + dom/base/crashtests/472593-1.html | 7 + dom/base/crashtests/474041-1.svg | 17 + dom/base/crashtests/476526.html | 10 + dom/base/crashtests/483818-1.html | 14 + dom/base/crashtests/490760-1.xhtml | 25 + dom/base/crashtests/493281-1.html | 7 + dom/base/crashtests/493281-2.html | 12 + dom/base/crashtests/494810-1.html | 15 + dom/base/crashtests/499006-1.html | 26 + dom/base/crashtests/499006-2.html | 35 + dom/base/crashtests/502617.html | 13 + dom/base/crashtests/504224.html | 29 + dom/base/crashtests/509536-1.html | 17 + dom/base/crashtests/522516-1.html | 10 + dom/base/crashtests/529670.html | 18 + dom/base/crashtests/535926-1.html | 28 + dom/base/crashtests/543645.html | 14 + dom/base/crashtests/551631-1.html | 22 + dom/base/crashtests/552651.html | 25 + dom/base/crashtests/552651.xml | 2 + dom/base/crashtests/554230-1.xhtml | 15 + dom/base/crashtests/558973.html | 17 + dom/base/crashtests/564079-1.html | 10 + dom/base/crashtests/564114.html | 11 + dom/base/crashtests/565125-1.html | 27 + dom/base/crashtests/575462.svg | 27 + dom/base/crashtests/582601.html | 12 + dom/base/crashtests/590395-1.html | 5 + dom/base/crashtests/593302-1.html | 29 + dom/base/crashtests/593302-2.html | 12 + dom/base/crashtests/595606-1.html | 17 + dom/base/crashtests/595606-2.html | 18 + dom/base/crashtests/601247.html | 8 + dom/base/crashtests/603531.html | 18 + dom/base/crashtests/604262-1.html | 8 + dom/base/crashtests/605672-1.svg | 17 + dom/base/crashtests/606729-1.html | 1 + dom/base/crashtests/607222.html | 21 + dom/base/crashtests/609560-1.xhtml | 31 + dom/base/crashtests/610571-1.html | 26 + dom/base/crashtests/612018-1.html | 21 + dom/base/crashtests/628599-1.html | 31 + dom/base/crashtests/637116.html | 29 + dom/base/crashtests/637214-1.svg | 26 + dom/base/crashtests/637214-2.svg | 26 + dom/base/crashtests/642022-1.html | 4 + dom/base/crashtests/646184.html | 17 + dom/base/crashtests/658845-1.svg | 3 + dom/base/crashtests/666869.html | 17 + dom/base/crashtests/667336-1.html | 4 + dom/base/crashtests/675516.xhtml | 31 + dom/base/crashtests/675621-1.html | 7 + dom/base/crashtests/677194.html | 6 + dom/base/crashtests/679459.html | 21 + dom/base/crashtests/679689-1.html | 2 + dom/base/crashtests/682463.html | 20 + dom/base/crashtests/693212.xhtml | 16 + dom/base/crashtests/693811-1.html | 14 + dom/base/crashtests/693811-2.html | 16 + dom/base/crashtests/693811-3.html | 4 + dom/base/crashtests/693894.html | 8 + dom/base/crashtests/695867.html | 9 + dom/base/crashtests/697643.html | 5 + dom/base/crashtests/698974-1.html | 4 + dom/base/crashtests/700090-1.html | 32 + dom/base/crashtests/700090-2.html | 29 + dom/base/crashtests/700512-worker.js | 7 + dom/base/crashtests/700512.html | 11 + dom/base/crashtests/706283-1.html | 6 + dom/base/crashtests/709384.html | 5 + dom/base/crashtests/709954.html | 21 + dom/base/crashtests/713417-1.html | 23 + dom/base/crashtests/713417-2.html | 26 + dom/base/crashtests/715056.html | 21 + dom/base/crashtests/729431-1.xhtml | 36 + dom/base/crashtests/741163-1.html | 7 + dom/base/crashtests/745495.html | 19 + dom/base/crashtests/752226-1.html | 4 + dom/base/crashtests/752226-2.html | 4 + dom/base/crashtests/766426.html | 32 + dom/base/crashtests/771639.html | 16 + dom/base/crashtests/786854.html | 4 + dom/base/crashtests/815043.html | 8 + dom/base/crashtests/815276.html | 6 + dom/base/crashtests/815477.html | 15 + dom/base/crashtests/815500.html | 14 + dom/base/crashtests/816253.html | 31 + dom/base/crashtests/819014.html | 22 + dom/base/crashtests/822723.html | 20 + dom/base/crashtests/824719.html | 26 + dom/base/crashtests/827190.html | 13 + dom/base/crashtests/828054.html | 19 + dom/base/crashtests/828903-iframe.html | 46 + dom/base/crashtests/828903.html | 28 + dom/base/crashtests/829428.html | 8 + dom/base/crashtests/830098.html | 14 + dom/base/crashtests/831287.html | 11 + dom/base/crashtests/832644.html | 8 + dom/base/crashtests/836890.html | 19 + dom/base/crashtests/838489-1.html | 11 + dom/base/crashtests/838489-2.html | 16 + dom/base/crashtests/841205.html | 25 + dom/base/crashtests/844404.html | 23 + dom/base/crashtests/845093-1.html | 10 + dom/base/crashtests/845093-2.html | 7 + dom/base/crashtests/847127.html | 19 + dom/base/crashtests/849601.html | 38 + dom/base/crashtests/849727.html | 9 + dom/base/crashtests/849732.html | 18 + dom/base/crashtests/851353-1.html | 25 + dom/base/crashtests/852381.html | 19 + dom/base/crashtests/863950.html | 18 + dom/base/crashtests/864448.html | 22 + dom/base/crashtests/886213.html | 22 + dom/base/crashtests/898906.html | 14 + dom/base/crashtests/90613-1.html | 7 + dom/base/crashtests/930250.html | 8 + dom/base/crashtests/942979.html | 42 + dom/base/crashtests/973401.html | 20 + dom/base/crashtests/978646.html | 15 + dom/base/crashtests/crashtests.list | 273 + ...Source_invalid_scheme_worker_shutdown-worker.js | 4 + ...eventSource_invalid_scheme_worker_shutdown.html | 36 + dom/base/crashtests/file_504224.html | 7 + dom/base/crashtests/module-with-syntax-error.js | 1 + .../structured_clone_container_throws.html | 9 + .../crashtests/xhr-with-pagehide-1-helper.html | 21 + dom/base/crashtests/xhr-with-pagehide-1.html | 21 + dom/base/crashtests/xhr_empty_datauri.html | 5 + dom/base/crashtests/xhr_html_nullresponse.html | 5 + dom/base/domerr.msg | 137 + dom/base/fuzztest/FuzzStructuredClone.cpp | 70 + dom/base/fuzztest/moz.build | 23 + dom/base/gen-usecounters.py | 74 + dom/base/mach_commands.py | 21 + dom/base/moz.build | 634 + dom/base/mozAutoDocUpdate.h | 51 + dom/base/mozIDOMWindow.idl | 16 + dom/base/nsAttrName.h | 179 + dom/base/nsAttrValue.cpp | 2170 + dom/base/nsAttrValue.h | 577 + dom/base/nsAttrValueInlines.h | 274 + dom/base/nsAttrValueOrString.cpp | 29 + dom/base/nsAttrValueOrString.h | 85 + dom/base/nsCCUncollectableMarker.cpp | 494 + dom/base/nsCCUncollectableMarker.h | 46 + dom/base/nsCaseTreatment.h | 15 + dom/base/nsChildContentList.h | 83 + dom/base/nsContentAreaDragDrop.cpp | 873 + dom/base/nsContentAreaDragDrop.h | 81 + dom/base/nsContentCID.h | 195 + dom/base/nsContentCreatorFunctions.h | 75 + dom/base/nsContentList.cpp | 1181 + dom/base/nsContentList.h | 655 + dom/base/nsContentListDeclarations.h | 61 + dom/base/nsContentPermissionHelper.cpp | 874 + dom/base/nsContentPermissionHelper.h | 232 + dom/base/nsContentPolicy.cpp | 160 + dom/base/nsContentPolicy.h | 42 + dom/base/nsContentPolicyUtils.h | 323 + dom/base/nsContentSink.cpp | 971 + dom/base/nsContentSink.h | 273 + dom/base/nsContentTypeParser.cpp | 28 + dom/base/nsContentTypeParser.h | 23 + dom/base/nsContentUtils.cpp | 11471 ++++++ dom/base/nsContentUtils.h | 3751 ++ dom/base/nsCopySupport.cpp | 914 + dom/base/nsCopySupport.h | 116 + dom/base/nsDOMAttributeMap.cpp | 405 + dom/base/nsDOMAttributeMap.h | 176 + dom/base/nsDOMCID.h | 28 + dom/base/nsDOMCaretPosition.cpp | 58 + dom/base/nsDOMCaretPosition.h | 91 + dom/base/nsDOMDataChannel.cpp | 504 + dom/base/nsDOMDataChannel.h | 129 + dom/base/nsDOMDataChannelDeclarations.h | 26 + dom/base/nsDOMJSUtils.h | 25 + dom/base/nsDOMMutationObserver.cpp | 1097 + dom/base/nsDOMMutationObserver.h | 867 + dom/base/nsDOMNavigationTiming.cpp | 698 + dom/base/nsDOMNavigationTiming.h | 282 + dom/base/nsDOMString.h | 18 + dom/base/nsDOMTokenList.cpp | 366 + dom/base/nsDOMTokenList.h | 98 + dom/base/nsDOMWindowUtils.cpp | 4900 +++ dom/base/nsDOMWindowUtils.h | 117 + dom/base/nsDataDocumentContentPolicy.cpp | 175 + dom/base/nsDataDocumentContentPolicy.h | 39 + dom/base/nsDeprecatedOperationList.h | 62 + dom/base/nsDocElementCreatedNotificationRunner.h | 31 + dom/base/nsDocumentWarningList.h | 18 + dom/base/nsFocusManager.cpp | 5515 +++ dom/base/nsFocusManager.h | 1036 + dom/base/nsFrameLoader.cpp | 3967 ++ dom/base/nsFrameLoader.h | 579 + dom/base/nsFrameLoaderOwner.cpp | 403 + dom/base/nsFrameLoaderOwner.h | 136 + dom/base/nsFrameMessageManager.cpp | 1657 + dom/base/nsFrameMessageManager.h | 375 + dom/base/nsGlobalWindowCommands.cpp | 1198 + dom/base/nsGlobalWindowCommands.h | 41 + dom/base/nsGlobalWindowInner.cpp | 7728 ++++ dom/base/nsGlobalWindowInner.h | 1518 + dom/base/nsGlobalWindowOuter.cpp | 7419 ++++ dom/base/nsGlobalWindowOuter.h | 1149 + dom/base/nsHistory.cpp | 272 + dom/base/nsHistory.h | 74 + dom/base/nsIAnimationObserver.h | 55 + dom/base/nsIContent.h | 780 + dom/base/nsIContentInlines.h | 254 + dom/base/nsIContentPolicy.idl | 596 + dom/base/nsIDOMRequestService.idl | 21 + dom/base/nsIDocumentObserver.h | 120 + dom/base/nsIDroppedLinkHandler.idl | 89 + dom/base/nsIEventSourceEventService.idl | 35 + dom/base/nsIGlobalObject.cpp | 420 + dom/base/nsIGlobalObject.h | 313 + dom/base/nsIImageLoadingContent.idl | 163 + dom/base/nsIMessageManager.idl | 20 + dom/base/nsIMutationObserver.h | 432 + dom/base/nsINode.cpp | 3850 ++ dom/base/nsINode.h | 2544 ++ dom/base/nsINodeList.h | 54 + dom/base/nsIObjectLoadingContent.idl | 55 + dom/base/nsIScriptChannel.idl | 75 + dom/base/nsIScriptContext.h | 93 + dom/base/nsIScriptGlobalObject.h | 84 + dom/base/nsIScriptObjectPrincipal.h | 40 + dom/base/nsIScriptableContentIterator.idl | 74 + dom/base/nsISelectionController.idl | 340 + dom/base/nsISelectionDisplay.idl | 37 + dom/base/nsISelectionListener.idl | 53 + dom/base/nsISizeOfEventTarget.h | 42 + dom/base/nsISlowScriptDebug.idl | 35 + dom/base/nsImageLoadingContent.cpp | 1862 + dom/base/nsImageLoadingContent.h | 611 + dom/base/nsJSEnvironment.cpp | 2448 ++ dom/base/nsJSEnvironment.h | 219 + dom/base/nsJSUtils.cpp | 228 + dom/base/nsJSUtils.h | 239 + dom/base/nsLineBreaker.cpp | 639 + dom/base/nsLineBreaker.h | 281 + dom/base/nsMimeTypeArray.cpp | 96 + dom/base/nsMimeTypeArray.h | 114 + dom/base/nsNameSpaceManager.cpp | 271 + dom/base/nsNameSpaceManager.h | 81 + dom/base/nsNoDataProtocolContentPolicy.cpp | 63 + dom/base/nsNoDataProtocolContentPolicy.h | 39 + dom/base/nsNodeInfoManager.cpp | 408 + dom/base/nsNodeInfoManager.h | 182 + dom/base/nsObjectLoadingContent.cpp | 1840 + dom/base/nsObjectLoadingContent.h | 469 + dom/base/nsOpenURIInFrameParams.cpp | 93 + dom/base/nsOpenURIInFrameParams.h | 40 + dom/base/nsPIDOMWindow.h | 1194 + dom/base/nsPIDOMWindowInlines.h | 88 + dom/base/nsPIWindowRoot.h | 96 + dom/base/nsPluginArray.cpp | 150 + dom/base/nsPluginArray.h | 134 + dom/base/nsPropertyTable.cpp | 286 + dom/base/nsPropertyTable.h | 166 + dom/base/nsQueryContentEventResult.cpp | 234 + dom/base/nsQueryContentEventResult.h | 44 + dom/base/nsRange.cpp | 3254 ++ dom/base/nsRange.h | 439 + dom/base/nsSandboxFlags.h | 131 + dom/base/nsScreen.cpp | 186 + dom/base/nsScreen.h | 103 + dom/base/nsStructuredCloneContainer.cpp | 162 + dom/base/nsStructuredCloneContainer.h | 42 + dom/base/nsStubAnimationObserver.cpp | 9 + dom/base/nsStubAnimationObserver.h | 17 + dom/base/nsStubDocumentObserver.cpp | 19 + dom/base/nsStubDocumentObserver.h | 35 + dom/base/nsStubMutationObserver.cpp | 201 + dom/base/nsStubMutationObserver.h | 83 + dom/base/nsStyledElement.cpp | 219 + dom/base/nsStyledElement.h | 99 + dom/base/nsSyncLoadService.cpp | 363 + dom/base/nsSyncLoadService.h | 70 + dom/base/nsTextFragment.cpp | 538 + dom/base/nsTextFragment.h | 316 + dom/base/nsTextFragmentGeneric.h | 65 + dom/base/nsTextFragmentGenericFwd.h | 20 + dom/base/nsTextFragmentImpl.h | 36 + dom/base/nsTextFragmentSSE2.cpp | 10 + dom/base/nsTextFragmentVMX.cpp | 101 + dom/base/nsTextNode.cpp | 255 + dom/base/nsTextNode.h | 66 + dom/base/nsTraversal.cpp | 66 + dom/base/nsTraversal.h | 49 + dom/base/nsTreeSanitizer.cpp | 2643 ++ dom/base/nsTreeSanitizer.h | 418 + dom/base/nsViewportInfo.cpp | 53 + dom/base/nsViewportInfo.h | 161 + dom/base/nsWindowMemoryReporter.cpp | 937 + dom/base/nsWindowMemoryReporter.h | 179 + dom/base/nsWindowRoot.cpp | 392 + dom/base/nsWindowRoot.h | 99 + dom/base/nsWindowSizes.h | 237 + dom/base/nsWrapperCache.cpp | 146 + dom/base/nsWrapperCache.h | 649 + dom/base/nsWrapperCacheInlines.h | 98 + dom/base/rust/Cargo.toml | 14 + dom/base/rust/cbindgen.toml | 40 + dom/base/rust/lib.rs | 164 + dom/base/test/345339_iframe.html | 29 + dom/base/test/Ahem.ttf | Bin 0 -> 12480 bytes dom/base/test/FAIL.html | 1 + dom/base/test/PASS.html | 1 + dom/base/test/accesscontrol.resource | 7 + dom/base/test/accesscontrol.resource^headers^ | 5 + dom/base/test/audio.ogg | Bin 0 -> 14293 bytes dom/base/test/badContentType.eventsource | 5 + dom/base/test/badContentType.eventsource^headers^ | 1 + dom/base/test/badHTTPResponseCode.eventsource | 5 + .../test/badHTTPResponseCode.eventsource^headers^ | 2 + dom/base/test/badMessageEvent.eventsource | 4 + dom/base/test/badMessageEvent.eventsource^headers^ | 1 + dom/base/test/badMessageEvent2.eventsource | 5 + .../test/badMessageEvent2.eventsource^headers^ | 1 + dom/base/test/browser.toml | 150 + .../test/browser_aboutnewtab_process_selection.js | 137 + dom/base/test/browser_blocking_image.js | 183 + dom/base/test/browser_bug1011748.js | 31 + dom/base/test/browser_bug1058164.js | 237 + dom/base/test/browser_bug1303838.js | 368 + dom/base/test/browser_bug1554070.js | 49 + dom/base/test/browser_bug1691214.js | 122 + dom/base/test/browser_bug1703472.js | 68 + dom/base/test/browser_bug902350.js | 56 + .../test/browser_chromeutils_getalldomprocesses.js | 69 + dom/base/test/browser_chromeutils_isdomobject.js | 115 + .../test/browser_data_documents_aboutmemory.js | 20 + ...wser_event_source_reconnect_after_disconnect.js | 108 + dom/base/test/browser_force_process_selector.js | 38 + .../test/browser_form_validity_popup_submit.js | 55 + .../test/browser_inputStream_structuredClone.js | 72 + .../browser_messagemanager_loadprocessscript.js | 199 + .../browser_messagemanager_targetframeloader.js | 41 + dom/base/test/browser_messagemanager_unload.js | 136 + dom/base/test/browser_multiple_popups.html | 63 + dom/base/test/browser_multiple_popups.js | 296 + dom/base/test/browser_outline_refocus.js | 65 + dom/base/test/browser_page_load_event_telemetry.js | 51 + dom/base/test/browser_pagehide_on_tab_close.js | 21 + dom/base/test/browser_promiseDocumentFlushed.js | 292 + dom/base/test/browser_refresh_content.js | 137 + dom/base/test/browser_state_notifications.js | 193 + ...owser_timeout_throttling_with_audio_playback.js | 73 + dom/base/test/browser_use_counters.js | 400 + dom/base/test/browser_user_input_handling_delay.js | 82 + ...browser_user_input_handling_delay_aboutblank.js | 58 + .../browser_user_input_handling_delay_bfcache.js | 107 + ...r_user_input_handling_delay_invisible_iframe.js | 78 + ...owser_user_input_handling_delay_reload_ticks.js | 54 + dom/base/test/browser_xml_toggle.js | 24 + dom/base/test/bug1576154.sjs | 8 + dom/base/test/bug1739957.sjs | 10 + dom/base/test/bug282547.sjs | 8 + dom/base/test/bug298064-subframe.html | 24 + dom/base/test/bug313646.txt | 1 + dom/base/test/bug382113_object.html | 6 + dom/base/test/bug403852_fileOpener.js | 25 + dom/base/test/bug419132.html | 22 + dom/base/test/bug426308-redirect.sjs | 4 + dom/base/test/bug435425.sjs | 25 + dom/base/test/bug435425_redirect.sjs | 4 + dom/base/test/bug444322.js | 0 dom/base/test/bug444322.txt | 0 dom/base/test/bug444546.sjs | 21 + dom/base/test/bug455629-helper.svg | 6 + dom/base/test/bug457746.sjs | 10 + dom/base/test/bug461735-post-redirect.js | 3 + dom/base/test/bug461735-redirect1.sjs | 8 + dom/base/test/bug461735-redirect2.sjs | 8 + dom/base/test/bug466080.sjs | 14 + dom/base/test/bug466409-empty.css | 0 dom/base/test/bug466409-page.html | 12 + dom/base/test/bug475156.sjs | 23 + dom/base/test/bug482935.sjs | 12 + dom/base/test/bug540854.sjs | 21 + dom/base/test/bug578096LoadChromeScript.js | 21 + dom/base/test/bug638112-response.txt | Bin 0 -> 247 bytes dom/base/test/bug638112.sjs | 24 + dom/base/test/bug696301-script-1.js | 3 + dom/base/test/bug696301-script-1.js^headers^ | 1 + dom/base/test/bug696301-script-2.js | 3 + dom/base/test/bug704320.sjs | 396 + dom/base/test/bug704320_counter.sjs | 95 + dom/base/test/bug819051.sjs | 9 + dom/base/test/chrome.toml | 69 + dom/base/test/chrome/bug418986-1.js | 88 + dom/base/test/chrome/bug421622-referer.sjs | 9 + dom/base/test/chrome/bug884693.sjs | 8 + dom/base/test/chrome/chrome.toml | 135 + dom/base/test/chrome/clonedoc/chrome.manifest | 1 + dom/base/test/chrome/clonedoc/content/doc.xml | 4 + dom/base/test/chrome/custom_element_ep.js | 14 + dom/base/test/chrome/file_bug1139964.xhtml | 60 + dom/base/test/chrome/file_bug1209621.xhtml | 85 + dom/base/test/chrome/file_bug549682.xhtml | 214 + dom/base/test/chrome/file_bug616841.xhtml | 63 + dom/base/test/chrome/file_bug816340.xhtml | 69 + dom/base/test/chrome/file_bug990812-1.xhtml | 61 + dom/base/test/chrome/file_bug990812-2.xhtml | 56 + dom/base/test/chrome/file_bug990812-3.xhtml | 68 + dom/base/test/chrome/file_bug990812-4.xhtml | 63 + dom/base/test/chrome/file_bug990812-5.xhtml | 74 + dom/base/test/chrome/file_bug990812.xhtml | 55 + .../file_document-element-inserted-inner.xhtml | 1 + .../chrome/file_document-element-inserted.xhtml | 3 + dom/base/test/chrome/file_title.xhtml | 1 + dom/base/test/chrome/fileconstructor_file.png | Bin 0 -> 95 bytes .../test/chrome/frame_custom_element_content.html | 5 + dom/base/test/chrome/nochrome_bug1346936.html | 3 + dom/base/test/chrome/nochrome_bug1346936.js | 4 + .../test/chrome/nochrome_bug1346936.js^headers^ | 1 + dom/base/test/chrome/nochrome_bug765993.html | 3 + dom/base/test/chrome/nochrome_bug765993.js | 4 + .../test/chrome/nochrome_bug765993.js^headers^ | 1 + dom/base/test/chrome/test_bug1063837.xhtml | 36 + ...test_bug1098074_throw_from_ReceiveMessage.xhtml | 47 + dom/base/test/chrome/test_bug1139964.xhtml | 32 + dom/base/test/chrome/test_bug120684.xhtml | 80 + dom/base/test/chrome/test_bug1209621.xhtml | 34 + dom/base/test/chrome/test_bug1339722.html | 86 + dom/base/test/chrome/test_bug1346936.html | 61 + dom/base/test/chrome/test_bug206691.xhtml | 32 + dom/base/test/chrome/test_bug289714.xhtml | 33 + dom/base/test/chrome/test_bug339494.xhtml | 73 + dom/base/test/chrome/test_bug357450.xhtml | 56 + dom/base/test/chrome/test_bug380418.html | 37 + dom/base/test/chrome/test_bug380418.html^headers^ | 4 + dom/base/test/chrome/test_bug383430.html | 38 + dom/base/test/chrome/test_bug418986-1.xhtml | 25 + dom/base/test/chrome/test_bug421622.xhtml | 34 + dom/base/test/chrome/test_bug429785.xhtml | 53 + dom/base/test/chrome/test_bug430050.xhtml | 48 + dom/base/test/chrome/test_bug467123.xhtml | 42 + dom/base/test/chrome/test_bug473284.xhtml | 83 + dom/base/test/chrome/test_bug549682.xhtml | 32 + dom/base/test/chrome/test_bug571390.xhtml | 42 + dom/base/test/chrome/test_bug616841.xhtml | 30 + dom/base/test/chrome/test_bug635835.xhtml | 36 + dom/base/test/chrome/test_bug682305.html | 150 + dom/base/test/chrome/test_bug683852.xhtml | 87 + dom/base/test/chrome/test_bug752226-3.xhtml | 28 + dom/base/test/chrome/test_bug752226-4.xhtml | 28 + dom/base/test/chrome/test_bug765993.html | 61 + dom/base/test/chrome/test_bug780199.xhtml | 51 + dom/base/test/chrome/test_bug780529.xhtml | 36 + dom/base/test/chrome/test_bug800386.xhtml | 65 + dom/base/test/chrome/test_bug816340.xhtml | 32 + dom/base/test/chrome/test_bug884693.xhtml | 79 + dom/base/test/chrome/test_bug914381.html | 58 + dom/base/test/chrome/test_bug990812.xhtml | 42 + .../test/chrome/test_chromeOuterWindowID.xhtml | 138 + .../test/chrome/test_custom_element_content.xhtml | 55 + dom/base/test/chrome/test_custom_element_ep.xhtml | 41 + .../chrome/test_document-element-inserted.xhtml | 54 + dom/base/test/chrome/test_domparsing.xhtml | 145 + dom/base/test/chrome/test_fileconstructor.xhtml | 86 + dom/base/test/chrome/test_getElementsWithGrid.html | 121 + .../test_input_value_set_preserve_undo.xhtml | 37 + .../test/chrome/test_nsITextInputProcessor.xhtml | 29 + ...back_at_changing_default_value_of_textarea.html | 107 + ...ermission_hasValidTransientUserActivation.xhtml | 93 + .../chrome/test_range_getClientRectsAndTexts.html | 74 + dom/base/test/chrome/test_swapFrameLoaders.xhtml | 25 + dom/base/test/chrome/test_title.xhtml | 29 + dom/base/test/chrome/test_windowroot.xhtml | 18 + dom/base/test/chrome/title_window.xhtml | 197 + .../test/chrome/window_chromeOuterWindowID.xhtml | 14 + .../test/chrome/window_nsITextInputProcessor.xhtml | 4874 +++ dom/base/test/chrome/window_swapFrameLoaders.xhtml | 223 + dom/base/test/common_postMessages.js | 393 + dom/base/test/copypaste.js | 557 + dom/base/test/delayedServerEvents.sjs | 50 + dom/base/test/dummy.html | 9 + dom/base/test/embed_bug455472.html | 1 + dom/base/test/empty.html | 0 dom/base/test/eventsource.resource | 22 + dom/base/test/eventsource.resource^headers^ | 3 + dom/base/test/eventsource_message.sjs | 12 + dom/base/test/eventsource_reconnect.sjs | 18 + dom/base/test/eventsource_redirect.resource | 2 + .../test/eventsource_redirect.resource^headers^ | 3 + dom/base/test/eventsource_redirect_to.resource | 4 + .../test/eventsource_redirect_to.resource^headers^ | 3 + dom/base/test/eventsource_worker.js | 6 + dom/base/test/fake_plugin.tst | 1 + dom/base/test/file1_setting_opener.html | 1 + dom/base/test/file2_setting_opener.html | 1 + dom/base/test/file3_setting_opener.html | 1 + dom/base/test/file4_setting_opener.html | 1 + dom/base/test/file_audioLoop.html | 2 + dom/base/test/file_audioLoopInIframe.html | 2 + dom/base/test/file_blocking_image.html | 10 + dom/base/test/file_browser_refresh_content.html | 41 + .../test/file_browser_refresh_expired_resource.sjs | 13 + dom/base/test/file_browser_refresh_iframe.sjs | 13 + dom/base/test/file_browser_refresh_image.sjs | 38 + .../test/file_browser_refresh_non_cacheable.sjs | 6 + dom/base/test/file_bug1008126_worker.js | 151 + dom/base/test/file_bug1011748_OK.sjs | 4 + dom/base/test/file_bug1011748_redirect.sjs | 5 + dom/base/test/file_bug1091883_frame.html | 13 + dom/base/test/file_bug1091883_subframe.html | 6 + dom/base/test/file_bug1091883_target.html | 13 + dom/base/test/file_bug1100912.html | 150 + dom/base/test/file_bug1198095.js | 39 + dom/base/test/file_bug1250148.sjs | 73 + dom/base/test/file_bug1268962.sjs | 92 + dom/base/test/file_bug1274806.html | 33 + dom/base/test/file_bug1303838.html | 34 + dom/base/test/file_bug1303838_target.html | 21 + dom/base/test/file_bug1303838_target_bar.html | 1 + dom/base/test/file_bug1303838_target_baz.html | 1 + dom/base/test/file_bug1303838_target_foo.html | 1 + dom/base/test/file_bug1303838_target_ibar.html | 1 + dom/base/test/file_bug1303838_target_ibaz.html | 1 + dom/base/test/file_bug1303838_target_ifoo.html | 1 + dom/base/test/file_bug1303838_with_iframe.html | 13 + dom/base/test/file_bug1554070_1.html | 14 + dom/base/test/file_bug1554070_2.html | 13 + dom/base/test/file_bug1639328.html | 8 + dom/base/test/file_bug1691214.html | 4 + dom/base/test/file_bug1700871.html | 18 + dom/base/test/file_bug1703472.html | 6 + dom/base/test/file_bug28293.sjs | 4 + dom/base/test/file_bug326337.xml | 1 + dom/base/test/file_bug326337_inner.html | 44 + dom/base/test/file_bug326337_outer.html | 15 + dom/base/test/file_bug357450.js | 74 + dom/base/test/file_bug416317.xhtml | 1469 + dom/base/test/file_bug426646-1.html | 37 + dom/base/test/file_bug426646-2.html | 65 + dom/base/test/file_bug428847-1.xhtml | 4 + dom/base/test/file_bug428847-2.xhtml | 4 + dom/base/test/file_bug498897.css | 1 + dom/base/test/file_bug498897.html | 23 + dom/base/test/file_bug498897.html^headers^ | 1 + dom/base/test/file_bug503473-frame.sjs | 22 + dom/base/test/file_bug503481.sjs | 54 + dom/base/test/file_bug503481b_inner.html | 62 + dom/base/test/file_bug518104.js | 3 + dom/base/test/file_bug541937.html | 7 + dom/base/test/file_bug541937.xhtml | 12 + dom/base/test/file_bug557892.html | 25 + dom/base/test/file_bug562137.txt | 1 + dom/base/test/file_bug590812-ref.xhtml | 3 + dom/base/test/file_bug590812.xml | 1 + dom/base/test/file_bug590870.html | 16 + dom/base/test/file_bug601803a.html | 22 + dom/base/test/file_bug601803b.html | 11 + dom/base/test/file_bug604660-1.xml | 3 + dom/base/test/file_bug604660-2.xsl | 19 + dom/base/test/file_bug604660-3.js | 1 + dom/base/test/file_bug604660-4.js | 1 + dom/base/test/file_bug604660-5.xml | 2 + dom/base/test/file_bug604660-6.xsl | 9 + dom/base/test/file_bug622088.sjs | 5 + dom/base/test/file_bug622088_inner.html | 38 + dom/base/test/file_bug675121.sjs | 17 + dom/base/test/file_bug687859-16.js | Bin 0 -> 64 bytes dom/base/test/file_bug687859-16.js^headers^ | 1 + dom/base/test/file_bug687859-bom.js | 1 + dom/base/test/file_bug687859-bom.js^headers^ | 1 + dom/base/test/file_bug687859-charset.js | 1 + dom/base/test/file_bug687859-http.js | 1 + dom/base/test/file_bug687859-http.js^headers^ | 1 + dom/base/test/file_bug687859-inherit.js | 1 + dom/base/test/file_bug692434.xml | 1 + dom/base/test/file_bug704320_preload_attr.html | 32 + dom/base/test/file_bug704320_preload_common.js | 32 + dom/base/test/file_bug704320_preload_reuse.html | 31 + dom/base/test/file_bug704320_redirect.html | 10 + dom/base/test/file_bug707142_baseline.json | 1 + dom/base/test/file_bug707142_bom.json | 1 + dom/base/test/file_bug707142_utf-16.json | Bin 0 -> 32 bytes dom/base/test/file_bug708620-2.html | 4 + dom/base/test/file_bug708620.html | 7 + dom/base/test/file_bug753278.html | 1 + dom/base/test/file_bug769117.html | 16 + dom/base/test/file_bug782342.txt | 1 + dom/base/test/file_bug787778.sjs | 7 + dom/base/test/file_bug869432.eventsource | 4 + dom/base/test/file_bug869432.eventsource^headers^ | 3 + dom/base/test/file_bug902350.html | 19 + dom/base/test/file_bug902350_frame.html | 14 + dom/base/test/file_bug907892.html | 12 + dom/base/test/file_bug945152.jar | Bin 0 -> 92275 bytes dom/base/test/file_bug945152_worker.js | 99 + dom/base/test/file_change_policy_redirect.html | 10 + dom/base/test/file_current_inner_window.html | 24 + dom/base/test/file_delazification_strategy.html | 10 + dom/base/test/file_delazification_strategy.js | 91 + dom/base/test/file_domwindowutils_animation.html | 233 + .../test/file_domwindowutils_dynamic_toolbar.html | 23 + dom/base/test/file_empty.html | 1 + dom/base/test/file_explicit_user_agent.sjs | 6 + dom/base/test/file_external_script.html | 11 + dom/base/test/file_external_script.xhtml | 11 + dom/base/test/file_focus_design_mode_inner.html | 32 + ...le_focus_display_none_xorigin_iframe_inner.html | 15 + dom/base/test/file_focus_shadow_dom.html | 999 + dom/base/test/file_general_document.html | 10 + dom/base/test/file_history_document_open.html | 1 + dom/base/test/file_htmlserializer_1.html | 44 + dom/base/test/file_htmlserializer_1_bodyonly.html | 43 + dom/base/test/file_htmlserializer_1_format.html | 57 + dom/base/test/file_htmlserializer_1_linebreak.html | 47 + dom/base/test/file_htmlserializer_1_links.html | 47 + .../test/file_htmlserializer_1_nested_body.html | 47 + dom/base/test/file_htmlserializer_1_no_body.html | 5 + dom/base/test/file_htmlserializer_1_noflag.html | 47 + .../test/file_htmlserializer_1_noformatpre.html | 51 + dom/base/test/file_htmlserializer_1_raw.html | 45 + .../test/file_htmlserializer_1_sibling_body.html | 47 + ...le_htmlserializer_1_sibling_body_only_body.html | 43 + dom/base/test/file_htmlserializer_1_wrap.html | 52 + dom/base/test/file_htmlserializer_2.html | 22 + dom/base/test/file_htmlserializer_2_basic.html | 24 + dom/base/test/file_htmlserializer_ipv6.html | 5 + dom/base/test/file_htmlserializer_ipv6_out.html | 6 + dom/base/test/file_inline_script.html | 11 + dom/base/test/file_inline_script.xhtml | 11 + dom/base/test/file_js_cache.html | 10 + dom/base/test/file_js_cache.js | 5 + dom/base/test/file_js_cache_module.html | 13 + dom/base/test/file_js_cache_save_after_load.html | 10 + dom/base/test/file_js_cache_save_after_load.js | 15 + dom/base/test/file_js_cache_syntax_error.html | 10 + dom/base/test/file_js_cache_syntax_error.js | 1 + dom/base/test/file_js_cache_with_sri.html | 12 + .../test/file_location_href_unknown_protocol.html | 15 + ...e_lock_orientation_with_pending_fullscreen.html | 22 + dom/base/test/file_messagemanager_unload.html | 6 + dom/base/test/file_module_js_cache.html | 10 + dom/base/test/file_module_js_cache.mjs | 6 + dom/base/test/file_module_js_cache_no_module.html | 10 + dom/base/test/file_module_js_cache_with_sri.html | 12 + dom/base/test/file_mozfiledataurl_img.jpg | Bin 0 -> 2711 bytes .../file_navigator_resolve_identity_xrays.xhtml | 29 + dom/base/test/file_receiveMessage.html | 13 + dom/base/test/file_restrictedEventSource.sjs | 69 + dom/base/test/file_sandbox_and_document_uri.html | 34 + dom/base/test/file_script.js | 1 + .../file_script_module_dynamic_and_element.html | 10 + .../file_script_module_dynamic_and_element.mjs | 20 + ...cript_module_dynamic_and_element_imported_1.mjs | 7 + ...cript_module_dynamic_and_element_imported_2.mjs | 1 + ...cript_module_dynamic_and_element_imported_3.mjs | 1 + .../file_script_module_dynamic_and_static.html | 10 + .../test/file_script_module_dynamic_and_static.mjs | 11 + ...script_module_dynamic_and_static_imported_1.mjs | 5 + ...script_module_dynamic_and_static_imported_2.mjs | 5 + ...script_module_dynamic_and_static_imported_3.mjs | 1 + .../test/file_script_module_dynamic_import.html | 10 + .../test/file_script_module_dynamic_import.mjs | 4 + .../file_script_module_dynamic_import_imported.mjs | 1 + .../file_script_module_element_and_dynamic.html | 10 + .../file_script_module_element_and_dynamic.mjs | 11 + ...cript_module_element_and_dynamic_imported_1.mjs | 13 + ...cript_module_element_and_dynamic_imported_2.mjs | 1 + ...cript_module_element_and_dynamic_imported_3.mjs | 1 + .../file_script_module_element_and_import.html | 10 + .../test/file_script_module_element_and_import.mjs | 9 + ...script_module_element_and_import_imported_1.mjs | 13 + ...script_module_element_and_import_imported_2.mjs | 1 + ...script_module_element_and_import_imported_3.mjs | 1 + .../test/file_script_module_frames_dynamic.html | 24 + .../file_script_module_frames_dynamic_load.html | 19 + .../file_script_module_frames_dynamic_load.mjs | 4 + .../file_script_module_frames_dynamic_save.html | 19 + .../file_script_module_frames_dynamic_save.mjs | 4 + .../file_script_module_frames_dynamic_shared.mjs | 1 + .../test/file_script_module_frames_element.html | 24 + .../file_script_module_frames_element_load.html | 19 + .../file_script_module_frames_element_save.html | 19 + .../file_script_module_frames_element_shared.mjs | 1 + .../test/file_script_module_frames_import.html | 24 + .../file_script_module_frames_import_load.html | 19 + .../test/file_script_module_frames_import_load.mjs | 5 + .../file_script_module_frames_import_save.html | 19 + .../test/file_script_module_frames_import_save.mjs | 5 + .../file_script_module_frames_import_shared.mjs | 1 + dom/base/test/file_script_module_frames_relay.js | 22 + dom/base/test/file_script_module_import.html | 10 + dom/base/test/file_script_module_import.mjs | 5 + .../file_script_module_import_and_element.html | 10 + .../test/file_script_module_import_and_element.mjs | 18 + ...script_module_import_and_element_imported_1.mjs | 7 + ...script_module_import_and_element_imported_2.mjs | 1 + ...script_module_import_and_element_imported_3.mjs | 1 + .../test/file_script_module_import_imported.mjs | 1 + dom/base/test/file_script_module_import_multi.html | 10 + dom/base/test/file_script_module_import_multi.mjs | 7 + .../file_script_module_import_multi_elems.html | 10 + .../file_script_module_import_multi_elems_1.mjs | 15 + .../file_script_module_import_multi_elems_2.mjs | 7 + ...t_module_import_multi_elems_imported_once_1.mjs | 1 + ...t_module_import_multi_elems_imported_once_2.mjs | 1 + ...t_module_import_multi_elems_imported_once_3.mjs | 1 + ...pt_module_import_multi_elems_imported_twice.mjs | 4 + ...le_script_module_import_multi_imported_once.mjs | 5 + ...e_script_module_import_multi_imported_twice.mjs | 1 + dom/base/test/file_script_module_single.html | 10 + dom/base/test/file_script_module_single.mjs | 8 + dom/base/test/file_script_module_sri_basic.html | 11 + dom/base/test/file_script_module_sri_basic.mjs | 1 + .../test/file_script_module_sri_basic_prep.html | 11 + .../test/file_script_module_sri_dynamic_elem.html | 12 + .../test/file_script_module_sri_dynamic_elem.mjs | 6 + ...ile_script_module_sri_dynamic_elem_imported.mjs | 3 + ...e_script_module_sri_dynamic_elem_nopreload.html | 10 + ...le_script_module_sri_dynamic_elem_nopreload.mjs | 20 + ..._module_sri_dynamic_elem_nopreload_imported.mjs | 3 + ...ipt_module_sri_dynamic_elem_nopreload_prep.html | 10 + .../file_script_module_sri_dynamic_elem_prep.html | 10 + .../test/file_script_module_sri_elem_dynamic.html | 12 + .../test/file_script_module_sri_elem_dynamic.mjs | 6 + ...ile_script_module_sri_elem_dynamic_imported.mjs | 3 + .../file_script_module_sri_elem_dynamic_prep.html | 10 + .../test/file_script_module_sri_elem_elem_1.html | 12 + .../test/file_script_module_sri_elem_elem_1.mjs | 1 + .../file_script_module_sri_elem_elem_1_prep.html | 10 + .../test/file_script_module_sri_elem_elem_2.html | 12 + .../test/file_script_module_sri_elem_elem_2.mjs | 1 + .../file_script_module_sri_elem_elem_2_prep.html | 10 + .../test/file_script_module_sri_elem_import.html | 12 + .../test/file_script_module_sri_elem_import.mjs | 5 + ...file_script_module_sri_elem_import_imported.mjs | 3 + .../file_script_module_sri_elem_import_prep.html | 10 + dom/base/test/file_script_module_sri_fallback.html | 11 + dom/base/test/file_script_module_sri_fallback.mjs | 1 + .../file_script_module_sri_fallback_failure.html | 15 + .../file_script_module_sri_fallback_failure.mjs | 1 + ...le_script_module_sri_fallback_failure_prep.html | 10 + .../test/file_script_module_sri_fallback_prep.html | 10 + .../test/file_script_module_sri_import_elem.html | 12 + .../test/file_script_module_sri_import_elem.mjs | 5 + ...file_script_module_sri_import_elem_imported.mjs | 3 + ...le_script_module_sri_import_elem_nopreload.html | 10 + ...ile_script_module_sri_import_elem_nopreload.mjs | 19 + ...t_module_sri_import_elem_nopreload_imported.mjs | 3 + ...ript_module_sri_import_elem_nopreload_prep.html | 10 + .../file_script_module_sri_import_elem_prep.html | 10 + .../file_script_module_static_and_dynamic.html | 10 + .../test/file_script_module_static_and_dynamic.mjs | 9 + ...script_module_static_and_dynamic_imported_1.mjs | 5 + ...script_module_static_and_dynamic_imported_2.mjs | 6 + ...script_module_static_and_dynamic_imported_3.mjs | 1 + dom/base/test/file_serializer_noscript.html | 1 + dom/base/test/file_setname.html | 8 + dom/base/test/file_settimeout_inner.html | 6 + .../test/file_suppressed_events_and_scrolling.html | 30 + dom/base/test/file_suppressed_events_inner.html | 16 + dom/base/test/file_suppressed_events_middle.html | 10 + dom/base/test/file_suppressed_events_top.html | 79 + .../file_suppressed_events_top_modalstate.html | 79 + dom/base/test/file_suppressed_events_top_xhr.html | 82 + dom/base/test/file_timer_flood.html | 19 + dom/base/test/file_title.xhtml | 1 + dom/base/test/file_toScreenRect.html | 48 + dom/base/test/file_use_counter_bfcache.html | 38 + dom/base/test/file_use_counter_bfcache_helper.html | 40 + dom/base/test/file_use_counter_outer.html | 17 + .../test/file_use_counter_outer_display_none.html | 16 + dom/base/test/file_use_counter_style.html | 14 + .../test/file_use_counter_svg_currentScale.svg | 17 + .../test/file_use_counter_svg_fill_pattern.svg | 16 + .../file_use_counter_svg_fill_pattern_data.svg | 13 + ...ile_use_counter_svg_fill_pattern_definition.svg | 12 + .../file_use_counter_svg_fill_pattern_internal.svg | 24 + .../test/file_use_counter_svg_getElementById.svg | 22 + ...file_viewport_metrics_on_landscape_content.html | 65 + dom/base/test/file_viewport_scroll_quirks.html | 1 + dom/base/test/file_viewport_scroll_xml.xml | 1 + dom/base/test/file_webaudio_startstop.html | 36 + dom/base/test/file_window_close.html | 68 + dom/base/test/file_window_close_2.html | 4 + .../test/file_window_focus_by_close_and_open.html | 13 + dom/base/test/file_x-frame-options_main.html | 44 + dom/base/test/file_x-frame-options_page.sjs | 67 + dom/base/test/file_xhtmlserializer_1.xhtml | 60 + .../test/file_xhtmlserializer_1_bodyonly.xhtml | 56 + dom/base/test/file_xhtmlserializer_1_format.xhtml | 71 + .../test/file_xhtmlserializer_1_linebreak.xhtml | 65 + dom/base/test/file_xhtmlserializer_1_links.xhtml | 65 + .../test/file_xhtmlserializer_1_nested_body.xhtml | 65 + dom/base/test/file_xhtmlserializer_1_no_body.xhtml | 10 + dom/base/test/file_xhtmlserializer_1_noflag.xhtml | 65 + .../test/file_xhtmlserializer_1_noformatpre.xhtml | 69 + dom/base/test/file_xhtmlserializer_1_raw.xhtml | 60 + .../test/file_xhtmlserializer_1_sibling_body.xhtml | 65 + ..._xhtmlserializer_1_sibling_body_only_body.xhtml | 56 + dom/base/test/file_xhtmlserializer_1_wrap.xhtml | 70 + dom/base/test/file_xhtmlserializer_2.xhtml | 30 + dom/base/test/file_xhtmlserializer_2_basic.xhtml | 31 + dom/base/test/file_xhtmlserializer_2_enthtml.xhtml | 55 + dom/base/test/file_xhtmlserializer_2_entw3c.xhtml | 55 + dom/base/test/file_xhtmlserializer_2_latin1.xhtml | 41 + dom/base/test/file_youtube_flash_embed.html | 65 + dom/base/test/fmm/browser.toml | 4 + .../fmm/browser_frame_message_manager_cache.js | 23 + dom/base/test/forRemoval.resource | 24 + dom/base/test/forRemoval.resource^headers^ | 3 + dom/base/test/formReset.html | 15 + .../test/fullscreen/MozDomFullscreen_chrome.xhtml | 108 + dom/base/test/fullscreen/browser.toml | 54 + .../test/fullscreen/browser_fullscreen-api-keys.js | 218 + .../fullscreen/browser_fullscreen-bug-1798219.js | 127 + .../browser_fullscreen-contextmenu-esc.js | 128 + ...wser_fullscreen-document-mutation-navigation.js | 141 + .../browser_fullscreen-document-mutation-race.js | 122 + .../browser_fullscreen-document-mutation.js | 118 + .../browser_fullscreen-navigation-history-race.js | 128 + .../browser_fullscreen-navigation-history.js | 100 + .../browser_fullscreen-navigation-race.js | 162 + .../fullscreen/browser_fullscreen-navigation.js | 142 + .../test/fullscreen/browser_fullscreen-newtab.js | 91 + .../test/fullscreen/browser_fullscreen-sizemode.js | 225 + .../browser_fullscreen-tab-close-race.js | 105 + .../fullscreen/browser_fullscreen-tab-close.js | 65 + .../browser_fullscreen-window-open-race.js | 73 + ...browser_fullscreen_exit_on_external_protocol.js | 215 + dom/base/test/fullscreen/chrome.toml | 11 + dom/base/test/fullscreen/dummy_page.html | 10 + .../test/fullscreen/file_MozDomFullscreen.html | 8 + .../test/fullscreen/file_fullscreen-api-keys.html | 41 + .../test/fullscreen/file_fullscreen-api-race.html | 8 + dom/base/test/fullscreen/file_fullscreen-api.html | 340 + .../test/fullscreen/file_fullscreen-async.html | 50 + .../test/fullscreen/file_fullscreen-backdrop.html | 107 + .../fullscreen/file_fullscreen-bug-1798219-2.html | 22 + .../fullscreen/file_fullscreen-bug-1798219.html | 14 + .../fullscreen/file_fullscreen-denied-inner.html | 24 + .../test/fullscreen/file_fullscreen-denied.html | 171 + .../fullscreen/file_fullscreen-esc-exit-inner.html | 58 + .../test/fullscreen/file_fullscreen-esc-exit.html | 63 + .../fullscreen/file_fullscreen-event-order.html | 50 + .../file_fullscreen-featurePolicy-inner.html | 34 + .../fullscreen/file_fullscreen-featurePolicy.html | 90 + .../fullscreen/file_fullscreen-focus-inner.html | 24 + .../test/fullscreen/file_fullscreen-focus.html | 67 + .../test/fullscreen/file_fullscreen-hidden.html | 56 + .../fullscreen/file_fullscreen-iframe-inner.html | 5 + .../fullscreen/file_fullscreen-iframe-middle.html | 5 + .../fullscreen/file_fullscreen-iframe-top.html | 5 + .../file_fullscreen-lenient-setters.html | 61 + .../fullscreen/file_fullscreen-multiple-inner.html | 25 + .../test/fullscreen/file_fullscreen-multiple.html | 67 + .../fullscreen/file_fullscreen-navigation.html | 52 + .../test/fullscreen/file_fullscreen-nested.html | 130 + .../test/fullscreen/file_fullscreen-newtab.html | 4 + .../test/fullscreen/file_fullscreen-prefixed.html | 153 + .../test/fullscreen/file_fullscreen-resize.html | 39 + .../test/fullscreen/file_fullscreen-rollback.html | 140 + .../test/fullscreen/file_fullscreen-scrollbar.html | 147 + .../test/fullscreen/file_fullscreen-selector.html | 187 + .../test/fullscreen/file_fullscreen-shadowdom.html | 52 + .../test/fullscreen/file_fullscreen-single.html | 78 + .../fullscreen/file_fullscreen-sub-iframe.html | 53 + .../fullscreen/file_fullscreen-svg-element.html | 49 + .../test/fullscreen/file_fullscreen-table.html | 52 + .../test/fullscreen/file_fullscreen-top-layer.html | 160 + dom/base/test/fullscreen/file_fullscreen-utils.js | 87 + .../fullscreen/file_fullscreen-with-full-zoom.html | 36 + .../fullscreen/file_fullscreen_meta_viewport.html | 12 + dom/base/test/fullscreen/fullscreen.xhtml | 27 + dom/base/test/fullscreen/fullscreen_helpers.js | 174 + dom/base/test/fullscreen/head.js | 65 + dom/base/test/fullscreen/mochitest.toml | 64 + dom/base/test/fullscreen/moz.build | 17 + .../fullscreen/test_MozDomFullscreen_event.xhtml | 46 + .../test/fullscreen/test_fullscreen-api-race.html | 177 + .../test_fullscreen-api-rapid-cycle.html | 167 + dom/base/test/fullscreen/test_fullscreen-api.html | 150 + dom/base/test/fullscreen/test_fullscreen.xhtml | 37 + .../fullscreen/test_fullscreen_meta_viewport.html | 33 + .../test/fullscreen/test_fullscreen_modal.html | 69 + dom/base/test/green.png | Bin 0 -> 255 bytes dom/base/test/gtest/TestContentUtils.cpp | 221 + dom/base/test/gtest/TestMimeType.cpp | 1078 + dom/base/test/gtest/TestParser.cpp | 52 + dom/base/test/gtest/TestPlainTextSerializer.cpp | 340 + dom/base/test/gtest/TestScheduler.cpp | 348 + .../test/gtest/TestXMLSerializerNoBreakLink.cpp | 69 + dom/base/test/gtest/TestXPathGenerator.cpp | 150 + dom/base/test/gtest/moz.build | 21 + dom/base/test/head.js | 15 + dom/base/test/iframe1_bug1640766.html | 20 + dom/base/test/iframe1_bug426646.html | 1 + dom/base/test/iframe1_bug431701.html | 1 + dom/base/test/iframe2_bug1640766.html | 10 + dom/base/test/iframe2_bug426646.html | 1 + dom/base/test/iframe2_bug431701.html | 1 + dom/base/test/iframe3_bug431701.html | 1 + dom/base/test/iframe4_bug431701.xml | 1 + dom/base/test/iframe5_bug431701.xml | 1 + dom/base/test/iframe6_bug431701.xml | 1 + dom/base/test/iframe7_bug431701.xml | 1 + dom/base/test/iframe_bug962251.html | 25 + dom/base/test/iframe_bug976673.html | 26 + dom/base/test/iframe_main_bug1022229.html | 33 + dom/base/test/iframe_meta_refresh.sjs | 90 + dom/base/test/iframe_postMessage_solidus.html | 15 + dom/base/test/iframe_postMessages.html | 14 + dom/base/test/iframe_sandbox_bug1022229.html | 13 + dom/base/test/iframe_shared_compartment2a.html | 2 + dom/base/test/iframe_shared_compartment2b.html | 3 + .../intersectionobserver_cross_domain_iframe.html | 24 + dom/base/test/intersectionobserver_iframe.html | 17 + dom/base/test/intersectionobserver_window.html | 46 + dom/base/test/invalid_accesscontrol.resource | 7 + .../test/invalid_accesscontrol.resource^headers^ | 4 + dom/base/test/jsmodules/.eslintrc.js | 15 + dom/base/test/jsmodules/ambiguous_export.mjs | 3 + dom/base/test/jsmodules/chrome.toml | 94 + dom/base/test/jsmodules/exportA1.mjs | 1 + dom/base/test/jsmodules/exportA2.mjs | 1 + dom/base/test/jsmodules/export_ambiguous.mjs | 1 + .../test/jsmodules/iframe_extractIntroType.html | 14 + dom/base/test/jsmodules/import_ambiguous.mjs | 1 + .../jsmodules/import_ambiguous_indirect_export.mjs | 1 + dom/base/test/jsmodules/import_no_export.mjs | 1 + .../test/jsmodules/import_no_indirect_export.mjs | 2 + .../test/jsmodules/importmaps/bad/module_2.mjs | 1 + .../test/jsmodules/importmaps/bad/module_3.mjs | 8 + .../test/jsmodules/importmaps/bad/module_4.mjs | 1 + .../test/jsmodules/importmaps/bad/module_7.mjs | 1 + .../jsmodules/importmaps/bug_1865410_module_a.mjs | 2 + .../jsmodules/importmaps/bug_1865410_module_b.mjs | 1 + dom/base/test/jsmodules/importmaps/bug_1873417.mjs | 2 + dom/base/test/jsmodules/importmaps/chrome.toml | 37 + .../jsmodules/importmaps/circular_dependency.mjs | 6 + .../jsmodules/importmaps/external_importMap.js | 5 + .../test/jsmodules/importmaps/good/module_0.mjs | 1 + .../test/jsmodules/importmaps/good/module_1.mjs | 1 + .../test/jsmodules/importmaps/good/module_2.mjs | 1 + .../test/jsmodules/importmaps/good/module_3.mjs | 6 + .../test/jsmodules/importmaps/good/module_4.mjs | 1 + .../test/jsmodules/importmaps/good/module_7.mjs | 1 + .../jsmodules/importmaps/insert_a_base_element.js | 4 + dom/base/test/jsmodules/importmaps/mochitest.toml | 33 + .../module_importMap_with_external_script_0.mjs | 3 + .../module_importMap_with_external_script_1.mjs | 3 + .../module_importMap_with_external_script_2.mjs | 3 + .../module_importMap_with_external_script_3.mjs | 3 + .../module_importMap_with_external_script_4.mjs | 3 + .../module_importMap_with_external_script_5.mjs | 3 + ...e_importMap_with_external_script_5.mjs^headers^ | 2 + .../module_importMap_with_external_script_6.mjs | 3 + ...e_importMap_with_external_script_6.mjs^headers^ | 2 + .../module_importMap_with_external_script_7.mjs | 3 + .../jsmodules/importmaps/module_simpleExport.mjs | 1 + .../importmaps/module_simpleImportMap.mjs | 4 + .../importmaps/module_simpleImportMap_dir.mjs | 4 + .../importmaps/module_simpleImportMap_remap.mjs | 4 + .../module_simpleImportMap_remap_https.mjs | 4 + .../importmaps/module_sortedImportMap.mjs | 6 + dom/base/test/jsmodules/importmaps/moz.build | 9 + .../importmaps/scope1/module_simpleExport.mjs | 1 + .../importmaps/scope1/module_simpleImportMap.mjs | 4 + .../scope1/scope2/module_simpleExport.mjs | 1 + .../scope1/scope2/module_simpleImportMap.mjs | 4 + .../jsmodules/importmaps/test_bug_1865410.html | 27 + .../jsmodules/importmaps/test_bug_1873417.html | 39 + .../test_dynamic_import_reject_importMap.html | 46 + .../importmaps/test_externalImportMap.html | 43 + .../test_importMap_with_external_script.html | 75 + .../test_import_meta_resolve_importMap.html | 49 + .../test_inline_module_reject_importMap.html | 61 + .../importmaps/test_load_importMap_with_base.html | 51 + .../importmaps/test_load_importMap_with_base2.html | 51 + .../test_module_script_reject_importMap.html | 45 + .../importmaps/test_parse_importMap_failed.html | 40 + .../test_reject_multiple_importMaps.html | 64 + .../jsmodules/importmaps/test_simpleImportMap.html | 62 + .../jsmodules/importmaps/test_sortedImportMap.html | 62 + dom/base/test/jsmodules/module_badImport.mjs | 2 + dom/base/test/jsmodules/module_badSyntax.mjs | 3 + dom/base/test/jsmodules/module_cyclic1.mjs | 8 + dom/base/test/jsmodules/module_cyclic2.mjs | 8 + dom/base/test/jsmodules/module_cyclic3.mjs | 8 + .../test/jsmodules/module_extractIntroType.mjs | 6 + dom/base/test/jsmodules/module_large1.mjs | 78 + dom/base/test/jsmodules/module_large2.mjs | 78 + dom/base/test/jsmodules/module_large3.mjs | 78 + dom/base/test/jsmodules/module_missingImport.mjs | 1 + dom/base/test/jsmodules/module_multiImports.mjs | 6 + .../test/jsmodules/module_multiLargeImports.mjs | 6 + dom/base/test/jsmodules/module_setRan.mjs | 2 + dom/base/test/jsmodules/module_simple1.mjs | 1 + dom/base/test/jsmodules/module_simple2.mjs | 1 + dom/base/test/jsmodules/module_simple3.mjs | 1 + dom/base/test/jsmodules/module_simpleExport.mjs | 1 + dom/base/test/jsmodules/module_simpleImport.mjs | 3 + dom/base/test/jsmodules/module_testSyntax.mjs | 3 + dom/base/test/jsmodules/moz.build | 7 + dom/base/test/jsmodules/no_export.mjs | 1 + dom/base/test/jsmodules/no_indirect_export.mjs | 1 + dom/base/test/jsmodules/script_simple2.js | 1 + .../test/jsmodules/test_asyncInlineModules.html | 36 + dom/base/test/jsmodules/test_cyclicImport.html | 18 + .../jsmodules/test_dynamicImportErrorMessage.html | 16 + dom/base/test/jsmodules/test_importIntroType.html | 22 + dom/base/test/jsmodules/test_importNotFound.html | 27 + .../test/jsmodules/test_importResolveFailed.html | 21 + .../test/jsmodules/test_import_errorMessage.html | 47 + .../test/jsmodules/test_import_meta_resolve.html | 65 + .../jsmodules/test_importedModuleMemoization.html | 30 + .../test/jsmodules/test_linkErrorInCommon1.html | 32 + .../test/jsmodules/test_linkErrorInCommon2.html | 32 + dom/base/test/jsmodules/test_moduleNotFound.html | 24 + .../test/jsmodules/test_moduleParsedAsModule.html | 23 + dom/base/test/jsmodules/test_moduleScriptsRun.html | 19 + .../test/jsmodules/test_multiAsyncImports.html | 30 + .../test/jsmodules/test_multiModuleImports.html | 28 + .../jsmodules/test_multiModuleLargeImports.html | 28 + .../test/jsmodules/test_multiTopLevelImports.html | 30 + .../jsmodules/test_multiTopLevelLargeImports.html | 30 + .../test/jsmodules/test_scriptInsertedModule.html | 20 + .../test/jsmodules/test_scriptModuleOrder.html | 30 + .../jsmodules/test_scriptNotParsedAsModule.html | 23 + dom/base/test/jsmodules/test_simpleImport.html | 16 + dom/base/test/jsmodules/test_syntaxError.html | 30 + dom/base/test/jsmodules/test_syntaxErrorAsync.html | 30 + .../test/jsmodules/test_syntaxErrorInline.html | 34 + .../jsmodules/test_syntaxErrorInlineAsync.html | 34 + .../test/jsmodules/test_topLevelIntroType.html | 21 + .../jsmodules/test_toplevelModuleMemoization.html | 30 + .../jsmodules/test_typeAttrCaseInsensitive.html | 19 + dom/base/test/meta_viewport/mochitest.toml | 102 + dom/base/test/meta_viewport/moz.build | 9 + .../test/meta_viewport/test_meta_viewport0.html | 41 + .../test/meta_viewport/test_meta_viewport1.html | 41 + .../test/meta_viewport/test_meta_viewport2.html | 41 + .../test/meta_viewport/test_meta_viewport3.html | 43 + .../test/meta_viewport/test_meta_viewport4.html | 42 + .../test/meta_viewport/test_meta_viewport5.html | 24 + .../test/meta_viewport/test_meta_viewport6.html | 47 + .../test/meta_viewport/test_meta_viewport7.html | 71 + .../test/meta_viewport/test_meta_viewport8.html | 27 + ...t_meta_viewport_auto_size_by_device_height.html | 24 + ...st_meta_viewport_auto_size_by_device_width.html | 24 + ...o_size_by_fixed_height_and_initial_scale_1.html | 25 + ...auto_size_by_fixed_width_and_device_height.html | 25 + ...to_size_by_fixed_width_and_initial_scale_1.html | 25 + ...ta_viewport_auto_size_by_initial_scale_0_5.html | 25 + ...meta_viewport_auto_size_by_initial_scale_1.html | 25 + ...t_meta_viewport_auto_size_by_invalid_width.html | 24 + ...uto_size_by_invalid_width_and_fixed_height.html | 25 + ...eta_viewport_change_content_among_multiple.html | 52 + .../test_meta_viewport_change_name.html | 47 + ...t_meta_viewport_change_name_among_multiple.html | 44 + .../test_meta_viewport_device_width.html | 25 + ...ewport_device_width_with_initial_scale_0_5.html | 26 + ...viewport_device_width_with_initial_scale_2.html | 31 + ...wport_empty_content_and_valid_content_tags.html | 26 + .../test/meta_viewport/test_meta_viewport_fit.html | 34 + .../test_meta_viewport_fit_multiple.html | 25 + ...iewport_fixed_width_and_zero_display_width.html | 29 + .../test_meta_viewport_initial_scale_0_5.html | 33 + .../test_meta_viewport_initial_scale_2.html | 26 + ...ort_initial_scale_with_trailing_characters.html | 26 + ...t_meta_viewport_insert_before_existing_tag.html | 32 + .../test_meta_viewport_maximum_scale_0.html | 28 + .../test_meta_viewport_maximum_scale_0_5.html | 29 + .../test_meta_viewport_maximum_scale_2.html | 26 + .../test_meta_viewport_multiple_tags.html | 28 + ...iewport_negative_width_and_negative_height.html | 27 + ...meta_viewport_negative_width_and_no_height.html | 25 + ...a_viewport_negative_width_and_valid_height.html | 25 + ...viewport_no_content_and_valid_content_tags.html | 25 + ...meta_viewport_no_width_and_negative_height.html | 26 + ...st_meta_viewport_no_width_and_valid_height.html | 25 + .../test_meta_viewport_remove_node.html | 34 + ...st_meta_viewport_remove_node_from_multiple.html | 44 + ...t_meta_viewport_removing_content_attribute.html | 33 + .../test_meta_viewport_replace_content.html | 39 + .../test_meta_viewport_tiny_display_size.html | 28 + ...a_viewport_valid_width_and_negative_height.html | 26 + ...st_meta_viewport_valid_width_and_no_height.html | 26 + ...ta_viewport_width_with_trailing_characters.html | 26 + dom/base/test/meta_viewport/viewport_helpers.js | 44 + dom/base/test/mochitest.toml | 1788 + dom/base/test/moz.build | 44 + dom/base/test/object_bug353334.html | 1 + dom/base/test/object_bug455472.html | 1 + dom/base/test/red.png | Bin 0 -> 87 bytes dom/base/test/referrerHelper.js | 343 + dom/base/test/referrer_change_server.sjs | 169 + dom/base/test/referrer_header.sjs | 6 + dom/base/test/referrer_helper.js | 129 + dom/base/test/referrer_testserver.sjs | 691 + dom/base/test/reftest/mixed-bmp-png.ico | Bin 0 -> 17542 bytes dom/base/test/reftest/reftest.list | 7 + dom/base/test/reftest/test_bug1525662-ref.html | 15 + dom/base/test/reftest/test_bug1525662.txt | 7 + dom/base/test/reftest/test_bug920877-ref.html | 20 + dom/base/test/reftest/test_bug920877.html | 38 + .../test/reftest/test_xmlPrettyPrint_csp-ref.xml | 4 + dom/base/test/reftest/test_xmlPrettyPrint_csp.xml | 4 + .../reftest/test_xmlPrettyPrint_csp.xml^headers^ | 1 + dom/base/test/script-1_bug597345.sjs | 20 + dom/base/test/script-2_bug597345.js | 1 + dom/base/test/script_bug1238440.js | 34 + dom/base/test/script_bug602838.sjs | 43 + dom/base/test/script_postmessages_fileList.js | 27 + dom/base/test/send_gzip_content.sjs | 46 + dom/base/test/slow.sjs | 13 + dom/base/test/somedatas.resource | 16 + dom/base/test/somedatas.resource^headers^ | 3 + dom/base/test/test_EventSource_redirects.html | 53 + dom/base/test/test_Image_constructor.html | 32 + .../test/test_NodeIterator_basics_filters.xhtml | 178 + dom/base/test/test_NodeIterator_mutations_1.xhtml | 204 + dom/base/test/test_NodeIterator_mutations_2.html | 112 + dom/base/test/test_NodeIterator_mutations_3.html | 160 + dom/base/test/test_anchor_area_referrer.html | 127 + .../test/test_anchor_area_referrer_changing.html | 66 + .../test/test_anchor_area_referrer_invalid.html | 74 + dom/base/test/test_anchor_area_referrer_rel.html | 50 + .../test/test_anchor_target_blank_referrer.html | 136 + dom/base/test/test_anonymousContent_api.html | 30 + .../test_anonymousContent_append_after_reflow.html | 35 + dom/base/test/test_anonymousContent_canvas.html | 48 + dom/base/test/test_anonymousContent_insert.html | 42 + .../test_anonymousContent_manipulate_content.html | 41 + dom/base/test/test_anonymousContent_style_csp.html | 23 + .../test_anonymousContent_style_csp.html^headers^ | 1 + .../test/test_anonymousContent_xul_window.xhtml | 23 + dom/base/test/test_async_setTimeout_stack.html | 60 + ...test_async_setTimeout_stack_across_globals.html | 60 + dom/base/test/test_base.xhtml | 39 + dom/base/test/test_blockParsing.html | 136 + dom/base/test/test_blocking_image.html | 87 + dom/base/test/test_bug1008126.html | 62 + dom/base/test/test_bug1016960.html | 30 + dom/base/test/test_bug1022229.html | 33 + dom/base/test/test_bug1025933.html | 41 + dom/base/test/test_bug1037687.html | 32 + dom/base/test/test_bug1037687_subframe.html | 46 + dom/base/test/test_bug1043106.html | 44 + dom/base/test/test_bug1057176.html | 32 + dom/base/test/test_bug1060938.html | 44 + dom/base/test/test_bug1064481.html | 24 + dom/base/test/test_bug1070015.html | 53 + dom/base/test/test_bug1075702.html | 77 + dom/base/test/test_bug1091883.html | 89 + dom/base/test/test_bug1100912.html | 35 + dom/base/test/test_bug1101364.html | 93 + dom/base/test/test_bug1118689.html | 40 + dom/base/test/test_bug1120222.html | 31 + dom/base/test/test_bug1126851.html | 44 + dom/base/test/test_bug116083.html | 120 + dom/base/test/test_bug1163743.html | 44 + dom/base/test/test_bug1165501.html | 51 + dom/base/test/test_bug1187157.html | 30 + dom/base/test/test_bug1198095.html | 71 + dom/base/test/test_bug1222633.html | 110 + dom/base/test/test_bug1222633_link_update.html | 127 + dom/base/test/test_bug1238440.html | 88 + dom/base/test/test_bug1250148.html | 64 + dom/base/test/test_bug1259588.html | 13 + dom/base/test/test_bug1268962.html | 104 + dom/base/test/test_bug1274806.html | 31 + dom/base/test/test_bug1295852.html | 19 + dom/base/test/test_bug1307730.html | 44 + dom/base/test/test_bug1308069.html | 87 + dom/base/test/test_bug1314032.html | 38 + dom/base/test/test_bug1318303.html | 47 + dom/base/test/test_bug1375050.html | 33 + dom/base/test/test_bug1381710.html | 40 + dom/base/test/test_bug1399605.html | 32 + dom/base/test/test_bug1404385.html | 31 + dom/base/test/test_bug1406102.html | 41 + dom/base/test/test_bug1421568.html | 48 + dom/base/test/test_bug1433073.html | 89 + dom/base/test/test_bug1472427.html | 89 + dom/base/test/test_bug1499169.html | 32 + dom/base/test/test_bug1576154.html | 36 + dom/base/test/test_bug1632975.html | 54 + dom/base/test/test_bug1639328.html | 89 + dom/base/test/test_bug1640766.html | 67 + dom/base/test/test_bug1648887.html | 34 + dom/base/test/test_bug166235.html | 156 + dom/base/test/test_bug1667316.html | 147 + dom/base/test/test_bug1730284.html | 71 + dom/base/test/test_bug1739957.html | 40 + dom/base/test/test_bug1784187.html | 38 + dom/base/test/test_bug1799354.html | 77 + dom/base/test/test_bug199959.html | 39 + dom/base/test/test_bug218236.html | 139 + dom/base/test/test_bug218277.html | 28 + dom/base/test/test_bug238409.html | 45 + dom/base/test/test_bug254337.html | 42 + dom/base/test/test_bug270145.xhtml | 51 + dom/base/test/test_bug276037-1.html | 105 + dom/base/test/test_bug276037-2.xhtml | 106 + dom/base/test/test_bug282547.html | 104 + dom/base/test/test_bug28293.html | 86 + dom/base/test/test_bug28293.xhtml | 87 + dom/base/test/test_bug298064.html | 32 + dom/base/test/test_bug300992.html | 45 + dom/base/test/test_bug311681.xml | 103 + dom/base/test/test_bug313646.html | 62 + dom/base/test/test_bug320799.html | 74 + dom/base/test/test_bug322317.html | 33 + dom/base/test/test_bug326337.html | 35 + dom/base/test/test_bug331959.html | 151 + dom/base/test/test_bug333064.html | 59 + dom/base/test/test_bug333198.html | 84 + dom/base/test/test_bug333673.html | 30 + dom/base/test/test_bug337631.html | 99 + dom/base/test/test_bug338541.xhtml | 49 + dom/base/test/test_bug338583.html | 666 + dom/base/test/test_bug338679.html | 82 + dom/base/test/test_bug339494.html | 59 + dom/base/test/test_bug339494.xhtml | 58 + dom/base/test/test_bug343596.html | 51 + dom/base/test/test_bug345339.html | 93 + dom/base/test/test_bug346485.html | 77 + dom/base/test/test_bug352728.html | 122 + dom/base/test/test_bug352728.xhtml | 188 + dom/base/test/test_bug353334.html | 67 + dom/base/test/test_bug355026.html | 29 + dom/base/test/test_bug357450.html | 41 + dom/base/test/test_bug357450.xhtml | 39 + dom/base/test/test_bug357450_svg.xhtml | 46 + dom/base/test/test_bug357509.html | 36 + dom/base/test/test_bug358660.html | 37 + dom/base/test/test_bug362391.xhtml | 75 + dom/base/test/test_bug364092.xhtml | 46 + dom/base/test/test_bug364413.xhtml | 48 + dom/base/test/test_bug366944.html | 49 + dom/base/test/test_bug366946.html | 79 + dom/base/test/test_bug367164.html | 47 + dom/base/test/test_bug368972.html | 120 + dom/base/test/test_bug371576-2.html | 32 + dom/base/test/test_bug371576-3.html | 29 + dom/base/test/test_bug371576-4.html | 21 + dom/base/test/test_bug371576-5.html | 36 + dom/base/test/test_bug372086.html | 96 + dom/base/test/test_bug372964-2.html | 58 + dom/base/test/test_bug372964.html | 144 + dom/base/test/test_bug373181.xhtml | 17 + dom/base/test/test_bug375314-2.html | 151 + dom/base/test/test_bug375314.html | 157 + dom/base/test/test_bug378969.html | 48 + dom/base/test/test_bug380418.html | 34 + dom/base/test/test_bug380418.html^headers^ | 4 + dom/base/test/test_bug382113.html | 35 + dom/base/test/test_bug382871.html | 46 + dom/base/test/test_bug384003.xhtml | 84 + dom/base/test/test_bug390219.html | 38 + dom/base/test/test_bug390735.html | 28 + dom/base/test/test_bug392318.html | 44 + dom/base/test/test_bug392511.html | 53 + dom/base/test/test_bug393968.html | 34 + dom/base/test/test_bug395915.html | 43 + dom/base/test/test_bug397234.html | 35 + dom/base/test/test_bug398243.html | 56 + dom/base/test/test_bug401662.html | 51 + dom/base/test/test_bug402150.html | 24 + dom/base/test/test_bug402150.html^headers^ | 1 + dom/base/test/test_bug403841.html | 29 + dom/base/test/test_bug403852.html | 66 + dom/base/test/test_bug403868.xml | 85 + dom/base/test/test_bug405182.html | 47 + dom/base/test/test_bug409380.html | 378 + dom/base/test/test_bug410229.html | 108 + dom/base/test/test_bug413974.html | 35 + dom/base/test/test_bug414190.html | 70 + dom/base/test/test_bug415860.html | 240 + dom/base/test/test_bug416317-1.html | 32 + dom/base/test/test_bug416317-2.html | 32 + dom/base/test/test_bug416383.html | 43 + dom/base/test/test_bug417255.html | 60 + dom/base/test/test_bug417384.html | 50 + dom/base/test/test_bug418214.html | 105 + dom/base/test/test_bug418986-1.html | 24 + dom/base/test/test_bug419132.html | 48 + dom/base/test/test_bug419527.xhtml | 68 + dom/base/test/test_bug420609.xhtml | 34 + dom/base/test/test_bug420700.html | 35 + dom/base/test/test_bug421602.html | 53 + dom/base/test/test_bug422403-1.html | 204 + dom/base/test/test_bug422403-2.xhtml | 296 + dom/base/test/test_bug422537.html | 55 + dom/base/test/test_bug424212.html | 35 + dom/base/test/test_bug424359-1.html | 213 + dom/base/test/test_bug424359-2.html | 301 + dom/base/test/test_bug426308.html | 42 + dom/base/test/test_bug426646.html | 41 + dom/base/test/test_bug428847.html | 33 + dom/base/test/test_bug431082.html | 51 + dom/base/test/test_bug431701.html | 119 + dom/base/test/test_bug431833.html | 51 + dom/base/test/test_bug433533.html | 300 + dom/base/test/test_bug433662.html | 31 + dom/base/test/test_bug435425.html | 430 + dom/base/test/test_bug444322.html | 2588 ++ dom/base/test/test_bug444546.html | 160 + dom/base/test/test_bug444722.html | 65 + dom/base/test/test_bug448993.html | 46 + dom/base/test/test_bug450160.html | 100 + dom/base/test/test_bug451376.html | 86 + dom/base/test/test_bug453521.html | 36 + dom/base/test/test_bug453736.html | 58 + dom/base/test/test_bug454325.html | 147 + dom/base/test/test_bug454326.html | 135 + dom/base/test/test_bug455472.html | 41 + dom/base/test/test_bug455629.html | 63 + dom/base/test/test_bug456262.html | 39 + dom/base/test/test_bug457746.html | 38 + dom/base/test/test_bug459424.html | 31 + dom/base/test/test_bug461555.html | 46 + dom/base/test/test_bug461735.html | 50 + dom/base/test/test_bug465767.html | 42 + dom/base/test/test_bug466080.html | 151 + dom/base/test/test_bug466409.html | 34 + dom/base/test/test_bug466751.xhtml | 40 + dom/base/test/test_bug469020.html | 128 + dom/base/test/test_bug469304.html | 187 + dom/base/test/test_bug473162-1.html | 30 + dom/base/test/test_bug473162-2.html | 33 + dom/base/test/test_bug475156.html | 301 + dom/base/test/test_bug482935.html | 72 + dom/base/test/test_bug484396.html | 48 + dom/base/test/test_bug493881.html | 31 + dom/base/test/test_bug493881.js | 100 + dom/base/test/test_bug498240.html | 254 + dom/base/test/test_bug498433.html | 104 + dom/base/test/test_bug498897.html | 97 + dom/base/test/test_bug499656.html | 57 + dom/base/test/test_bug499656.xhtml | 57 + dom/base/test/test_bug500937.html | 54 + dom/base/test/test_bug503473.html | 37 + dom/base/test/test_bug503481.html | 69 + dom/base/test/test_bug503481b.html | 22 + dom/base/test/test_bug51034.html | 42 + dom/base/test/test_bug513194.html | 28 + dom/base/test/test_bug5141.html | 30 + dom/base/test/test_bug514487.html | 49 + dom/base/test/test_bug515401.html | 141 + dom/base/test/test_bug518104.html | 41 + dom/base/test/test_bug527896.html | 61 + dom/base/test/test_bug540854.html | 47 + dom/base/test/test_bug541937.html | 118 + dom/base/test/test_bug544642.html | 42 + dom/base/test/test_bug545644.html | 42 + dom/base/test/test_bug545644.xhtml | 49 + dom/base/test/test_bug548463.html | 66 + dom/base/test/test_bug553896.xhtml | 69 + dom/base/test/test_bug557892.html | 34 + dom/base/test/test_bug558726.html | 40 + dom/base/test/test_bug559526.html | 93 + dom/base/test/test_bug560780.html | 99 + dom/base/test/test_bug562137.html | 32 + dom/base/test/test_bug562169-1.html | 44 + dom/base/test/test_bug562169-2.html | 29 + dom/base/test/test_bug562652.html | 51 + dom/base/test/test_bug564047.html | 31 + dom/base/test/test_bug564863-2.xhtml | 170 + dom/base/test/test_bug564863.xhtml | 305 + dom/base/test/test_bug567350.html | 24 + dom/base/test/test_bug574596.html | 94 + dom/base/test/test_bug578096.html | 49 + dom/base/test/test_bug585978.html | 38 + dom/base/test/test_bug587931.html | 102 + dom/base/test/test_bug588990.html | 332 + dom/base/test/test_bug590812.html | 48 + dom/base/test/test_bug590870.html | 44 + dom/base/test/test_bug592366.html | 59 + dom/base/test/test_bug592829.html | 40 + dom/base/test/test_bug597345.html | 27 + dom/base/test/test_bug599295.html | 47 + dom/base/test/test_bug599588.html | 39 + dom/base/test/test_bug601803.html | 35 + dom/base/test/test_bug602838.html | 68 + dom/base/test/test_bug604592.html | 37 + dom/base/test/test_bug604660.html | 77 + dom/base/test/test_bug605982.html | 34 + dom/base/test/test_bug606729.html | 52 + dom/base/test/test_bug614058.html | 29 + dom/base/test/test_bug622088.html | 96 + dom/base/test/test_bug622117.html | 49 + dom/base/test/test_bug622246.html | 49 + dom/base/test/test_bug625722.html | 39 + dom/base/test/test_bug626262.html | 54 + dom/base/test/test_bug628938.html | 239 + dom/base/test/test_bug631615.html | 39 + dom/base/test/test_bug638112.html | 46 + dom/base/test/test_bug647518.html | 45 + dom/base/test/test_bug650001.html | 30 + dom/base/test/test_bug650776.html | 109 + dom/base/test/test_bug650784.html | 37 + dom/base/test/test_bug656283.html | 58 + dom/base/test/test_bug664916.html | 39 + dom/base/test/test_bug666604.html | 149 + dom/base/test/test_bug675121.html | 45 + dom/base/test/test_bug675166.html | 57 + dom/base/test/test_bug682463.html | 156 + dom/base/test/test_bug682554.html | 30 + dom/base/test/test_bug682592.html | 178 + dom/base/test/test_bug684671.html | 45 + dom/base/test/test_bug685798.html | 45 + dom/base/test/test_bug686449.xhtml | 79 + dom/base/test/test_bug687859.html | 33 + dom/base/test/test_bug690056.html | 54 + dom/base/test/test_bug692434.html | 44 + dom/base/test/test_bug693615.html | 41 + dom/base/test/test_bug693875.html | 34 + dom/base/test/test_bug694754.xhtml | 70 + dom/base/test/test_bug696301-1.html | 78 + dom/base/test/test_bug696301-2.html | 80 + dom/base/test/test_bug698381.html | 55 + dom/base/test/test_bug698384.html | 61 + dom/base/test/test_bug704063.html | 56 + dom/base/test/test_bug704320-1.html | 90 + dom/base/test/test_bug704320-2.html | 99 + dom/base/test/test_bug704320_policyset.html | 104 + dom/base/test/test_bug704320_policyset2.html | 45 + dom/base/test/test_bug704320_preload.html | 136 + dom/base/test/test_bug707142.html | 51 + dom/base/test/test_bug708620.html | 41 + dom/base/test/test_bug711047.html | 16 + dom/base/test/test_bug711180.html | 25 + dom/base/test/test_bug719533.html | 27 + dom/base/test/test_bug726364.html | 48 + dom/base/test/test_bug737087.html | 37 + dom/base/test/test_bug737565.html | 64 + dom/base/test/test_bug737612.html | 29 + dom/base/test/test_bug738108.html | 39 + dom/base/test/test_bug744830.html | 132 + dom/base/test/test_bug749367.html | 29 + dom/base/test/test_bug750096.html | 44 + dom/base/test/test_bug753278.html | 46 + dom/base/test/test_bug761120.html | 41 + dom/base/test/test_bug769117.html | 55 + dom/base/test/test_bug782342.html | 85 + dom/base/test/test_bug787778.html | 25 + dom/base/test/test_bug789315.html | 49 + dom/base/test/test_bug789856.html | 42 + dom/base/test/test_bug809003.html | 47 + dom/base/test/test_bug810494.html | 46 + dom/base/test/test_bug811701.html | 48 + dom/base/test/test_bug811701.xhtml | 52 + dom/base/test/test_bug813919.html | 46 + dom/base/test/test_bug814576.html | 41 + dom/base/test/test_bug819051.html | 59 + dom/base/test/test_bug820909.html | 87 + dom/base/test/test_bug864595.html | 34 + dom/base/test/test_bug868999.html | 39 + dom/base/test/test_bug869000.html | 37 + dom/base/test/test_bug869002.html | 32 + dom/base/test/test_bug869006.html | 37 + dom/base/test/test_bug876282.html | 45 + dom/base/test/test_bug891952.html | 61 + dom/base/test/test_bug894874.html | 45 + dom/base/test/test_bug895974.html | 69 + dom/base/test/test_bug907892.html | 49 + dom/base/test/test_bug913761.html | 40 + dom/base/test/test_bug922681.html | 113 + dom/base/test/test_bug927196.html | 56 + dom/base/test/test_bug945152.html | 58 + dom/base/test/test_bug962251.html | 244 + dom/base/test/test_bug976673.html | 105 + dom/base/test/test_bug982153.html | 29 + dom/base/test/test_bug999456.html | 32 + dom/base/test/test_caretPositionFromPoint.html | 131 + dom/base/test/test_change_policy.html | 134 + dom/base/test/test_clearTimeoutIntervalNoArg.html | 14 + dom/base/test/test_clipboard_nbsp.html | 116 + dom/base/test/test_constructor-assignment.html | 61 + dom/base/test/test_constructor.html | 61 + .../test/test_content_iterator_post_order.html | 875 + dom/base/test/test_content_iterator_pre_order.html | 869 + dom/base/test/test_content_iterator_subtree.html | 690 + dom/base/test/test_copyimage.html | 87 + dom/base/test/test_copypaste.html | 125 + dom/base/test/test_copypaste.xhtml | 112 + dom/base/test/test_copypaste_disabled.html | 116 + dom/base/test/test_createHTMLDocument.html | 52 + dom/base/test/test_current_inner_window.html | 61 + dom/base/test/test_custom_element.html | 29 + dom/base/test/test_custom_element_reflector.html | 27 + dom/base/test/test_data_uri.html | 189 + dom/base/test/test_delazification_strategy.html | 174 + dom/base/test/test_document.all_iteration.html | 11 + dom/base/test/test_document.all_unqualified.html | 35 + dom/base/test/test_document_constructor.html | 31 + .../test/test_document_importNode_document.html | 32 + dom/base/test/test_document_wireframe.html | 354 + dom/base/test/test_domparser_null_char.html | 27 + dom/base/test/test_domparsing.html | 84 + dom/base/test/test_domrequest.html | 233 + dom/base/test/test_domrequesthelper.xhtml | 549 + dom/base/test/test_domwindowutils.html | 127 + dom/base/test/test_element.matches.html | 28 + dom/base/test/test_elementTraversal.html | 112 + dom/base/test/test_element_closest.html | 84 + dom/base/test/test_embed_xorigin_document.html | 84 + .../test/test_encodeToStringWithMaxLength.html | 60 + ...ncodeToStringWithRequiresReinitAfterOutput.html | 87 + .../test_eventsource_event_listener_leaks.html | 40 + dom/base/test/test_eventsourceservice_basic.html | 69 + .../test_eventsourceservice_reconnect_error.html | 72 + .../test/test_eventsourceservice_status_error.html | 67 + dom/base/test/test_eventsourceservice_worker.html | 61 + dom/base/test/test_explicit_user_agent.html | 64 + dom/base/test/test_find.html | 210 + dom/base/test/test_find_bug1601118.html | 61 + dom/base/test/test_find_bug1654683.html | 30 + dom/base/test/test_find_nac.html | 13 + dom/base/test/test_focus_design_mode.html | 62 + .../test_focus_display_none_xorigin_iframe.html | 134 + dom/base/test/test_focus_keyboard_event.html | 48 + dom/base/test/test_focus_scroll_padding_tab.html | 74 + dom/base/test/test_focus_scrollable_fieldset.html | 60 + dom/base/test/test_focus_scrollable_input.html | 56 + dom/base/test/test_focus_shadow_dom.html | 36 + dom/base/test/test_focus_shadow_dom_root.html | 41 + dom/base/test/test_fragment_sanitization.xhtml | 98 + .../test_getAttribute_after_createAttribute.html | 15 + dom/base/test/test_getElementById.html | 58 + ...etLastOverWindowPointerLocationInCSSPixels.html | 83 + dom/base/test/test_getTranslationNodes.html | 225 + dom/base/test/test_getTranslationNodes_limit.html | 31 + dom/base/test/test_gsp-qualified.html | 38 + dom/base/test/test_gsp-quirks.html | 27 + dom/base/test/test_gsp-standards.html | 27 + dom/base/test/test_history_document_open.html | 37 + dom/base/test/test_history_state_null.html | 25 + dom/base/test/test_html_colors_quirks.html | 711 + dom/base/test/test_html_colors_standards.html | 712 + dom/base/test/test_htmlcopyencoder.html | 195 + dom/base/test/test_htmlcopyencoder.xhtml | 179 + .../test/test_iframe_event_listener_leaks.html | 41 + dom/base/test/test_iframe_referrer.html | 107 + dom/base/test/test_iframe_referrer_changing.html | 50 + dom/base/test/test_iframe_referrer_invalid.html | 81 + dom/base/test/test_innersize_scrollport.html | 38 + ...est_input_vsync_alignment_inner_event_loop.html | 49 + ...st_input_vsync_alignment_input_while_vsync.html | 47 + ...st_input_vsync_alignment_lower_than_normal.html | 51 + .../test/test_integer_attr_with_leading_zero.html | 64 + dom/base/test/test_intersectionobservers.html | 1221 + dom/base/test/test_link_prefetch.html | 220 + dom/base/test/test_link_preload.html | 296 + dom/base/test/test_link_stylesheet.html | 221 + .../test/test_location_href_unknown_protocol.html | 27 + .../test_lock_orientation_after_fullscreen.html | 58 + ...t_lock_orientation_with_pending_fullscreen.html | 127 + dom/base/test/test_messagePort.html | 114 + .../test/test_messagemanager_send_principal.html | 108 + dom/base/test/test_meta_refresh_referrer.html | 98 + dom/base/test/test_mozMatchesSelector.html | 14 + dom/base/test/test_mutationobservers.html | 862 + dom/base/test/test_named_frames.html | 38 + dom/base/test/test_navigatorPrefOverride.html | 51 + dom/base/test/test_navigator_cookieEnabled.html | 124 + .../test/test_navigator_hardwareConcurrency.html | 42 + dom/base/test/test_navigator_language.html | 213 + .../test_navigator_resolve_identity_xrays.xhtml | 39 + ...test_nested_event_loop_spin_and_idle_tasks.html | 34 + dom/base/test/test_nodelist_holes.html | 42 + dom/base/test/test_openDialogChromeOnly.html | 38 + dom/base/test/test_open_null_features.html | 54 + dom/base/test/test_pasting_svg_image.html | 99 + dom/base/test/test_pdf_print.html | 62 + dom/base/test/test_plugin_freezing.html | 68 + .../test/test_postMessage_originAttributes.html | 53 + dom/base/test/test_postMessage_solidus.html | 93 + .../test/test_postMessages_broadcastChannel.html | 167 + dom/base/test/test_postMessages_messagePort.html | 114 + dom/base/test/test_postMessages_window.html | 124 + dom/base/test/test_postMessages_workers.html | 111 + ..._processing_instruction_update_stylesheet.xhtml | 46 + .../test/test_progress_events_for_gzip_data.html | 44 + dom/base/test/test_pushState_structuredclone.html | 51 + dom/base/test/test_range_bounds.html | 305 + dom/base/test/test_reentrant_flush.html | 60 + dom/base/test/test_root_iframe.html | 27 + dom/base/test/test_sandbox_and_document_uri.html | 31 + dom/base/test/test_sandbox_structuredclone.html | 21 + dom/base/test/test_sandboxed_blob_uri.html | 22 + dom/base/test/test_sanitize_xhr.html | 35 + dom/base/test/test_screen_orientation.html | 86 + .../test_script_loader_crossorigin_data_url.html | 38 + dom/base/test/test_script_loader_js_cache.html | 264 + .../test/test_script_loader_js_cache_frames.html | 202 + .../test/test_script_loader_js_cache_module.html | 537 + .../test_script_loader_js_cache_module_sri.html | 425 + .../test_sendQueryContentAndSelectionSetEvent.html | 257 + ...test_sendSelectionSetEvent_with_same_range.html | 102 + dom/base/test/test_serializer_noscript.html | 38 + dom/base/test/test_setInterval_from_start.html | 57 + .../test_setInterval_uncatchable_exception.html | 55 + dom/base/test/test_setTimeoutWith0.html | 23 + dom/base/test/test_settimeout_extra_arguments.html | 14 + dom/base/test/test_settimeout_inner.html | 59 + dom/base/test/test_setting_opener.html | 125 + dom/base/test/test_shared_compartment1.html | 77 + dom/base/test/test_shared_compartment2.html | 47 + dom/base/test/test_structuredclone_backref.html | 32 + dom/base/test/test_structuredclone_error.html | 23 + dom/base/test/test_style_cssText.html | 85 + .../test/test_suppressed_events_and_scrolling.html | 47 + .../test/test_suppressed_events_nested_iframe.html | 71 + dom/base/test/test_suppressed_microtasks.html | 62 + dom/base/test/test_text_wholeText.html | 232 + .../test/test_textnode_normalize_in_selection.html | 201 + .../test/test_textnode_split_in_selection.html | 221 + dom/base/test/test_timeout_clamp.html | 162 + dom/base/test/test_timer_flood.html | 118 + dom/base/test/test_title.html | 52 + dom/base/test/test_toScreenRect.html | 9 + dom/base/test/test_treewalker_nextsibling.xml | 96 + dom/base/test/test_urgent_start.html | 275 + dom/base/test/test_user_select.html | 357 + ...test_viewport_metrics_on_landscape_content.html | 20 + dom/base/test/test_viewport_scroll.html | 89 + .../test/test_viewsource_forbidden_in_object.html | 61 + dom/base/test/test_w3element_traversal.html | 148 + dom/base/test/test_w3element_traversal.xhtml | 149 + dom/base/test/test_w3element_traversal_svg.html | 107 + ...est_warning_for_blocked_cross_site_request.html | 129 + dom/base/test/test_window_close.html | 93 + dom/base/test/test_window_constructor.html | 36 + dom/base/test/test_window_content.html | 28 + dom/base/test/test_window_cross_origin_props.html | 101 + .../test/test_window_define_nonconfigurable.html | 111 + dom/base/test/test_window_define_symbol.html | 29 + dom/base/test/test_window_element_enumeration.html | 70 + dom/base/test/test_window_enumeration.html | 33 + dom/base/test/test_window_extensible.html | 46 + .../test/test_window_focus_by_close_and_open.html | 34 + dom/base/test/test_window_indexing.html | 139 + dom/base/test/test_window_keys.html | 28 + .../test/test_window_named_frame_enumeration.html | 96 + dom/base/test/test_window_own_props.html | 29 + dom/base/test/test_window_proto.html | 17 + dom/base/test/test_writable-replaceable.html | 49 + dom/base/test/test_x-frame-options.html | 195 + dom/base/test/test_youtube_flash_embed.html | 32 + dom/base/test/unit/1_original.xml | 3 + dom/base/test/unit/1_result.xml | 3 + dom/base/test/unit/2_original.xml | 13 + dom/base/test/unit/2_result_1.xml | 13 + dom/base/test/unit/2_result_2.xml | 14 + dom/base/test/unit/2_result_3.xml | 23 + dom/base/test/unit/2_result_4.xml | 21 + dom/base/test/unit/3_original.xml | 4 + dom/base/test/unit/3_result.xml | 7 + dom/base/test/unit/3_result_2.xml | 7 + dom/base/test/unit/4_original.xml | 32 + dom/base/test/unit/4_result_1.xml | 32 + dom/base/test/unit/4_result_2.xml | 7 + dom/base/test/unit/4_result_3.xml | 4 + dom/base/test/unit/4_result_4.xml | 4 + dom/base/test/unit/4_result_5.xml | 46 + dom/base/test/unit/4_result_6.xml | 48 + dom/base/test/unit/empty_document.xml | 3 + dom/base/test/unit/head_utilities.js | 71 + dom/base/test/unit/head_xml.js | 152 + dom/base/test/unit/isequalnode_data.xml | 150 + dom/base/test/unit/nodelist_data_1.xml | 58 + dom/base/test/unit/nodelist_data_2.xhtml | 45 + dom/base/test/unit/test_blockParsing.js | 121 + dom/base/test/unit/test_bug553888.js | 59 + dom/base/test/unit/test_bug737966.js | 16 + dom/base/test/unit/test_cancelPrefetch.js | 149 + dom/base/test/unit/test_chromeutils_base64.js | 140 + .../test/unit/test_chromeutils_defineLazyGetter.js | 25 + .../unit/test_chromeutils_getXPCOMErrorName.js | 40 + .../test/unit/test_chromeutils_shallowclone.js | 60 + dom/base/test/unit/test_delete_range.xml | 125 + dom/base/test/unit/test_error_codes.js | 56 + dom/base/test/unit/test_generate_xpath.js | 85 + dom/base/test/unit/test_htmlserializer.js | 70 + dom/base/test/unit/test_isequalnode.js | 390 + .../test/unit/test_js_dev_error_interceptor.js | 53 + dom/base/test/unit/test_nodelist.js | 345 + dom/base/test/unit/test_normalize.js | 100 + dom/base/test/unit/test_range.js | 465 + dom/base/test/unit/test_serializers_entities.js | 99 + .../test/unit/test_serializers_entities_in_attr.js | 108 + dom/base/test/unit/test_structuredcloneholder.js | 159 + dom/base/test/unit/test_thirdpartyutil.js | 99 + dom/base/test/unit/test_treewalker.js | 23 + dom/base/test/unit/test_xhr_document.js | 49 + dom/base/test/unit/test_xhr_origin_attributes.js | 53 + dom/base/test/unit/test_xhr_standalone.js | 19 + dom/base/test/unit/test_xml_parser.js | 48 + dom/base/test/unit/test_xml_serializer.js | 421 + dom/base/test/unit/test_xmlserializer.js | 179 + dom/base/test/unit/xpcshell.toml | 97 + dom/base/test/unit_ipc/test_bug553888_wrap.js | 3 + dom/base/test/unit_ipc/test_xhr_document_ipc.js | 3 + dom/base/test/unit_ipc/xpcshell.toml | 16 + .../test/useractivation/file_clipboard_common.js | 505 + dom/base/test/useractivation/file_empty.html | 0 .../file_iframe_check_user_activation.html | 22 + .../file_iframe_consume_user_activation.html | 15 + .../useractivation/file_iframe_user_activated.html | 14 + ...ile_useractivation_sandbox_transient_popup.html | 20 + dom/base/test/useractivation/mochitest.toml | 33 + dom/base/test/useractivation/moz.build | 9 + .../test/useractivation/test_clipboard_editor.html | 31 + .../useractivation/test_clipboard_noeditor.html | 29 + .../test_popup_blocker_async_callback.html | 83 + .../test_popup_blocker_mouse_event.html | 98 + .../test_popup_blocker_pointer_event.html | 122 + .../test_useractivation_has_been_activated.html | 115 + .../test_useractivation_key_events.html | 87 + .../test_useractivation_sandbox_transient.html | 90 + .../test_useractivation_scrollbar.html | 135 + .../test_useractivation_transient.html | 155 + .../test_useractivation_transient_consuming.html | 151 + dom/base/test/variable_style_sheet.sjs | 18 + dom/base/test/w3element_traversal.svg | 70 + dom/base/test/wholeTexty-helper.xml | 6 + dom/base/test/worker_postMessages.js | 73 + dom/base/use_counter_metrics.yaml | 39346 +++++++++++++++++++ dom/base/usecounters.py | 792 + 2209 files changed, 353222 insertions(+) create mode 100644 dom/base/AbstractRange.cpp create mode 100644 dom/base/AbstractRange.h create mode 100644 dom/base/AncestorIterator.h create mode 100644 dom/base/AnimationFrameProvider.cpp create mode 100644 dom/base/AnimationFrameProvider.h create mode 100644 dom/base/AnonymousContent.cpp create mode 100644 dom/base/AnonymousContent.h create mode 100644 dom/base/Attr.cpp create mode 100644 dom/base/Attr.h create mode 100644 dom/base/AttrArray.cpp create mode 100644 dom/base/AttrArray.h create mode 100644 dom/base/AutoPrintEventDispatcher.h create mode 100644 dom/base/AutoSuppressEventHandlingAndSuspend.h create mode 100644 dom/base/AutocompleteFieldList.h create mode 100644 dom/base/BarProps.cpp create mode 100644 dom/base/BarProps.h create mode 100644 dom/base/BindContext.cpp create mode 100644 dom/base/BindContext.h create mode 100644 dom/base/BodyConsumer.cpp create mode 100644 dom/base/BodyConsumer.h create mode 100644 dom/base/BodyUtil.cpp create mode 100644 dom/base/BodyUtil.h create mode 100644 dom/base/BorrowedAttrInfo.cpp create mode 100644 dom/base/BorrowedAttrInfo.h create mode 100644 dom/base/CCGCScheduler.cpp create mode 100644 dom/base/CCGCScheduler.h create mode 100644 dom/base/CORSMode.h create mode 100644 dom/base/CallState.h create mode 100644 dom/base/CharacterData.cpp create mode 100644 dom/base/CharacterData.h create mode 100644 dom/base/ChildIterator.cpp create mode 100644 dom/base/ChildIterator.h create mode 100644 dom/base/ChildProcessMessageManager.h create mode 100644 dom/base/ChromeMessageBroadcaster.cpp create mode 100644 dom/base/ChromeMessageBroadcaster.h create mode 100644 dom/base/ChromeMessageSender.cpp create mode 100644 dom/base/ChromeMessageSender.h create mode 100644 dom/base/ChromeNodeList.cpp create mode 100644 dom/base/ChromeNodeList.h create mode 100644 dom/base/ChromeUtils.cpp create mode 100644 dom/base/ChromeUtils.h create mode 100644 dom/base/Comment.cpp create mode 100644 dom/base/Comment.h create mode 100644 dom/base/CompressionStream.cpp create mode 100644 dom/base/CompressionStream.h create mode 100644 dom/base/ContentAreaDropListener.sys.mjs create mode 100644 dom/base/ContentFrameMessageManager.cpp create mode 100644 dom/base/ContentFrameMessageManager.h create mode 100644 dom/base/ContentIterator.cpp create mode 100644 dom/base/ContentIterator.h create mode 100644 dom/base/ContentProcessMessageManager.cpp create mode 100644 dom/base/ContentProcessMessageManager.h create mode 100644 dom/base/Crypto.cpp create mode 100644 dom/base/Crypto.h create mode 100644 dom/base/CustomElementRegistry.cpp create mode 100644 dom/base/CustomElementRegistry.h create mode 100644 dom/base/DOMArena.h create mode 100644 dom/base/DOMException.cpp create mode 100644 dom/base/DOMException.h create mode 100644 dom/base/DOMImplementation.cpp create mode 100644 dom/base/DOMImplementation.h create mode 100644 dom/base/DOMIntersectionObserver.cpp create mode 100644 dom/base/DOMIntersectionObserver.h create mode 100644 dom/base/DOMMatrix.cpp create mode 100644 dom/base/DOMMatrix.h create mode 100644 dom/base/DOMMozPromiseRequestHolder.h create mode 100644 dom/base/DOMParser.cpp create mode 100644 dom/base/DOMParser.h create mode 100644 dom/base/DOMPoint.cpp create mode 100644 dom/base/DOMPoint.h create mode 100644 dom/base/DOMQuad.cpp create mode 100644 dom/base/DOMQuad.h create mode 100644 dom/base/DOMRect.cpp create mode 100644 dom/base/DOMRect.h create mode 100644 dom/base/DOMRequest.cpp create mode 100644 dom/base/DOMRequest.h create mode 100644 dom/base/DOMRequestHelper.sys.mjs create mode 100644 dom/base/DOMStringList.cpp create mode 100644 dom/base/DOMStringList.h create mode 100644 dom/base/DOMTokenListSupportedTokens.h create mode 100644 dom/base/DecompressionStream.cpp create mode 100644 dom/base/DecompressionStream.h create mode 100644 dom/base/DirectionalityUtils.cpp create mode 100644 dom/base/DirectionalityUtils.h create mode 100644 dom/base/DocGroup.cpp create mode 100644 dom/base/DocGroup.h create mode 100644 dom/base/Document.cpp create mode 100644 dom/base/Document.h create mode 100644 dom/base/DocumentFragment.cpp create mode 100644 dom/base/DocumentFragment.h create mode 100644 dom/base/DocumentInlines.h create mode 100644 dom/base/DocumentOrShadowRoot.cpp create mode 100644 dom/base/DocumentOrShadowRoot.h create mode 100644 dom/base/DocumentType.cpp create mode 100644 dom/base/DocumentType.h create mode 100644 dom/base/Element.cpp create mode 100644 dom/base/Element.h create mode 100644 dom/base/ElementInlines.h create mode 100644 dom/base/EventSource.cpp create mode 100644 dom/base/EventSource.h create mode 100644 dom/base/EventSourceEventService.cpp create mode 100644 dom/base/EventSourceEventService.h create mode 100644 dom/base/External.cpp create mode 100644 dom/base/External.h create mode 100644 dom/base/FilteredNodeIterator.h create mode 100644 dom/base/FlushType.h create mode 100644 dom/base/FormData.cpp create mode 100644 dom/base/FormData.h create mode 100644 dom/base/FragmentOrElement.cpp create mode 100644 dom/base/FragmentOrElement.h create mode 100644 dom/base/FromParser.h create mode 100644 dom/base/FullscreenChange.h create mode 100644 dom/base/FuzzingFunctions.cpp create mode 100644 dom/base/FuzzingFunctions.h create mode 100644 dom/base/GeneratedImageContent.cpp create mode 100644 dom/base/GeneratedImageContent.h create mode 100644 dom/base/GlobalTeardownObserver.cpp create mode 100644 dom/base/GlobalTeardownObserver.h create mode 100644 dom/base/HTMLSplitOnSpacesTokenizer.h create mode 100644 dom/base/Highlight.cpp create mode 100644 dom/base/Highlight.h create mode 100644 dom/base/HighlightRegistry.cpp create mode 100644 dom/base/HighlightRegistry.h create mode 100644 dom/base/IDTracker.cpp create mode 100644 dom/base/IDTracker.h create mode 100644 dom/base/IdentifierMapEntry.h create mode 100644 dom/base/IdleDeadline.cpp create mode 100644 dom/base/IdleDeadline.h create mode 100644 dom/base/IdleRequest.cpp create mode 100644 dom/base/IdleRequest.h create mode 100644 dom/base/IframeSandboxKeywordList.h create mode 100644 dom/base/ImageEncoder.cpp create mode 100644 dom/base/ImageEncoder.h create mode 100644 dom/base/ImageTracker.cpp create mode 100644 dom/base/ImageTracker.h create mode 100644 dom/base/InProcessBrowserChildMessageManager.cpp create mode 100644 dom/base/InProcessBrowserChildMessageManager.h create mode 100644 dom/base/IndexedDBHelper.sys.mjs create mode 100644 dom/base/IntlUtils.cpp create mode 100644 dom/base/IntlUtils.h create mode 100644 dom/base/JSExecutionContext.cpp create mode 100644 dom/base/JSExecutionContext.h create mode 100644 dom/base/Link.cpp create mode 100644 dom/base/Link.h create mode 100644 dom/base/LinkStyle.cpp create mode 100644 dom/base/LinkStyle.h create mode 100644 dom/base/Location.cpp create mode 100644 dom/base/Location.h create mode 100644 dom/base/LocationBase.cpp create mode 100644 dom/base/LocationBase.h create mode 100644 dom/base/LocationHelper.sys.mjs create mode 100644 dom/base/MaybeCrossOriginObject.cpp create mode 100644 dom/base/MaybeCrossOriginObject.h create mode 100644 dom/base/MessageBroadcaster.cpp create mode 100644 dom/base/MessageBroadcaster.h create mode 100644 dom/base/MessageListenerManager.cpp create mode 100644 dom/base/MessageListenerManager.h create mode 100644 dom/base/MessageManagerCallback.h create mode 100644 dom/base/MessageManagerGlobal.cpp create mode 100644 dom/base/MessageManagerGlobal.h create mode 100644 dom/base/MessageSender.cpp create mode 100644 dom/base/MessageSender.h create mode 100644 dom/base/MimeType.cpp create mode 100644 dom/base/MimeType.h create mode 100644 dom/base/MozQueryInterface.cpp create mode 100644 dom/base/MozQueryInterface.h create mode 100644 dom/base/MutationObservers.cpp create mode 100644 dom/base/MutationObservers.h create mode 100644 dom/base/NameSpaceConstants.h create mode 100644 dom/base/Navigator.cpp create mode 100644 dom/base/Navigator.h create mode 100644 dom/base/NodeInfo.cpp create mode 100644 dom/base/NodeInfo.h create mode 100644 dom/base/NodeInfoInlines.h create mode 100644 dom/base/NodeIterator.cpp create mode 100644 dom/base/NodeIterator.h create mode 100644 dom/base/NodeUbiReporting.cpp create mode 100644 dom/base/NodeUbiReporting.h create mode 100644 dom/base/ParentProcessMessageManager.cpp create mode 100644 dom/base/ParentProcessMessageManager.h create mode 100644 dom/base/PlacesBookmark.h create mode 100644 dom/base/PlacesBookmarkAddition.h create mode 100644 dom/base/PlacesBookmarkChanged.h create mode 100644 dom/base/PlacesBookmarkGuid.h create mode 100644 dom/base/PlacesBookmarkKeyword.h create mode 100644 dom/base/PlacesBookmarkMoved.h create mode 100644 dom/base/PlacesBookmarkRemoved.h create mode 100644 dom/base/PlacesBookmarkTags.h create mode 100644 dom/base/PlacesBookmarkTime.h create mode 100644 dom/base/PlacesBookmarkTitle.h create mode 100644 dom/base/PlacesBookmarkUrl.h create mode 100644 dom/base/PlacesEvent.cpp create mode 100644 dom/base/PlacesEvent.h create mode 100644 dom/base/PlacesFavicon.h create mode 100644 dom/base/PlacesHistoryCleared.h create mode 100644 dom/base/PlacesObservers.cpp create mode 100644 dom/base/PlacesObservers.h create mode 100644 dom/base/PlacesPurgeCaches.h create mode 100644 dom/base/PlacesRanking.h create mode 100644 dom/base/PlacesVisit.h create mode 100644 dom/base/PlacesVisitRemoved.h create mode 100644 dom/base/PlacesVisitTitle.h create mode 100644 dom/base/PlacesWeakCallbackWrapper.cpp create mode 100644 dom/base/PlacesWeakCallbackWrapper.h create mode 100644 dom/base/PointerLockManager.cpp create mode 100644 dom/base/PointerLockManager.h create mode 100644 dom/base/PopoverData.cpp create mode 100644 dom/base/PopoverData.h create mode 100644 dom/base/PopupBlocker.cpp create mode 100644 dom/base/PopupBlocker.h create mode 100644 dom/base/Pose.cpp create mode 100644 dom/base/Pose.h create mode 100644 dom/base/PostMessageEvent.cpp create mode 100644 dom/base/PostMessageEvent.h create mode 100644 dom/base/ProcessMessageManager.cpp create mode 100644 dom/base/ProcessMessageManager.h create mode 100644 dom/base/ProcessSelector.sys.mjs create mode 100644 dom/base/RadioGroupContainer.cpp create mode 100644 dom/base/RadioGroupContainer.h create mode 100644 dom/base/RangeBoundary.h create mode 100644 dom/base/RangeUtils.cpp create mode 100644 dom/base/RangeUtils.h create mode 100644 dom/base/RemoteOuterWindowProxy.cpp create mode 100644 dom/base/ResizeObserver.cpp create mode 100644 dom/base/ResizeObserver.h create mode 100644 dom/base/ResponsiveImageSelector.cpp create mode 100644 dom/base/ResponsiveImageSelector.h create mode 100644 dom/base/RustTypes.h create mode 100644 dom/base/SameProcessMessageQueue.cpp create mode 100644 dom/base/SameProcessMessageQueue.h create mode 100644 dom/base/ScreenLuminance.cpp create mode 100644 dom/base/ScreenLuminance.h create mode 100644 dom/base/ScreenOrientation.cpp create mode 100644 dom/base/ScreenOrientation.h create mode 100644 dom/base/ScriptableContentIterator.cpp create mode 100644 dom/base/ScriptableContentIterator.h create mode 100644 dom/base/ScrollingMetrics.cpp create mode 100644 dom/base/ScrollingMetrics.h create mode 100644 dom/base/Selection.cpp create mode 100644 dom/base/Selection.h create mode 100644 dom/base/SelectionChangeEventDispatcher.cpp create mode 100644 dom/base/SelectionChangeEventDispatcher.h create mode 100644 dom/base/SerializedStackHolder.cpp create mode 100644 dom/base/SerializedStackHolder.h create mode 100644 dom/base/ShadowIncludingTreeIterator.h create mode 100644 dom/base/ShadowRoot.cpp create mode 100644 dom/base/ShadowRoot.h create mode 100644 dom/base/SlowScriptDebug.sys.mjs create mode 100644 dom/base/StaticRange.cpp create mode 100644 dom/base/StaticRange.h create mode 100644 dom/base/StorageAccessPermissionRequest.cpp create mode 100644 dom/base/StorageAccessPermissionRequest.h create mode 100644 dom/base/StructuredCloneBlob.cpp create mode 100644 dom/base/StructuredCloneBlob.h create mode 100644 dom/base/StructuredCloneHolder.cpp create mode 100644 dom/base/StructuredCloneHolder.h create mode 100644 dom/base/StructuredCloneTags.h create mode 100644 dom/base/StructuredCloneTester.cpp create mode 100644 dom/base/StructuredCloneTester.h create mode 100644 dom/base/StyleSheetList.cpp create mode 100644 dom/base/StyleSheetList.h create mode 100644 dom/base/StyledRange.cpp create mode 100644 dom/base/StyledRange.h create mode 100644 dom/base/SubtleCrypto.cpp create mode 100644 dom/base/SubtleCrypto.h create mode 100644 dom/base/SyncMessageSender.h create mode 100644 dom/base/TestUtils.cpp create mode 100644 dom/base/TestUtils.h create mode 100644 dom/base/Text.cpp create mode 100644 dom/base/Text.h create mode 100644 dom/base/TextInputProcessor.cpp create mode 100644 dom/base/TextInputProcessor.h create mode 100644 dom/base/ThirdPartyUtil.cpp create mode 100644 dom/base/ThirdPartyUtil.h create mode 100644 dom/base/Timeout.cpp create mode 100644 dom/base/Timeout.h create mode 100644 dom/base/TimeoutBudgetManager.cpp create mode 100644 dom/base/TimeoutBudgetManager.h create mode 100644 dom/base/TimeoutExecutor.cpp create mode 100644 dom/base/TimeoutExecutor.h create mode 100644 dom/base/TimeoutHandler.cpp create mode 100644 dom/base/TimeoutHandler.h create mode 100644 dom/base/TimeoutManager.cpp create mode 100644 dom/base/TimeoutManager.h create mode 100644 dom/base/TreeIterator.h create mode 100644 dom/base/TreeOrderedArray.h create mode 100644 dom/base/TreeOrderedArrayInlines.h create mode 100644 dom/base/TreeWalker.cpp create mode 100644 dom/base/TreeWalker.h create mode 100644 dom/base/UIDirectionManager.cpp create mode 100644 dom/base/UIDirectionManager.h create mode 100644 dom/base/UseCounter.h create mode 100644 dom/base/UseCounterMetrics.h create mode 100644 dom/base/UseCounters.conf create mode 100644 dom/base/UseCountersWorker.conf create mode 100644 dom/base/UserActivation.cpp create mode 100644 dom/base/UserActivation.h create mode 100644 dom/base/ViewportMetaData.cpp create mode 100644 dom/base/ViewportMetaData.h create mode 100644 dom/base/VisualViewport.cpp create mode 100644 dom/base/VisualViewport.h create mode 100644 dom/base/WindowDestroyedEvent.cpp create mode 100644 dom/base/WindowDestroyedEvent.h create mode 100644 dom/base/WindowFeatures.cpp create mode 100644 dom/base/WindowFeatures.h create mode 100644 dom/base/WindowNamedPropertiesHandler.cpp create mode 100644 dom/base/WindowNamedPropertiesHandler.h create mode 100644 dom/base/WindowProxyHolder.h create mode 100644 dom/base/XPathGenerator.cpp create mode 100644 dom/base/XPathGenerator.h create mode 100644 dom/base/ZLibHelper.h create mode 100644 dom/base/components.conf create mode 100644 dom/base/crashtests/1024428-1.html create mode 100644 dom/base/crashtests/1027461-1.html create mode 100644 dom/base/crashtests/1027461-inner.xhtml create mode 100644 dom/base/crashtests/1029710.html create mode 100644 dom/base/crashtests/1154598.xhtml create mode 100644 dom/base/crashtests/1157995.html create mode 100644 dom/base/crashtests/1158412.html create mode 100644 dom/base/crashtests/116848-1.html create mode 100644 dom/base/crashtests/1181619.html create mode 100644 dom/base/crashtests/1228882.html create mode 100644 dom/base/crashtests/1230422.html create mode 100644 dom/base/crashtests/1251361.html create mode 100644 dom/base/crashtests/1281715.html create mode 100644 dom/base/crashtests/1291535-iframe.html create mode 100644 dom/base/crashtests/1291535.html create mode 100644 dom/base/crashtests/1304437.html create mode 100644 dom/base/crashtests/1324209.html create mode 100644 dom/base/crashtests/1324500.html create mode 100644 dom/base/crashtests/1326194-1.html create mode 100644 dom/base/crashtests/1326194-2.html create mode 100644 dom/base/crashtests/1332939.html create mode 100644 dom/base/crashtests/1341693.html create mode 100644 dom/base/crashtests/1352453.html create mode 100644 dom/base/crashtests/1353529-inner.html create mode 100644 dom/base/crashtests/1353529.xhtml create mode 100644 dom/base/crashtests/1368327-iframe.html create mode 100644 dom/base/crashtests/1368327.html create mode 100644 dom/base/crashtests/1369363.xhtml create mode 100644 dom/base/crashtests/1370072.html create mode 100644 dom/base/crashtests/1370737.html create mode 100644 dom/base/crashtests/1370968-inner.xhtml create mode 100644 dom/base/crashtests/1370968.html create mode 100644 dom/base/crashtests/1373750.html create mode 100644 dom/base/crashtests/1377826.html create mode 100644 dom/base/crashtests/1383478.html create mode 100644 dom/base/crashtests/1383780.html create mode 100644 dom/base/crashtests/1385272-1.html create mode 100644 dom/base/crashtests/1393806.html create mode 100644 dom/base/crashtests/1396466.html create mode 100644 dom/base/crashtests/1397795.html create mode 100644 dom/base/crashtests/1400701.html create mode 100644 dom/base/crashtests/1403377.html create mode 100644 dom/base/crashtests/1405771.html create mode 100644 dom/base/crashtests/1406109-1.html create mode 100644 dom/base/crashtests/1411473.html create mode 100644 dom/base/crashtests/1413815.html create mode 100644 dom/base/crashtests/1419799.html create mode 100644 dom/base/crashtests/1419902.html create mode 100644 dom/base/crashtests/1422883.html create mode 100644 dom/base/crashtests/1428053.html create mode 100644 dom/base/crashtests/1441029.html create mode 100644 dom/base/crashtests/1445670.html create mode 100644 dom/base/crashtests/1449601.html create mode 100644 dom/base/crashtests/1458016.html create mode 100644 dom/base/crashtests/1459688.html create mode 100644 dom/base/crashtests/1460794.html create mode 100644 dom/base/crashtests/1462548.html create mode 100644 dom/base/crashtests/149320-1.html create mode 100644 dom/base/crashtests/1505811.html create mode 100644 dom/base/crashtests/1505875.html create mode 100644 dom/base/crashtests/1508845.html create mode 100644 dom/base/crashtests/1516289.html create mode 100644 dom/base/crashtests/1516560.html create mode 100644 dom/base/crashtests/1517025.html create mode 100644 dom/base/crashtests/1528675.html create mode 100644 dom/base/crashtests/1529203-1.html create mode 100644 dom/base/crashtests/1529203-2.html create mode 100644 dom/base/crashtests/1529203-3.html create mode 100644 dom/base/crashtests/1555786.html create mode 100644 dom/base/crashtests/1566310.html create mode 100644 dom/base/crashtests/1577191.html create mode 100644 dom/base/crashtests/1588259.html create mode 100644 dom/base/crashtests/1611853.html create mode 100644 dom/base/crashtests/1619322.html create mode 100644 dom/base/crashtests/1623918.html create mode 100644 dom/base/crashtests/1656925.html create mode 100644 dom/base/crashtests/1665792.html create mode 100644 dom/base/crashtests/1681729-inner1.html create mode 100644 dom/base/crashtests/1681729-inner2.html create mode 100644 dom/base/crashtests/1681729.html create mode 100644 dom/base/crashtests/1693049.html create mode 100644 dom/base/crashtests/1697256.html create mode 100644 dom/base/crashtests/1697525.html create mode 100644 dom/base/crashtests/1700237.html create mode 100644 dom/base/crashtests/1712198.html create mode 100644 dom/base/crashtests/1728670-1-child.html create mode 100644 dom/base/crashtests/1728670-1.html create mode 100644 dom/base/crashtests/1757923.html create mode 100644 dom/base/crashtests/1766472.html create mode 100644 dom/base/crashtests/1780790.html create mode 100644 dom/base/crashtests/1811939.html create mode 100644 dom/base/crashtests/1822717-module.js create mode 100644 dom/base/crashtests/1822717.html create mode 100644 dom/base/crashtests/1835886.html create mode 100644 dom/base/crashtests/1835886.js create mode 100644 dom/base/crashtests/1836824.html create mode 100644 dom/base/crashtests/1838484.html create mode 100644 dom/base/crashtests/1840191.html create mode 100644 dom/base/crashtests/205225-1.html create mode 100644 dom/base/crashtests/231475-1.html create mode 100644 dom/base/crashtests/244933-1.html create mode 100644 dom/base/crashtests/275912-1.html create mode 100644 dom/base/crashtests/293388-1.html create mode 100644 dom/base/crashtests/325730-1.html create mode 100644 dom/base/crashtests/326618-1.html create mode 100644 dom/base/crashtests/326646-1.html create mode 100644 dom/base/crashtests/326865-1.html create mode 100644 dom/base/crashtests/327571-1.html create mode 100644 dom/base/crashtests/327694.html create mode 100644 dom/base/crashtests/327695-1.html create mode 100644 dom/base/crashtests/329481-1.xhtml create mode 100644 dom/base/crashtests/336381-1.xhtml create mode 100644 dom/base/crashtests/336715-1.xhtml create mode 100644 dom/base/crashtests/338391-1.xhtml create mode 100644 dom/base/crashtests/338674-1.xhtml create mode 100644 dom/base/crashtests/340733-1.html create mode 100644 dom/base/crashtests/343730-1.xhtml create mode 100644 dom/base/crashtests/343850-1.xhtml create mode 100644 dom/base/crashtests/343889-1.html create mode 100644 dom/base/crashtests/344434-1.xhtml create mode 100644 dom/base/crashtests/344882-1.html create mode 100644 dom/base/crashtests/345837-1.xhtml create mode 100644 dom/base/crashtests/346381-1.html create mode 100644 dom/base/crashtests/349355-1.html create mode 100644 dom/base/crashtests/359432-1.xhtml create mode 100644 dom/base/crashtests/360599-1.html create mode 100644 dom/base/crashtests/366200-1.xhtml create mode 100644 dom/base/crashtests/369219-1.xhtml create mode 100644 dom/base/crashtests/369413-1.html create mode 100644 dom/base/crashtests/371124-1-inner.html create mode 100644 dom/base/crashtests/371124-1.html create mode 100644 dom/base/crashtests/371124-2-inner.html create mode 100644 dom/base/crashtests/371124-2.html create mode 100644 dom/base/crashtests/371466-1.xhtml create mode 100644 dom/base/crashtests/372554-1.html create mode 100644 dom/base/crashtests/375399-1-inner.xhtml create mode 100644 dom/base/crashtests/375399-1.html create mode 100644 dom/base/crashtests/377360-1.xhtml create mode 100644 dom/base/crashtests/377960-1.html create mode 100644 dom/base/crashtests/377960-2.html create mode 100644 dom/base/crashtests/384663-1-inner.xhtml create mode 100644 dom/base/crashtests/384663-1.html create mode 100644 dom/base/crashtests/386000-1.html create mode 100644 dom/base/crashtests/386794-1.html create mode 100644 dom/base/crashtests/387460-1-inner.xhtml create mode 100644 dom/base/crashtests/387460-1.html create mode 100644 dom/base/crashtests/399712-1.html create mode 100644 dom/base/crashtests/400763-1.html create mode 100644 dom/base/crashtests/407818.html create mode 100644 dom/base/crashtests/410860-1.xml create mode 100644 dom/base/crashtests/411882-1.xhtml create mode 100644 dom/base/crashtests/416734-1.html create mode 100644 dom/base/crashtests/417852-1.html create mode 100644 dom/base/crashtests/418928-1.html create mode 100644 dom/base/crashtests/420620-1.html create mode 100644 dom/base/crashtests/424276-1.html create mode 100644 dom/base/crashtests/426987-1.html create mode 100644 dom/base/crashtests/43040-1.html create mode 100644 dom/base/crashtests/439206-1.html create mode 100644 dom/base/crashtests/443538-1.svg create mode 100644 dom/base/crashtests/448615-1.html create mode 100644 dom/base/crashtests/450383-1.html create mode 100644 dom/base/crashtests/450385-1.html create mode 100644 dom/base/crashtests/458637-1-inner.xhtml create mode 100644 dom/base/crashtests/458637-1.html create mode 100644 dom/base/crashtests/462947.html create mode 100644 dom/base/crashtests/467392.html create mode 100644 dom/base/crashtests/472593-1.html create mode 100644 dom/base/crashtests/474041-1.svg create mode 100644 dom/base/crashtests/476526.html create mode 100644 dom/base/crashtests/483818-1.html create mode 100644 dom/base/crashtests/490760-1.xhtml create mode 100644 dom/base/crashtests/493281-1.html create mode 100644 dom/base/crashtests/493281-2.html create mode 100644 dom/base/crashtests/494810-1.html create mode 100644 dom/base/crashtests/499006-1.html create mode 100644 dom/base/crashtests/499006-2.html create mode 100644 dom/base/crashtests/502617.html create mode 100644 dom/base/crashtests/504224.html create mode 100644 dom/base/crashtests/509536-1.html create mode 100644 dom/base/crashtests/522516-1.html create mode 100644 dom/base/crashtests/529670.html create mode 100644 dom/base/crashtests/535926-1.html create mode 100644 dom/base/crashtests/543645.html create mode 100644 dom/base/crashtests/551631-1.html create mode 100644 dom/base/crashtests/552651.html create mode 100644 dom/base/crashtests/552651.xml create mode 100644 dom/base/crashtests/554230-1.xhtml create mode 100644 dom/base/crashtests/558973.html create mode 100644 dom/base/crashtests/564079-1.html create mode 100644 dom/base/crashtests/564114.html create mode 100644 dom/base/crashtests/565125-1.html create mode 100644 dom/base/crashtests/575462.svg create mode 100644 dom/base/crashtests/582601.html create mode 100644 dom/base/crashtests/590395-1.html create mode 100644 dom/base/crashtests/593302-1.html create mode 100644 dom/base/crashtests/593302-2.html create mode 100644 dom/base/crashtests/595606-1.html create mode 100644 dom/base/crashtests/595606-2.html create mode 100644 dom/base/crashtests/601247.html create mode 100644 dom/base/crashtests/603531.html create mode 100644 dom/base/crashtests/604262-1.html create mode 100644 dom/base/crashtests/605672-1.svg create mode 100644 dom/base/crashtests/606729-1.html create mode 100644 dom/base/crashtests/607222.html create mode 100644 dom/base/crashtests/609560-1.xhtml create mode 100644 dom/base/crashtests/610571-1.html create mode 100644 dom/base/crashtests/612018-1.html create mode 100644 dom/base/crashtests/628599-1.html create mode 100644 dom/base/crashtests/637116.html create mode 100644 dom/base/crashtests/637214-1.svg create mode 100644 dom/base/crashtests/637214-2.svg create mode 100644 dom/base/crashtests/642022-1.html create mode 100644 dom/base/crashtests/646184.html create mode 100644 dom/base/crashtests/658845-1.svg create mode 100644 dom/base/crashtests/666869.html create mode 100644 dom/base/crashtests/667336-1.html create mode 100644 dom/base/crashtests/675516.xhtml create mode 100644 dom/base/crashtests/675621-1.html create mode 100644 dom/base/crashtests/677194.html create mode 100644 dom/base/crashtests/679459.html create mode 100644 dom/base/crashtests/679689-1.html create mode 100644 dom/base/crashtests/682463.html create mode 100644 dom/base/crashtests/693212.xhtml create mode 100644 dom/base/crashtests/693811-1.html create mode 100644 dom/base/crashtests/693811-2.html create mode 100644 dom/base/crashtests/693811-3.html create mode 100644 dom/base/crashtests/693894.html create mode 100644 dom/base/crashtests/695867.html create mode 100644 dom/base/crashtests/697643.html create mode 100644 dom/base/crashtests/698974-1.html create mode 100644 dom/base/crashtests/700090-1.html create mode 100644 dom/base/crashtests/700090-2.html create mode 100644 dom/base/crashtests/700512-worker.js create mode 100644 dom/base/crashtests/700512.html create mode 100644 dom/base/crashtests/706283-1.html create mode 100644 dom/base/crashtests/709384.html create mode 100644 dom/base/crashtests/709954.html create mode 100644 dom/base/crashtests/713417-1.html create mode 100644 dom/base/crashtests/713417-2.html create mode 100644 dom/base/crashtests/715056.html create mode 100644 dom/base/crashtests/729431-1.xhtml create mode 100644 dom/base/crashtests/741163-1.html create mode 100644 dom/base/crashtests/745495.html create mode 100644 dom/base/crashtests/752226-1.html create mode 100644 dom/base/crashtests/752226-2.html create mode 100644 dom/base/crashtests/766426.html create mode 100644 dom/base/crashtests/771639.html create mode 100644 dom/base/crashtests/786854.html create mode 100644 dom/base/crashtests/815043.html create mode 100644 dom/base/crashtests/815276.html create mode 100644 dom/base/crashtests/815477.html create mode 100644 dom/base/crashtests/815500.html create mode 100644 dom/base/crashtests/816253.html create mode 100644 dom/base/crashtests/819014.html create mode 100644 dom/base/crashtests/822723.html create mode 100644 dom/base/crashtests/824719.html create mode 100644 dom/base/crashtests/827190.html create mode 100644 dom/base/crashtests/828054.html create mode 100644 dom/base/crashtests/828903-iframe.html create mode 100644 dom/base/crashtests/828903.html create mode 100644 dom/base/crashtests/829428.html create mode 100644 dom/base/crashtests/830098.html create mode 100644 dom/base/crashtests/831287.html create mode 100644 dom/base/crashtests/832644.html create mode 100644 dom/base/crashtests/836890.html create mode 100644 dom/base/crashtests/838489-1.html create mode 100644 dom/base/crashtests/838489-2.html create mode 100644 dom/base/crashtests/841205.html create mode 100644 dom/base/crashtests/844404.html create mode 100644 dom/base/crashtests/845093-1.html create mode 100644 dom/base/crashtests/845093-2.html create mode 100644 dom/base/crashtests/847127.html create mode 100644 dom/base/crashtests/849601.html create mode 100644 dom/base/crashtests/849727.html create mode 100644 dom/base/crashtests/849732.html create mode 100644 dom/base/crashtests/851353-1.html create mode 100644 dom/base/crashtests/852381.html create mode 100644 dom/base/crashtests/863950.html create mode 100644 dom/base/crashtests/864448.html create mode 100644 dom/base/crashtests/886213.html create mode 100644 dom/base/crashtests/898906.html create mode 100644 dom/base/crashtests/90613-1.html create mode 100644 dom/base/crashtests/930250.html create mode 100644 dom/base/crashtests/942979.html create mode 100644 dom/base/crashtests/973401.html create mode 100644 dom/base/crashtests/978646.html create mode 100644 dom/base/crashtests/crashtests.list create mode 100644 dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown-worker.js create mode 100644 dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown.html create mode 100644 dom/base/crashtests/file_504224.html create mode 100644 dom/base/crashtests/module-with-syntax-error.js create mode 100644 dom/base/crashtests/structured_clone_container_throws.html create mode 100644 dom/base/crashtests/xhr-with-pagehide-1-helper.html create mode 100644 dom/base/crashtests/xhr-with-pagehide-1.html create mode 100644 dom/base/crashtests/xhr_empty_datauri.html create mode 100644 dom/base/crashtests/xhr_html_nullresponse.html create mode 100644 dom/base/domerr.msg create mode 100644 dom/base/fuzztest/FuzzStructuredClone.cpp create mode 100644 dom/base/fuzztest/moz.build create mode 100755 dom/base/gen-usecounters.py create mode 100644 dom/base/mach_commands.py create mode 100644 dom/base/moz.build create mode 100644 dom/base/mozAutoDocUpdate.h create mode 100644 dom/base/mozIDOMWindow.idl create mode 100644 dom/base/nsAttrName.h create mode 100644 dom/base/nsAttrValue.cpp create mode 100644 dom/base/nsAttrValue.h create mode 100644 dom/base/nsAttrValueInlines.h create mode 100644 dom/base/nsAttrValueOrString.cpp create mode 100644 dom/base/nsAttrValueOrString.h create mode 100644 dom/base/nsCCUncollectableMarker.cpp create mode 100644 dom/base/nsCCUncollectableMarker.h create mode 100644 dom/base/nsCaseTreatment.h create mode 100644 dom/base/nsChildContentList.h create mode 100644 dom/base/nsContentAreaDragDrop.cpp create mode 100644 dom/base/nsContentAreaDragDrop.h create mode 100644 dom/base/nsContentCID.h create mode 100644 dom/base/nsContentCreatorFunctions.h create mode 100644 dom/base/nsContentList.cpp create mode 100644 dom/base/nsContentList.h create mode 100644 dom/base/nsContentListDeclarations.h create mode 100644 dom/base/nsContentPermissionHelper.cpp create mode 100644 dom/base/nsContentPermissionHelper.h create mode 100644 dom/base/nsContentPolicy.cpp create mode 100644 dom/base/nsContentPolicy.h create mode 100644 dom/base/nsContentPolicyUtils.h create mode 100644 dom/base/nsContentSink.cpp create mode 100644 dom/base/nsContentSink.h create mode 100644 dom/base/nsContentTypeParser.cpp create mode 100644 dom/base/nsContentTypeParser.h create mode 100644 dom/base/nsContentUtils.cpp create mode 100644 dom/base/nsContentUtils.h create mode 100644 dom/base/nsCopySupport.cpp create mode 100644 dom/base/nsCopySupport.h create mode 100644 dom/base/nsDOMAttributeMap.cpp create mode 100644 dom/base/nsDOMAttributeMap.h create mode 100644 dom/base/nsDOMCID.h create mode 100644 dom/base/nsDOMCaretPosition.cpp create mode 100644 dom/base/nsDOMCaretPosition.h create mode 100644 dom/base/nsDOMDataChannel.cpp create mode 100644 dom/base/nsDOMDataChannel.h create mode 100644 dom/base/nsDOMDataChannelDeclarations.h create mode 100644 dom/base/nsDOMJSUtils.h create mode 100644 dom/base/nsDOMMutationObserver.cpp create mode 100644 dom/base/nsDOMMutationObserver.h create mode 100644 dom/base/nsDOMNavigationTiming.cpp create mode 100644 dom/base/nsDOMNavigationTiming.h create mode 100644 dom/base/nsDOMString.h create mode 100644 dom/base/nsDOMTokenList.cpp create mode 100644 dom/base/nsDOMTokenList.h create mode 100644 dom/base/nsDOMWindowUtils.cpp create mode 100644 dom/base/nsDOMWindowUtils.h create mode 100644 dom/base/nsDataDocumentContentPolicy.cpp create mode 100644 dom/base/nsDataDocumentContentPolicy.h create mode 100644 dom/base/nsDeprecatedOperationList.h create mode 100644 dom/base/nsDocElementCreatedNotificationRunner.h create mode 100644 dom/base/nsDocumentWarningList.h create mode 100644 dom/base/nsFocusManager.cpp create mode 100644 dom/base/nsFocusManager.h create mode 100644 dom/base/nsFrameLoader.cpp create mode 100644 dom/base/nsFrameLoader.h create mode 100644 dom/base/nsFrameLoaderOwner.cpp create mode 100644 dom/base/nsFrameLoaderOwner.h create mode 100644 dom/base/nsFrameMessageManager.cpp create mode 100644 dom/base/nsFrameMessageManager.h create mode 100644 dom/base/nsGlobalWindowCommands.cpp create mode 100644 dom/base/nsGlobalWindowCommands.h create mode 100644 dom/base/nsGlobalWindowInner.cpp create mode 100644 dom/base/nsGlobalWindowInner.h create mode 100644 dom/base/nsGlobalWindowOuter.cpp create mode 100644 dom/base/nsGlobalWindowOuter.h create mode 100644 dom/base/nsHistory.cpp create mode 100644 dom/base/nsHistory.h create mode 100644 dom/base/nsIAnimationObserver.h create mode 100644 dom/base/nsIContent.h create mode 100644 dom/base/nsIContentInlines.h create mode 100644 dom/base/nsIContentPolicy.idl create mode 100644 dom/base/nsIDOMRequestService.idl create mode 100644 dom/base/nsIDocumentObserver.h create mode 100644 dom/base/nsIDroppedLinkHandler.idl create mode 100644 dom/base/nsIEventSourceEventService.idl create mode 100644 dom/base/nsIGlobalObject.cpp create mode 100644 dom/base/nsIGlobalObject.h create mode 100644 dom/base/nsIImageLoadingContent.idl create mode 100644 dom/base/nsIMessageManager.idl create mode 100644 dom/base/nsIMutationObserver.h create mode 100644 dom/base/nsINode.cpp create mode 100644 dom/base/nsINode.h create mode 100644 dom/base/nsINodeList.h create mode 100644 dom/base/nsIObjectLoadingContent.idl create mode 100644 dom/base/nsIScriptChannel.idl create mode 100644 dom/base/nsIScriptContext.h create mode 100644 dom/base/nsIScriptGlobalObject.h create mode 100644 dom/base/nsIScriptObjectPrincipal.h create mode 100644 dom/base/nsIScriptableContentIterator.idl create mode 100644 dom/base/nsISelectionController.idl create mode 100644 dom/base/nsISelectionDisplay.idl create mode 100644 dom/base/nsISelectionListener.idl create mode 100644 dom/base/nsISizeOfEventTarget.h create mode 100644 dom/base/nsISlowScriptDebug.idl create mode 100644 dom/base/nsImageLoadingContent.cpp create mode 100644 dom/base/nsImageLoadingContent.h create mode 100644 dom/base/nsJSEnvironment.cpp create mode 100644 dom/base/nsJSEnvironment.h create mode 100644 dom/base/nsJSUtils.cpp create mode 100644 dom/base/nsJSUtils.h create mode 100644 dom/base/nsLineBreaker.cpp create mode 100644 dom/base/nsLineBreaker.h create mode 100644 dom/base/nsMimeTypeArray.cpp create mode 100644 dom/base/nsMimeTypeArray.h create mode 100644 dom/base/nsNameSpaceManager.cpp create mode 100644 dom/base/nsNameSpaceManager.h create mode 100644 dom/base/nsNoDataProtocolContentPolicy.cpp create mode 100644 dom/base/nsNoDataProtocolContentPolicy.h create mode 100644 dom/base/nsNodeInfoManager.cpp create mode 100644 dom/base/nsNodeInfoManager.h create mode 100644 dom/base/nsObjectLoadingContent.cpp create mode 100644 dom/base/nsObjectLoadingContent.h create mode 100644 dom/base/nsOpenURIInFrameParams.cpp create mode 100644 dom/base/nsOpenURIInFrameParams.h create mode 100644 dom/base/nsPIDOMWindow.h create mode 100644 dom/base/nsPIDOMWindowInlines.h create mode 100644 dom/base/nsPIWindowRoot.h create mode 100644 dom/base/nsPluginArray.cpp create mode 100644 dom/base/nsPluginArray.h create mode 100644 dom/base/nsPropertyTable.cpp create mode 100644 dom/base/nsPropertyTable.h create mode 100644 dom/base/nsQueryContentEventResult.cpp create mode 100644 dom/base/nsQueryContentEventResult.h create mode 100644 dom/base/nsRange.cpp create mode 100644 dom/base/nsRange.h create mode 100644 dom/base/nsSandboxFlags.h create mode 100644 dom/base/nsScreen.cpp create mode 100644 dom/base/nsScreen.h create mode 100644 dom/base/nsStructuredCloneContainer.cpp create mode 100644 dom/base/nsStructuredCloneContainer.h create mode 100644 dom/base/nsStubAnimationObserver.cpp create mode 100644 dom/base/nsStubAnimationObserver.h create mode 100644 dom/base/nsStubDocumentObserver.cpp create mode 100644 dom/base/nsStubDocumentObserver.h create mode 100644 dom/base/nsStubMutationObserver.cpp create mode 100644 dom/base/nsStubMutationObserver.h create mode 100644 dom/base/nsStyledElement.cpp create mode 100644 dom/base/nsStyledElement.h create mode 100644 dom/base/nsSyncLoadService.cpp create mode 100644 dom/base/nsSyncLoadService.h create mode 100644 dom/base/nsTextFragment.cpp create mode 100644 dom/base/nsTextFragment.h create mode 100644 dom/base/nsTextFragmentGeneric.h create mode 100644 dom/base/nsTextFragmentGenericFwd.h create mode 100644 dom/base/nsTextFragmentImpl.h create mode 100644 dom/base/nsTextFragmentSSE2.cpp create mode 100644 dom/base/nsTextFragmentVMX.cpp create mode 100644 dom/base/nsTextNode.cpp create mode 100644 dom/base/nsTextNode.h create mode 100644 dom/base/nsTraversal.cpp create mode 100644 dom/base/nsTraversal.h create mode 100644 dom/base/nsTreeSanitizer.cpp create mode 100644 dom/base/nsTreeSanitizer.h create mode 100644 dom/base/nsViewportInfo.cpp create mode 100644 dom/base/nsViewportInfo.h create mode 100644 dom/base/nsWindowMemoryReporter.cpp create mode 100644 dom/base/nsWindowMemoryReporter.h create mode 100644 dom/base/nsWindowRoot.cpp create mode 100644 dom/base/nsWindowRoot.h create mode 100644 dom/base/nsWindowSizes.h create mode 100644 dom/base/nsWrapperCache.cpp create mode 100644 dom/base/nsWrapperCache.h create mode 100644 dom/base/nsWrapperCacheInlines.h create mode 100644 dom/base/rust/Cargo.toml create mode 100644 dom/base/rust/cbindgen.toml create mode 100644 dom/base/rust/lib.rs create mode 100644 dom/base/test/345339_iframe.html create mode 100644 dom/base/test/Ahem.ttf create mode 100644 dom/base/test/FAIL.html create mode 100644 dom/base/test/PASS.html create mode 100644 dom/base/test/accesscontrol.resource create mode 100644 dom/base/test/accesscontrol.resource^headers^ create mode 100644 dom/base/test/audio.ogg create mode 100644 dom/base/test/badContentType.eventsource create mode 100644 dom/base/test/badContentType.eventsource^headers^ create mode 100644 dom/base/test/badHTTPResponseCode.eventsource create mode 100644 dom/base/test/badHTTPResponseCode.eventsource^headers^ create mode 100644 dom/base/test/badMessageEvent.eventsource create mode 100644 dom/base/test/badMessageEvent.eventsource^headers^ create mode 100644 dom/base/test/badMessageEvent2.eventsource create mode 100644 dom/base/test/badMessageEvent2.eventsource^headers^ create mode 100644 dom/base/test/browser.toml create mode 100644 dom/base/test/browser_aboutnewtab_process_selection.js create mode 100644 dom/base/test/browser_blocking_image.js create mode 100644 dom/base/test/browser_bug1011748.js create mode 100644 dom/base/test/browser_bug1058164.js create mode 100644 dom/base/test/browser_bug1303838.js create mode 100644 dom/base/test/browser_bug1554070.js create mode 100644 dom/base/test/browser_bug1691214.js create mode 100644 dom/base/test/browser_bug1703472.js create mode 100644 dom/base/test/browser_bug902350.js create mode 100644 dom/base/test/browser_chromeutils_getalldomprocesses.js create mode 100644 dom/base/test/browser_chromeutils_isdomobject.js create mode 100644 dom/base/test/browser_data_documents_aboutmemory.js create mode 100644 dom/base/test/browser_event_source_reconnect_after_disconnect.js create mode 100644 dom/base/test/browser_force_process_selector.js create mode 100644 dom/base/test/browser_form_validity_popup_submit.js create mode 100644 dom/base/test/browser_inputStream_structuredClone.js create mode 100644 dom/base/test/browser_messagemanager_loadprocessscript.js create mode 100644 dom/base/test/browser_messagemanager_targetframeloader.js create mode 100644 dom/base/test/browser_messagemanager_unload.js create mode 100644 dom/base/test/browser_multiple_popups.html create mode 100644 dom/base/test/browser_multiple_popups.js create mode 100644 dom/base/test/browser_outline_refocus.js create mode 100644 dom/base/test/browser_page_load_event_telemetry.js create mode 100644 dom/base/test/browser_pagehide_on_tab_close.js create mode 100644 dom/base/test/browser_promiseDocumentFlushed.js create mode 100644 dom/base/test/browser_refresh_content.js create mode 100644 dom/base/test/browser_state_notifications.js create mode 100644 dom/base/test/browser_timeout_throttling_with_audio_playback.js create mode 100644 dom/base/test/browser_use_counters.js create mode 100644 dom/base/test/browser_user_input_handling_delay.js create mode 100644 dom/base/test/browser_user_input_handling_delay_aboutblank.js create mode 100644 dom/base/test/browser_user_input_handling_delay_bfcache.js create mode 100644 dom/base/test/browser_user_input_handling_delay_invisible_iframe.js create mode 100644 dom/base/test/browser_user_input_handling_delay_reload_ticks.js create mode 100644 dom/base/test/browser_xml_toggle.js create mode 100644 dom/base/test/bug1576154.sjs create mode 100644 dom/base/test/bug1739957.sjs create mode 100644 dom/base/test/bug282547.sjs create mode 100644 dom/base/test/bug298064-subframe.html create mode 100644 dom/base/test/bug313646.txt create mode 100644 dom/base/test/bug382113_object.html create mode 100644 dom/base/test/bug403852_fileOpener.js create mode 100644 dom/base/test/bug419132.html create mode 100644 dom/base/test/bug426308-redirect.sjs create mode 100644 dom/base/test/bug435425.sjs create mode 100644 dom/base/test/bug435425_redirect.sjs create mode 100644 dom/base/test/bug444322.js create mode 100644 dom/base/test/bug444322.txt create mode 100644 dom/base/test/bug444546.sjs create mode 100644 dom/base/test/bug455629-helper.svg create mode 100644 dom/base/test/bug457746.sjs create mode 100644 dom/base/test/bug461735-post-redirect.js create mode 100644 dom/base/test/bug461735-redirect1.sjs create mode 100644 dom/base/test/bug461735-redirect2.sjs create mode 100644 dom/base/test/bug466080.sjs create mode 100644 dom/base/test/bug466409-empty.css create mode 100644 dom/base/test/bug466409-page.html create mode 100644 dom/base/test/bug475156.sjs create mode 100644 dom/base/test/bug482935.sjs create mode 100644 dom/base/test/bug540854.sjs create mode 100644 dom/base/test/bug578096LoadChromeScript.js create mode 100644 dom/base/test/bug638112-response.txt create mode 100644 dom/base/test/bug638112.sjs create mode 100644 dom/base/test/bug696301-script-1.js create mode 100644 dom/base/test/bug696301-script-1.js^headers^ create mode 100644 dom/base/test/bug696301-script-2.js create mode 100644 dom/base/test/bug704320.sjs create mode 100644 dom/base/test/bug704320_counter.sjs create mode 100644 dom/base/test/bug819051.sjs create mode 100644 dom/base/test/chrome.toml create mode 100644 dom/base/test/chrome/bug418986-1.js create mode 100644 dom/base/test/chrome/bug421622-referer.sjs create mode 100644 dom/base/test/chrome/bug884693.sjs create mode 100644 dom/base/test/chrome/chrome.toml create mode 100644 dom/base/test/chrome/clonedoc/chrome.manifest create mode 100644 dom/base/test/chrome/clonedoc/content/doc.xml create mode 100644 dom/base/test/chrome/custom_element_ep.js create mode 100644 dom/base/test/chrome/file_bug1139964.xhtml create mode 100644 dom/base/test/chrome/file_bug1209621.xhtml create mode 100644 dom/base/test/chrome/file_bug549682.xhtml create mode 100644 dom/base/test/chrome/file_bug616841.xhtml create mode 100644 dom/base/test/chrome/file_bug816340.xhtml create mode 100644 dom/base/test/chrome/file_bug990812-1.xhtml create mode 100644 dom/base/test/chrome/file_bug990812-2.xhtml create mode 100644 dom/base/test/chrome/file_bug990812-3.xhtml create mode 100644 dom/base/test/chrome/file_bug990812-4.xhtml create mode 100644 dom/base/test/chrome/file_bug990812-5.xhtml create mode 100644 dom/base/test/chrome/file_bug990812.xhtml create mode 100644 dom/base/test/chrome/file_document-element-inserted-inner.xhtml create mode 100644 dom/base/test/chrome/file_document-element-inserted.xhtml create mode 100644 dom/base/test/chrome/file_title.xhtml create mode 100644 dom/base/test/chrome/fileconstructor_file.png create mode 100644 dom/base/test/chrome/frame_custom_element_content.html create mode 100644 dom/base/test/chrome/nochrome_bug1346936.html create mode 100644 dom/base/test/chrome/nochrome_bug1346936.js create mode 100644 dom/base/test/chrome/nochrome_bug1346936.js^headers^ create mode 100644 dom/base/test/chrome/nochrome_bug765993.html create mode 100644 dom/base/test/chrome/nochrome_bug765993.js create mode 100644 dom/base/test/chrome/nochrome_bug765993.js^headers^ create mode 100644 dom/base/test/chrome/test_bug1063837.xhtml create mode 100644 dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xhtml create mode 100644 dom/base/test/chrome/test_bug1139964.xhtml create mode 100644 dom/base/test/chrome/test_bug120684.xhtml create mode 100644 dom/base/test/chrome/test_bug1209621.xhtml create mode 100644 dom/base/test/chrome/test_bug1339722.html create mode 100644 dom/base/test/chrome/test_bug1346936.html create mode 100644 dom/base/test/chrome/test_bug206691.xhtml create mode 100644 dom/base/test/chrome/test_bug289714.xhtml create mode 100644 dom/base/test/chrome/test_bug339494.xhtml create mode 100644 dom/base/test/chrome/test_bug357450.xhtml create mode 100644 dom/base/test/chrome/test_bug380418.html create mode 100644 dom/base/test/chrome/test_bug380418.html^headers^ create mode 100644 dom/base/test/chrome/test_bug383430.html create mode 100644 dom/base/test/chrome/test_bug418986-1.xhtml create mode 100644 dom/base/test/chrome/test_bug421622.xhtml create mode 100644 dom/base/test/chrome/test_bug429785.xhtml create mode 100644 dom/base/test/chrome/test_bug430050.xhtml create mode 100644 dom/base/test/chrome/test_bug467123.xhtml create mode 100644 dom/base/test/chrome/test_bug473284.xhtml create mode 100644 dom/base/test/chrome/test_bug549682.xhtml create mode 100644 dom/base/test/chrome/test_bug571390.xhtml create mode 100644 dom/base/test/chrome/test_bug616841.xhtml create mode 100644 dom/base/test/chrome/test_bug635835.xhtml create mode 100644 dom/base/test/chrome/test_bug682305.html create mode 100644 dom/base/test/chrome/test_bug683852.xhtml create mode 100644 dom/base/test/chrome/test_bug752226-3.xhtml create mode 100644 dom/base/test/chrome/test_bug752226-4.xhtml create mode 100644 dom/base/test/chrome/test_bug765993.html create mode 100644 dom/base/test/chrome/test_bug780199.xhtml create mode 100644 dom/base/test/chrome/test_bug780529.xhtml create mode 100644 dom/base/test/chrome/test_bug800386.xhtml create mode 100644 dom/base/test/chrome/test_bug816340.xhtml create mode 100644 dom/base/test/chrome/test_bug884693.xhtml create mode 100644 dom/base/test/chrome/test_bug914381.html create mode 100644 dom/base/test/chrome/test_bug990812.xhtml create mode 100644 dom/base/test/chrome/test_chromeOuterWindowID.xhtml create mode 100644 dom/base/test/chrome/test_custom_element_content.xhtml create mode 100644 dom/base/test/chrome/test_custom_element_ep.xhtml create mode 100644 dom/base/test/chrome/test_document-element-inserted.xhtml create mode 100644 dom/base/test/chrome/test_domparsing.xhtml create mode 100644 dom/base/test/chrome/test_fileconstructor.xhtml create mode 100644 dom/base/test/chrome/test_getElementsWithGrid.html create mode 100644 dom/base/test/chrome/test_input_value_set_preserve_undo.xhtml create mode 100644 dom/base/test/chrome/test_nsITextInputProcessor.xhtml create mode 100644 dom/base/test/chrome/test_nsITextInputProcessorCallback_at_changing_default_value_of_textarea.html create mode 100644 dom/base/test/chrome/test_permission_hasValidTransientUserActivation.xhtml create mode 100644 dom/base/test/chrome/test_range_getClientRectsAndTexts.html create mode 100644 dom/base/test/chrome/test_swapFrameLoaders.xhtml create mode 100644 dom/base/test/chrome/test_title.xhtml create mode 100644 dom/base/test/chrome/test_windowroot.xhtml create mode 100644 dom/base/test/chrome/title_window.xhtml create mode 100644 dom/base/test/chrome/window_chromeOuterWindowID.xhtml create mode 100644 dom/base/test/chrome/window_nsITextInputProcessor.xhtml create mode 100644 dom/base/test/chrome/window_swapFrameLoaders.xhtml create mode 100644 dom/base/test/common_postMessages.js create mode 100644 dom/base/test/copypaste.js create mode 100644 dom/base/test/delayedServerEvents.sjs create mode 100644 dom/base/test/dummy.html create mode 100644 dom/base/test/embed_bug455472.html create mode 100644 dom/base/test/empty.html create mode 100644 dom/base/test/eventsource.resource create mode 100644 dom/base/test/eventsource.resource^headers^ create mode 100644 dom/base/test/eventsource_message.sjs create mode 100644 dom/base/test/eventsource_reconnect.sjs create mode 100644 dom/base/test/eventsource_redirect.resource create mode 100644 dom/base/test/eventsource_redirect.resource^headers^ create mode 100644 dom/base/test/eventsource_redirect_to.resource create mode 100644 dom/base/test/eventsource_redirect_to.resource^headers^ create mode 100644 dom/base/test/eventsource_worker.js create mode 100644 dom/base/test/fake_plugin.tst create mode 100644 dom/base/test/file1_setting_opener.html create mode 100644 dom/base/test/file2_setting_opener.html create mode 100644 dom/base/test/file3_setting_opener.html create mode 100644 dom/base/test/file4_setting_opener.html create mode 100644 dom/base/test/file_audioLoop.html create mode 100644 dom/base/test/file_audioLoopInIframe.html create mode 100644 dom/base/test/file_blocking_image.html create mode 100644 dom/base/test/file_browser_refresh_content.html create mode 100644 dom/base/test/file_browser_refresh_expired_resource.sjs create mode 100644 dom/base/test/file_browser_refresh_iframe.sjs create mode 100644 dom/base/test/file_browser_refresh_image.sjs create mode 100644 dom/base/test/file_browser_refresh_non_cacheable.sjs create mode 100644 dom/base/test/file_bug1008126_worker.js create mode 100644 dom/base/test/file_bug1011748_OK.sjs create mode 100644 dom/base/test/file_bug1011748_redirect.sjs create mode 100644 dom/base/test/file_bug1091883_frame.html create mode 100644 dom/base/test/file_bug1091883_subframe.html create mode 100644 dom/base/test/file_bug1091883_target.html create mode 100644 dom/base/test/file_bug1100912.html create mode 100644 dom/base/test/file_bug1198095.js create mode 100644 dom/base/test/file_bug1250148.sjs create mode 100644 dom/base/test/file_bug1268962.sjs create mode 100644 dom/base/test/file_bug1274806.html create mode 100644 dom/base/test/file_bug1303838.html create mode 100644 dom/base/test/file_bug1303838_target.html create mode 100644 dom/base/test/file_bug1303838_target_bar.html create mode 100644 dom/base/test/file_bug1303838_target_baz.html create mode 100644 dom/base/test/file_bug1303838_target_foo.html create mode 100644 dom/base/test/file_bug1303838_target_ibar.html create mode 100644 dom/base/test/file_bug1303838_target_ibaz.html create mode 100644 dom/base/test/file_bug1303838_target_ifoo.html create mode 100644 dom/base/test/file_bug1303838_with_iframe.html create mode 100644 dom/base/test/file_bug1554070_1.html create mode 100644 dom/base/test/file_bug1554070_2.html create mode 100644 dom/base/test/file_bug1639328.html create mode 100644 dom/base/test/file_bug1691214.html create mode 100644 dom/base/test/file_bug1700871.html create mode 100644 dom/base/test/file_bug1703472.html create mode 100644 dom/base/test/file_bug28293.sjs create mode 100644 dom/base/test/file_bug326337.xml create mode 100644 dom/base/test/file_bug326337_inner.html create mode 100644 dom/base/test/file_bug326337_outer.html create mode 100644 dom/base/test/file_bug357450.js create mode 100644 dom/base/test/file_bug416317.xhtml create mode 100644 dom/base/test/file_bug426646-1.html create mode 100644 dom/base/test/file_bug426646-2.html create mode 100644 dom/base/test/file_bug428847-1.xhtml create mode 100644 dom/base/test/file_bug428847-2.xhtml create mode 100644 dom/base/test/file_bug498897.css create mode 100644 dom/base/test/file_bug498897.html create mode 100644 dom/base/test/file_bug498897.html^headers^ create mode 100644 dom/base/test/file_bug503473-frame.sjs create mode 100644 dom/base/test/file_bug503481.sjs create mode 100644 dom/base/test/file_bug503481b_inner.html create mode 100644 dom/base/test/file_bug518104.js create mode 100644 dom/base/test/file_bug541937.html create mode 100644 dom/base/test/file_bug541937.xhtml create mode 100644 dom/base/test/file_bug557892.html create mode 100644 dom/base/test/file_bug562137.txt create mode 100644 dom/base/test/file_bug590812-ref.xhtml create mode 100644 dom/base/test/file_bug590812.xml create mode 100644 dom/base/test/file_bug590870.html create mode 100644 dom/base/test/file_bug601803a.html create mode 100644 dom/base/test/file_bug601803b.html create mode 100644 dom/base/test/file_bug604660-1.xml create mode 100644 dom/base/test/file_bug604660-2.xsl create mode 100644 dom/base/test/file_bug604660-3.js create mode 100644 dom/base/test/file_bug604660-4.js create mode 100644 dom/base/test/file_bug604660-5.xml create mode 100644 dom/base/test/file_bug604660-6.xsl create mode 100644 dom/base/test/file_bug622088.sjs create mode 100644 dom/base/test/file_bug622088_inner.html create mode 100644 dom/base/test/file_bug675121.sjs create mode 100644 dom/base/test/file_bug687859-16.js create mode 100644 dom/base/test/file_bug687859-16.js^headers^ create mode 100644 dom/base/test/file_bug687859-bom.js create mode 100644 dom/base/test/file_bug687859-bom.js^headers^ create mode 100644 dom/base/test/file_bug687859-charset.js create mode 100644 dom/base/test/file_bug687859-http.js create mode 100644 dom/base/test/file_bug687859-http.js^headers^ create mode 100644 dom/base/test/file_bug687859-inherit.js create mode 100644 dom/base/test/file_bug692434.xml create mode 100644 dom/base/test/file_bug704320_preload_attr.html create mode 100644 dom/base/test/file_bug704320_preload_common.js create mode 100644 dom/base/test/file_bug704320_preload_reuse.html create mode 100644 dom/base/test/file_bug704320_redirect.html create mode 100644 dom/base/test/file_bug707142_baseline.json create mode 100644 dom/base/test/file_bug707142_bom.json create mode 100644 dom/base/test/file_bug707142_utf-16.json create mode 100644 dom/base/test/file_bug708620-2.html create mode 100644 dom/base/test/file_bug708620.html create mode 100644 dom/base/test/file_bug753278.html create mode 100644 dom/base/test/file_bug769117.html create mode 100644 dom/base/test/file_bug782342.txt create mode 100644 dom/base/test/file_bug787778.sjs create mode 100644 dom/base/test/file_bug869432.eventsource create mode 100644 dom/base/test/file_bug869432.eventsource^headers^ create mode 100644 dom/base/test/file_bug902350.html create mode 100644 dom/base/test/file_bug902350_frame.html create mode 100644 dom/base/test/file_bug907892.html create mode 100644 dom/base/test/file_bug945152.jar create mode 100644 dom/base/test/file_bug945152_worker.js create mode 100644 dom/base/test/file_change_policy_redirect.html create mode 100644 dom/base/test/file_current_inner_window.html create mode 100644 dom/base/test/file_delazification_strategy.html create mode 100644 dom/base/test/file_delazification_strategy.js create mode 100644 dom/base/test/file_domwindowutils_animation.html create mode 100644 dom/base/test/file_domwindowutils_dynamic_toolbar.html create mode 100644 dom/base/test/file_empty.html create mode 100644 dom/base/test/file_explicit_user_agent.sjs create mode 100644 dom/base/test/file_external_script.html create mode 100644 dom/base/test/file_external_script.xhtml create mode 100644 dom/base/test/file_focus_design_mode_inner.html create mode 100644 dom/base/test/file_focus_display_none_xorigin_iframe_inner.html create mode 100644 dom/base/test/file_focus_shadow_dom.html create mode 100644 dom/base/test/file_general_document.html create mode 100644 dom/base/test/file_history_document_open.html create mode 100644 dom/base/test/file_htmlserializer_1.html create mode 100644 dom/base/test/file_htmlserializer_1_bodyonly.html create mode 100644 dom/base/test/file_htmlserializer_1_format.html create mode 100644 dom/base/test/file_htmlserializer_1_linebreak.html create mode 100644 dom/base/test/file_htmlserializer_1_links.html create mode 100644 dom/base/test/file_htmlserializer_1_nested_body.html create mode 100644 dom/base/test/file_htmlserializer_1_no_body.html create mode 100644 dom/base/test/file_htmlserializer_1_noflag.html create mode 100644 dom/base/test/file_htmlserializer_1_noformatpre.html create mode 100644 dom/base/test/file_htmlserializer_1_raw.html create mode 100644 dom/base/test/file_htmlserializer_1_sibling_body.html create mode 100644 dom/base/test/file_htmlserializer_1_sibling_body_only_body.html create mode 100644 dom/base/test/file_htmlserializer_1_wrap.html create mode 100644 dom/base/test/file_htmlserializer_2.html create mode 100644 dom/base/test/file_htmlserializer_2_basic.html create mode 100644 dom/base/test/file_htmlserializer_ipv6.html create mode 100644 dom/base/test/file_htmlserializer_ipv6_out.html create mode 100644 dom/base/test/file_inline_script.html create mode 100644 dom/base/test/file_inline_script.xhtml create mode 100644 dom/base/test/file_js_cache.html create mode 100644 dom/base/test/file_js_cache.js create mode 100644 dom/base/test/file_js_cache_module.html create mode 100644 dom/base/test/file_js_cache_save_after_load.html create mode 100644 dom/base/test/file_js_cache_save_after_load.js create mode 100644 dom/base/test/file_js_cache_syntax_error.html create mode 100644 dom/base/test/file_js_cache_syntax_error.js create mode 100644 dom/base/test/file_js_cache_with_sri.html create mode 100644 dom/base/test/file_location_href_unknown_protocol.html create mode 100644 dom/base/test/file_lock_orientation_with_pending_fullscreen.html create mode 100644 dom/base/test/file_messagemanager_unload.html create mode 100644 dom/base/test/file_module_js_cache.html create mode 100644 dom/base/test/file_module_js_cache.mjs create mode 100644 dom/base/test/file_module_js_cache_no_module.html create mode 100644 dom/base/test/file_module_js_cache_with_sri.html create mode 100644 dom/base/test/file_mozfiledataurl_img.jpg create mode 100644 dom/base/test/file_navigator_resolve_identity_xrays.xhtml create mode 100644 dom/base/test/file_receiveMessage.html create mode 100644 dom/base/test/file_restrictedEventSource.sjs create mode 100644 dom/base/test/file_sandbox_and_document_uri.html create mode 100644 dom/base/test/file_script.js create mode 100644 dom/base/test/file_script_module_dynamic_and_element.html create mode 100644 dom/base/test/file_script_module_dynamic_and_element.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_element_imported_1.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_element_imported_2.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_element_imported_3.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_static.html create mode 100644 dom/base/test/file_script_module_dynamic_and_static.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_static_imported_1.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_static_imported_2.mjs create mode 100644 dom/base/test/file_script_module_dynamic_and_static_imported_3.mjs create mode 100644 dom/base/test/file_script_module_dynamic_import.html create mode 100644 dom/base/test/file_script_module_dynamic_import.mjs create mode 100644 dom/base/test/file_script_module_dynamic_import_imported.mjs create mode 100644 dom/base/test/file_script_module_element_and_dynamic.html create mode 100644 dom/base/test/file_script_module_element_and_dynamic.mjs create mode 100644 dom/base/test/file_script_module_element_and_dynamic_imported_1.mjs create mode 100644 dom/base/test/file_script_module_element_and_dynamic_imported_2.mjs create mode 100644 dom/base/test/file_script_module_element_and_dynamic_imported_3.mjs create mode 100644 dom/base/test/file_script_module_element_and_import.html create mode 100644 dom/base/test/file_script_module_element_and_import.mjs create mode 100644 dom/base/test/file_script_module_element_and_import_imported_1.mjs create mode 100644 dom/base/test/file_script_module_element_and_import_imported_2.mjs create mode 100644 dom/base/test/file_script_module_element_and_import_imported_3.mjs create mode 100644 dom/base/test/file_script_module_frames_dynamic.html create mode 100644 dom/base/test/file_script_module_frames_dynamic_load.html create mode 100644 dom/base/test/file_script_module_frames_dynamic_load.mjs create mode 100644 dom/base/test/file_script_module_frames_dynamic_save.html create mode 100644 dom/base/test/file_script_module_frames_dynamic_save.mjs create mode 100644 dom/base/test/file_script_module_frames_dynamic_shared.mjs create mode 100644 dom/base/test/file_script_module_frames_element.html create mode 100644 dom/base/test/file_script_module_frames_element_load.html create mode 100644 dom/base/test/file_script_module_frames_element_save.html create mode 100644 dom/base/test/file_script_module_frames_element_shared.mjs create mode 100644 dom/base/test/file_script_module_frames_import.html create mode 100644 dom/base/test/file_script_module_frames_import_load.html create mode 100644 dom/base/test/file_script_module_frames_import_load.mjs create mode 100644 dom/base/test/file_script_module_frames_import_save.html create mode 100644 dom/base/test/file_script_module_frames_import_save.mjs create mode 100644 dom/base/test/file_script_module_frames_import_shared.mjs create mode 100644 dom/base/test/file_script_module_frames_relay.js create mode 100644 dom/base/test/file_script_module_import.html create mode 100644 dom/base/test/file_script_module_import.mjs create mode 100644 dom/base/test/file_script_module_import_and_element.html create mode 100644 dom/base/test/file_script_module_import_and_element.mjs create mode 100644 dom/base/test/file_script_module_import_and_element_imported_1.mjs create mode 100644 dom/base/test/file_script_module_import_and_element_imported_2.mjs create mode 100644 dom/base/test/file_script_module_import_and_element_imported_3.mjs create mode 100644 dom/base/test/file_script_module_import_imported.mjs create mode 100644 dom/base/test/file_script_module_import_multi.html create mode 100644 dom/base/test/file_script_module_import_multi.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems.html create mode 100644 dom/base/test/file_script_module_import_multi_elems_1.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems_2.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems_imported_once_1.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems_imported_once_2.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems_imported_once_3.mjs create mode 100644 dom/base/test/file_script_module_import_multi_elems_imported_twice.mjs create mode 100644 dom/base/test/file_script_module_import_multi_imported_once.mjs create mode 100644 dom/base/test/file_script_module_import_multi_imported_twice.mjs create mode 100644 dom/base/test/file_script_module_single.html create mode 100644 dom/base/test/file_script_module_single.mjs create mode 100644 dom/base/test/file_script_module_sri_basic.html create mode 100644 dom/base/test/file_script_module_sri_basic.mjs create mode 100644 dom/base/test/file_script_module_sri_basic_prep.html create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem.html create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem.mjs create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_nopreload.html create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_nopreload.mjs create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_nopreload_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_nopreload_prep.html create mode 100644 dom/base/test/file_script_module_sri_dynamic_elem_prep.html create mode 100644 dom/base/test/file_script_module_sri_elem_dynamic.html create mode 100644 dom/base/test/file_script_module_sri_elem_dynamic.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_dynamic_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_dynamic_prep.html create mode 100644 dom/base/test/file_script_module_sri_elem_elem_1.html create mode 100644 dom/base/test/file_script_module_sri_elem_elem_1.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_elem_1_prep.html create mode 100644 dom/base/test/file_script_module_sri_elem_elem_2.html create mode 100644 dom/base/test/file_script_module_sri_elem_elem_2.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_elem_2_prep.html create mode 100644 dom/base/test/file_script_module_sri_elem_import.html create mode 100644 dom/base/test/file_script_module_sri_elem_import.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_import_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_elem_import_prep.html create mode 100644 dom/base/test/file_script_module_sri_fallback.html create mode 100644 dom/base/test/file_script_module_sri_fallback.mjs create mode 100644 dom/base/test/file_script_module_sri_fallback_failure.html create mode 100644 dom/base/test/file_script_module_sri_fallback_failure.mjs create mode 100644 dom/base/test/file_script_module_sri_fallback_failure_prep.html create mode 100644 dom/base/test/file_script_module_sri_fallback_prep.html create mode 100644 dom/base/test/file_script_module_sri_import_elem.html create mode 100644 dom/base/test/file_script_module_sri_import_elem.mjs create mode 100644 dom/base/test/file_script_module_sri_import_elem_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_import_elem_nopreload.html create mode 100644 dom/base/test/file_script_module_sri_import_elem_nopreload.mjs create mode 100644 dom/base/test/file_script_module_sri_import_elem_nopreload_imported.mjs create mode 100644 dom/base/test/file_script_module_sri_import_elem_nopreload_prep.html create mode 100644 dom/base/test/file_script_module_sri_import_elem_prep.html create mode 100644 dom/base/test/file_script_module_static_and_dynamic.html create mode 100644 dom/base/test/file_script_module_static_and_dynamic.mjs create mode 100644 dom/base/test/file_script_module_static_and_dynamic_imported_1.mjs create mode 100644 dom/base/test/file_script_module_static_and_dynamic_imported_2.mjs create mode 100644 dom/base/test/file_script_module_static_and_dynamic_imported_3.mjs create mode 100644 dom/base/test/file_serializer_noscript.html create mode 100644 dom/base/test/file_setname.html create mode 100644 dom/base/test/file_settimeout_inner.html create mode 100644 dom/base/test/file_suppressed_events_and_scrolling.html create mode 100644 dom/base/test/file_suppressed_events_inner.html create mode 100644 dom/base/test/file_suppressed_events_middle.html create mode 100644 dom/base/test/file_suppressed_events_top.html create mode 100644 dom/base/test/file_suppressed_events_top_modalstate.html create mode 100644 dom/base/test/file_suppressed_events_top_xhr.html create mode 100644 dom/base/test/file_timer_flood.html create mode 100644 dom/base/test/file_title.xhtml create mode 100644 dom/base/test/file_toScreenRect.html create mode 100644 dom/base/test/file_use_counter_bfcache.html create mode 100644 dom/base/test/file_use_counter_bfcache_helper.html create mode 100644 dom/base/test/file_use_counter_outer.html create mode 100644 dom/base/test/file_use_counter_outer_display_none.html create mode 100644 dom/base/test/file_use_counter_style.html create mode 100644 dom/base/test/file_use_counter_svg_currentScale.svg create mode 100644 dom/base/test/file_use_counter_svg_fill_pattern.svg create mode 100644 dom/base/test/file_use_counter_svg_fill_pattern_data.svg create mode 100644 dom/base/test/file_use_counter_svg_fill_pattern_definition.svg create mode 100644 dom/base/test/file_use_counter_svg_fill_pattern_internal.svg create mode 100644 dom/base/test/file_use_counter_svg_getElementById.svg create mode 100644 dom/base/test/file_viewport_metrics_on_landscape_content.html create mode 100644 dom/base/test/file_viewport_scroll_quirks.html create mode 100644 dom/base/test/file_viewport_scroll_xml.xml create mode 100644 dom/base/test/file_webaudio_startstop.html create mode 100644 dom/base/test/file_window_close.html create mode 100644 dom/base/test/file_window_close_2.html create mode 100644 dom/base/test/file_window_focus_by_close_and_open.html create mode 100644 dom/base/test/file_x-frame-options_main.html create mode 100644 dom/base/test/file_x-frame-options_page.sjs create mode 100644 dom/base/test/file_xhtmlserializer_1.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_bodyonly.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_format.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_linebreak.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_links.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_nested_body.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_no_body.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_noflag.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_noformatpre.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_raw.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_sibling_body.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_1_wrap.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_2.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_2_basic.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_2_enthtml.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_2_entw3c.xhtml create mode 100644 dom/base/test/file_xhtmlserializer_2_latin1.xhtml create mode 100644 dom/base/test/file_youtube_flash_embed.html create mode 100644 dom/base/test/fmm/browser.toml create mode 100644 dom/base/test/fmm/browser_frame_message_manager_cache.js create mode 100644 dom/base/test/forRemoval.resource create mode 100644 dom/base/test/forRemoval.resource^headers^ create mode 100644 dom/base/test/formReset.html create mode 100644 dom/base/test/fullscreen/MozDomFullscreen_chrome.xhtml create mode 100644 dom/base/test/fullscreen/browser.toml create mode 100644 dom/base/test/fullscreen/browser_fullscreen-api-keys.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-bug-1798219.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-contextmenu-esc.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-document-mutation-navigation.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-document-mutation-race.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-document-mutation.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-navigation-history-race.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-navigation-history.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-navigation-race.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-navigation.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-newtab.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-sizemode.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-tab-close-race.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-tab-close.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen-window-open-race.js create mode 100644 dom/base/test/fullscreen/browser_fullscreen_exit_on_external_protocol.js create mode 100644 dom/base/test/fullscreen/chrome.toml create mode 100644 dom/base/test/fullscreen/dummy_page.html create mode 100644 dom/base/test/fullscreen/file_MozDomFullscreen.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-api-keys.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-api-race.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-api.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-async.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-backdrop.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-bug-1798219-2.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-bug-1798219.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-denied-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-denied.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-esc-exit-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-esc-exit.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-event-order.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-featurePolicy-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-featurePolicy.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-focus-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-focus.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-hidden.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-iframe-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-iframe-middle.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-iframe-top.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-lenient-setters.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-multiple-inner.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-multiple.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-navigation.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-nested.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-newtab.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-prefixed.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-resize.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-rollback.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-scrollbar.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-selector.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-shadowdom.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-single.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-sub-iframe.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-svg-element.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-table.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-top-layer.html create mode 100644 dom/base/test/fullscreen/file_fullscreen-utils.js create mode 100644 dom/base/test/fullscreen/file_fullscreen-with-full-zoom.html create mode 100644 dom/base/test/fullscreen/file_fullscreen_meta_viewport.html create mode 100644 dom/base/test/fullscreen/fullscreen.xhtml create mode 100644 dom/base/test/fullscreen/fullscreen_helpers.js create mode 100644 dom/base/test/fullscreen/head.js create mode 100644 dom/base/test/fullscreen/mochitest.toml create mode 100644 dom/base/test/fullscreen/moz.build create mode 100644 dom/base/test/fullscreen/test_MozDomFullscreen_event.xhtml create mode 100644 dom/base/test/fullscreen/test_fullscreen-api-race.html create mode 100644 dom/base/test/fullscreen/test_fullscreen-api-rapid-cycle.html create mode 100644 dom/base/test/fullscreen/test_fullscreen-api.html create mode 100644 dom/base/test/fullscreen/test_fullscreen.xhtml create mode 100644 dom/base/test/fullscreen/test_fullscreen_meta_viewport.html create mode 100644 dom/base/test/fullscreen/test_fullscreen_modal.html create mode 100644 dom/base/test/green.png create mode 100644 dom/base/test/gtest/TestContentUtils.cpp create mode 100644 dom/base/test/gtest/TestMimeType.cpp create mode 100644 dom/base/test/gtest/TestParser.cpp create mode 100644 dom/base/test/gtest/TestPlainTextSerializer.cpp create mode 100644 dom/base/test/gtest/TestScheduler.cpp create mode 100644 dom/base/test/gtest/TestXMLSerializerNoBreakLink.cpp create mode 100644 dom/base/test/gtest/TestXPathGenerator.cpp create mode 100644 dom/base/test/gtest/moz.build create mode 100644 dom/base/test/head.js create mode 100644 dom/base/test/iframe1_bug1640766.html create mode 100644 dom/base/test/iframe1_bug426646.html create mode 100644 dom/base/test/iframe1_bug431701.html create mode 100644 dom/base/test/iframe2_bug1640766.html create mode 100644 dom/base/test/iframe2_bug426646.html create mode 100644 dom/base/test/iframe2_bug431701.html create mode 100644 dom/base/test/iframe3_bug431701.html create mode 100644 dom/base/test/iframe4_bug431701.xml create mode 100644 dom/base/test/iframe5_bug431701.xml create mode 100644 dom/base/test/iframe6_bug431701.xml create mode 100644 dom/base/test/iframe7_bug431701.xml create mode 100644 dom/base/test/iframe_bug962251.html create mode 100644 dom/base/test/iframe_bug976673.html create mode 100644 dom/base/test/iframe_main_bug1022229.html create mode 100644 dom/base/test/iframe_meta_refresh.sjs create mode 100644 dom/base/test/iframe_postMessage_solidus.html create mode 100644 dom/base/test/iframe_postMessages.html create mode 100644 dom/base/test/iframe_sandbox_bug1022229.html create mode 100644 dom/base/test/iframe_shared_compartment2a.html create mode 100644 dom/base/test/iframe_shared_compartment2b.html create mode 100644 dom/base/test/intersectionobserver_cross_domain_iframe.html create mode 100644 dom/base/test/intersectionobserver_iframe.html create mode 100644 dom/base/test/intersectionobserver_window.html create mode 100644 dom/base/test/invalid_accesscontrol.resource create mode 100644 dom/base/test/invalid_accesscontrol.resource^headers^ create mode 100644 dom/base/test/jsmodules/.eslintrc.js create mode 100644 dom/base/test/jsmodules/ambiguous_export.mjs create mode 100644 dom/base/test/jsmodules/chrome.toml create mode 100644 dom/base/test/jsmodules/exportA1.mjs create mode 100644 dom/base/test/jsmodules/exportA2.mjs create mode 100644 dom/base/test/jsmodules/export_ambiguous.mjs create mode 100644 dom/base/test/jsmodules/iframe_extractIntroType.html create mode 100644 dom/base/test/jsmodules/import_ambiguous.mjs create mode 100644 dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs create mode 100644 dom/base/test/jsmodules/import_no_export.mjs create mode 100644 dom/base/test/jsmodules/import_no_indirect_export.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bad/module_2.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bad/module_3.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bad/module_4.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bad/module_7.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1873417.mjs create mode 100644 dom/base/test/jsmodules/importmaps/chrome.toml create mode 100644 dom/base/test/jsmodules/importmaps/circular_dependency.mjs create mode 100644 dom/base/test/jsmodules/importmaps/external_importMap.js create mode 100644 dom/base/test/jsmodules/importmaps/good/module_0.mjs create mode 100644 dom/base/test/jsmodules/importmaps/good/module_1.mjs create mode 100644 dom/base/test/jsmodules/importmaps/good/module_2.mjs create mode 100644 dom/base/test/jsmodules/importmaps/good/module_3.mjs create mode 100644 dom/base/test/jsmodules/importmaps/good/module_4.mjs create mode 100644 dom/base/test/jsmodules/importmaps/good/module_7.mjs create mode 100644 dom/base/test/jsmodules/importmaps/insert_a_base_element.js create mode 100644 dom/base/test/jsmodules/importmaps/mochitest.toml create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^ create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^ create mode 100644 dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_simpleExport.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs create mode 100644 dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs create mode 100644 dom/base/test/jsmodules/importmaps/moz.build create mode 100644 dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs create mode 100644 dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs create mode 100644 dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs create mode 100644 dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs create mode 100644 dom/base/test/jsmodules/importmaps/test_bug_1865410.html create mode 100644 dom/base/test/jsmodules/importmaps/test_bug_1873417.html create mode 100644 dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_externalImportMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html create mode 100644 dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html create mode 100644 dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html create mode 100644 dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html create mode 100644 dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html create mode 100644 dom/base/test/jsmodules/importmaps/test_simpleImportMap.html create mode 100644 dom/base/test/jsmodules/importmaps/test_sortedImportMap.html create mode 100644 dom/base/test/jsmodules/module_badImport.mjs create mode 100644 dom/base/test/jsmodules/module_badSyntax.mjs create mode 100644 dom/base/test/jsmodules/module_cyclic1.mjs create mode 100644 dom/base/test/jsmodules/module_cyclic2.mjs create mode 100644 dom/base/test/jsmodules/module_cyclic3.mjs create mode 100644 dom/base/test/jsmodules/module_extractIntroType.mjs create mode 100644 dom/base/test/jsmodules/module_large1.mjs create mode 100644 dom/base/test/jsmodules/module_large2.mjs create mode 100644 dom/base/test/jsmodules/module_large3.mjs create mode 100644 dom/base/test/jsmodules/module_missingImport.mjs create mode 100644 dom/base/test/jsmodules/module_multiImports.mjs create mode 100644 dom/base/test/jsmodules/module_multiLargeImports.mjs create mode 100644 dom/base/test/jsmodules/module_setRan.mjs create mode 100644 dom/base/test/jsmodules/module_simple1.mjs create mode 100644 dom/base/test/jsmodules/module_simple2.mjs create mode 100644 dom/base/test/jsmodules/module_simple3.mjs create mode 100644 dom/base/test/jsmodules/module_simpleExport.mjs create mode 100644 dom/base/test/jsmodules/module_simpleImport.mjs create mode 100644 dom/base/test/jsmodules/module_testSyntax.mjs create mode 100644 dom/base/test/jsmodules/moz.build create mode 100644 dom/base/test/jsmodules/no_export.mjs create mode 100644 dom/base/test/jsmodules/no_indirect_export.mjs create mode 100644 dom/base/test/jsmodules/script_simple2.js create mode 100644 dom/base/test/jsmodules/test_asyncInlineModules.html create mode 100644 dom/base/test/jsmodules/test_cyclicImport.html create mode 100644 dom/base/test/jsmodules/test_dynamicImportErrorMessage.html create mode 100644 dom/base/test/jsmodules/test_importIntroType.html create mode 100644 dom/base/test/jsmodules/test_importNotFound.html create mode 100644 dom/base/test/jsmodules/test_importResolveFailed.html create mode 100644 dom/base/test/jsmodules/test_import_errorMessage.html create mode 100644 dom/base/test/jsmodules/test_import_meta_resolve.html create mode 100644 dom/base/test/jsmodules/test_importedModuleMemoization.html create mode 100644 dom/base/test/jsmodules/test_linkErrorInCommon1.html create mode 100644 dom/base/test/jsmodules/test_linkErrorInCommon2.html create mode 100644 dom/base/test/jsmodules/test_moduleNotFound.html create mode 100644 dom/base/test/jsmodules/test_moduleParsedAsModule.html create mode 100644 dom/base/test/jsmodules/test_moduleScriptsRun.html create mode 100644 dom/base/test/jsmodules/test_multiAsyncImports.html create mode 100644 dom/base/test/jsmodules/test_multiModuleImports.html create mode 100644 dom/base/test/jsmodules/test_multiModuleLargeImports.html create mode 100644 dom/base/test/jsmodules/test_multiTopLevelImports.html create mode 100644 dom/base/test/jsmodules/test_multiTopLevelLargeImports.html create mode 100644 dom/base/test/jsmodules/test_scriptInsertedModule.html create mode 100644 dom/base/test/jsmodules/test_scriptModuleOrder.html create mode 100644 dom/base/test/jsmodules/test_scriptNotParsedAsModule.html create mode 100644 dom/base/test/jsmodules/test_simpleImport.html create mode 100644 dom/base/test/jsmodules/test_syntaxError.html create mode 100644 dom/base/test/jsmodules/test_syntaxErrorAsync.html create mode 100644 dom/base/test/jsmodules/test_syntaxErrorInline.html create mode 100644 dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html create mode 100644 dom/base/test/jsmodules/test_topLevelIntroType.html create mode 100644 dom/base/test/jsmodules/test_toplevelModuleMemoization.html create mode 100644 dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html create mode 100644 dom/base/test/meta_viewport/mochitest.toml create mode 100644 dom/base/test/meta_viewport/moz.build create mode 100644 dom/base/test/meta_viewport/test_meta_viewport0.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport1.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport2.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport3.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport4.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport5.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport6.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport7.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport8.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_width.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_height_and_initial_scale_1.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_device_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_initial_scale_1.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_0_5.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_1.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width_and_fixed_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_change_content_among_multiple.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_change_name.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_change_name_among_multiple.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_device_width.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_0_5.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_2.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_empty_content_and_valid_content_tags.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_fit.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_fit_multiple.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_fixed_width_and_zero_display_width.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_initial_scale_0_5.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_initial_scale_2.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_initial_scale_with_trailing_characters.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_insert_before_existing_tag.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0_5.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_2.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_multiple_tags.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_negative_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_no_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_valid_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_no_content_and_valid_content_tags.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_no_width_and_negative_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_no_width_and_valid_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_remove_node.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_remove_node_from_multiple.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_removing_content_attribute.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_replace_content.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_tiny_display_size.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_negative_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_no_height.html create mode 100644 dom/base/test/meta_viewport/test_meta_viewport_width_with_trailing_characters.html create mode 100644 dom/base/test/meta_viewport/viewport_helpers.js create mode 100644 dom/base/test/mochitest.toml create mode 100644 dom/base/test/moz.build create mode 100644 dom/base/test/object_bug353334.html create mode 100644 dom/base/test/object_bug455472.html create mode 100644 dom/base/test/red.png create mode 100644 dom/base/test/referrerHelper.js create mode 100644 dom/base/test/referrer_change_server.sjs create mode 100644 dom/base/test/referrer_header.sjs create mode 100644 dom/base/test/referrer_helper.js create mode 100644 dom/base/test/referrer_testserver.sjs create mode 100644 dom/base/test/reftest/mixed-bmp-png.ico create mode 100644 dom/base/test/reftest/reftest.list create mode 100644 dom/base/test/reftest/test_bug1525662-ref.html create mode 100644 dom/base/test/reftest/test_bug1525662.txt create mode 100644 dom/base/test/reftest/test_bug920877-ref.html create mode 100644 dom/base/test/reftest/test_bug920877.html create mode 100644 dom/base/test/reftest/test_xmlPrettyPrint_csp-ref.xml create mode 100644 dom/base/test/reftest/test_xmlPrettyPrint_csp.xml create mode 100644 dom/base/test/reftest/test_xmlPrettyPrint_csp.xml^headers^ create mode 100644 dom/base/test/script-1_bug597345.sjs create mode 100644 dom/base/test/script-2_bug597345.js create mode 100644 dom/base/test/script_bug1238440.js create mode 100644 dom/base/test/script_bug602838.sjs create mode 100644 dom/base/test/script_postmessages_fileList.js create mode 100644 dom/base/test/send_gzip_content.sjs create mode 100644 dom/base/test/slow.sjs create mode 100644 dom/base/test/somedatas.resource create mode 100644 dom/base/test/somedatas.resource^headers^ create mode 100644 dom/base/test/test_EventSource_redirects.html create mode 100644 dom/base/test/test_Image_constructor.html create mode 100644 dom/base/test/test_NodeIterator_basics_filters.xhtml create mode 100644 dom/base/test/test_NodeIterator_mutations_1.xhtml create mode 100644 dom/base/test/test_NodeIterator_mutations_2.html create mode 100644 dom/base/test/test_NodeIterator_mutations_3.html create mode 100644 dom/base/test/test_anchor_area_referrer.html create mode 100644 dom/base/test/test_anchor_area_referrer_changing.html create mode 100644 dom/base/test/test_anchor_area_referrer_invalid.html create mode 100644 dom/base/test/test_anchor_area_referrer_rel.html create mode 100644 dom/base/test/test_anchor_target_blank_referrer.html create mode 100644 dom/base/test/test_anonymousContent_api.html create mode 100644 dom/base/test/test_anonymousContent_append_after_reflow.html create mode 100644 dom/base/test/test_anonymousContent_canvas.html create mode 100644 dom/base/test/test_anonymousContent_insert.html create mode 100644 dom/base/test/test_anonymousContent_manipulate_content.html create mode 100644 dom/base/test/test_anonymousContent_style_csp.html create mode 100644 dom/base/test/test_anonymousContent_style_csp.html^headers^ create mode 100644 dom/base/test/test_anonymousContent_xul_window.xhtml create mode 100644 dom/base/test/test_async_setTimeout_stack.html create mode 100644 dom/base/test/test_async_setTimeout_stack_across_globals.html create mode 100644 dom/base/test/test_base.xhtml create mode 100644 dom/base/test/test_blockParsing.html create mode 100644 dom/base/test/test_blocking_image.html create mode 100644 dom/base/test/test_bug1008126.html create mode 100644 dom/base/test/test_bug1016960.html create mode 100644 dom/base/test/test_bug1022229.html create mode 100644 dom/base/test/test_bug1025933.html create mode 100644 dom/base/test/test_bug1037687.html create mode 100644 dom/base/test/test_bug1037687_subframe.html create mode 100644 dom/base/test/test_bug1043106.html create mode 100644 dom/base/test/test_bug1057176.html create mode 100644 dom/base/test/test_bug1060938.html create mode 100644 dom/base/test/test_bug1064481.html create mode 100644 dom/base/test/test_bug1070015.html create mode 100644 dom/base/test/test_bug1075702.html create mode 100644 dom/base/test/test_bug1091883.html create mode 100644 dom/base/test/test_bug1100912.html create mode 100644 dom/base/test/test_bug1101364.html create mode 100644 dom/base/test/test_bug1118689.html create mode 100644 dom/base/test/test_bug1120222.html create mode 100644 dom/base/test/test_bug1126851.html create mode 100644 dom/base/test/test_bug116083.html create mode 100644 dom/base/test/test_bug1163743.html create mode 100644 dom/base/test/test_bug1165501.html create mode 100644 dom/base/test/test_bug1187157.html create mode 100644 dom/base/test/test_bug1198095.html create mode 100644 dom/base/test/test_bug1222633.html create mode 100644 dom/base/test/test_bug1222633_link_update.html create mode 100644 dom/base/test/test_bug1238440.html create mode 100644 dom/base/test/test_bug1250148.html create mode 100644 dom/base/test/test_bug1259588.html create mode 100644 dom/base/test/test_bug1268962.html create mode 100644 dom/base/test/test_bug1274806.html create mode 100644 dom/base/test/test_bug1295852.html create mode 100644 dom/base/test/test_bug1307730.html create mode 100644 dom/base/test/test_bug1308069.html create mode 100644 dom/base/test/test_bug1314032.html create mode 100644 dom/base/test/test_bug1318303.html create mode 100644 dom/base/test/test_bug1375050.html create mode 100644 dom/base/test/test_bug1381710.html create mode 100644 dom/base/test/test_bug1399605.html create mode 100644 dom/base/test/test_bug1404385.html create mode 100644 dom/base/test/test_bug1406102.html create mode 100644 dom/base/test/test_bug1421568.html create mode 100644 dom/base/test/test_bug1433073.html create mode 100644 dom/base/test/test_bug1472427.html create mode 100644 dom/base/test/test_bug1499169.html create mode 100644 dom/base/test/test_bug1576154.html create mode 100644 dom/base/test/test_bug1632975.html create mode 100644 dom/base/test/test_bug1639328.html create mode 100644 dom/base/test/test_bug1640766.html create mode 100644 dom/base/test/test_bug1648887.html create mode 100644 dom/base/test/test_bug166235.html create mode 100644 dom/base/test/test_bug1667316.html create mode 100644 dom/base/test/test_bug1730284.html create mode 100644 dom/base/test/test_bug1739957.html create mode 100644 dom/base/test/test_bug1784187.html create mode 100644 dom/base/test/test_bug1799354.html create mode 100644 dom/base/test/test_bug199959.html create mode 100644 dom/base/test/test_bug218236.html create mode 100644 dom/base/test/test_bug218277.html create mode 100644 dom/base/test/test_bug238409.html create mode 100644 dom/base/test/test_bug254337.html create mode 100644 dom/base/test/test_bug270145.xhtml create mode 100644 dom/base/test/test_bug276037-1.html create mode 100644 dom/base/test/test_bug276037-2.xhtml create mode 100644 dom/base/test/test_bug282547.html create mode 100644 dom/base/test/test_bug28293.html create mode 100644 dom/base/test/test_bug28293.xhtml create mode 100644 dom/base/test/test_bug298064.html create mode 100644 dom/base/test/test_bug300992.html create mode 100644 dom/base/test/test_bug311681.xml create mode 100644 dom/base/test/test_bug313646.html create mode 100644 dom/base/test/test_bug320799.html create mode 100644 dom/base/test/test_bug322317.html create mode 100644 dom/base/test/test_bug326337.html create mode 100644 dom/base/test/test_bug331959.html create mode 100644 dom/base/test/test_bug333064.html create mode 100644 dom/base/test/test_bug333198.html create mode 100644 dom/base/test/test_bug333673.html create mode 100644 dom/base/test/test_bug337631.html create mode 100644 dom/base/test/test_bug338541.xhtml create mode 100644 dom/base/test/test_bug338583.html create mode 100644 dom/base/test/test_bug338679.html create mode 100644 dom/base/test/test_bug339494.html create mode 100644 dom/base/test/test_bug339494.xhtml create mode 100644 dom/base/test/test_bug343596.html create mode 100644 dom/base/test/test_bug345339.html create mode 100644 dom/base/test/test_bug346485.html create mode 100644 dom/base/test/test_bug352728.html create mode 100644 dom/base/test/test_bug352728.xhtml create mode 100644 dom/base/test/test_bug353334.html create mode 100644 dom/base/test/test_bug355026.html create mode 100644 dom/base/test/test_bug357450.html create mode 100644 dom/base/test/test_bug357450.xhtml create mode 100644 dom/base/test/test_bug357450_svg.xhtml create mode 100644 dom/base/test/test_bug357509.html create mode 100644 dom/base/test/test_bug358660.html create mode 100644 dom/base/test/test_bug362391.xhtml create mode 100644 dom/base/test/test_bug364092.xhtml create mode 100644 dom/base/test/test_bug364413.xhtml create mode 100644 dom/base/test/test_bug366944.html create mode 100644 dom/base/test/test_bug366946.html create mode 100644 dom/base/test/test_bug367164.html create mode 100644 dom/base/test/test_bug368972.html create mode 100644 dom/base/test/test_bug371576-2.html create mode 100644 dom/base/test/test_bug371576-3.html create mode 100644 dom/base/test/test_bug371576-4.html create mode 100644 dom/base/test/test_bug371576-5.html create mode 100644 dom/base/test/test_bug372086.html create mode 100644 dom/base/test/test_bug372964-2.html create mode 100644 dom/base/test/test_bug372964.html create mode 100644 dom/base/test/test_bug373181.xhtml create mode 100644 dom/base/test/test_bug375314-2.html create mode 100644 dom/base/test/test_bug375314.html create mode 100644 dom/base/test/test_bug378969.html create mode 100644 dom/base/test/test_bug380418.html create mode 100644 dom/base/test/test_bug380418.html^headers^ create mode 100644 dom/base/test/test_bug382113.html create mode 100644 dom/base/test/test_bug382871.html create mode 100644 dom/base/test/test_bug384003.xhtml create mode 100644 dom/base/test/test_bug390219.html create mode 100644 dom/base/test/test_bug390735.html create mode 100644 dom/base/test/test_bug392318.html create mode 100644 dom/base/test/test_bug392511.html create mode 100644 dom/base/test/test_bug393968.html create mode 100644 dom/base/test/test_bug395915.html create mode 100644 dom/base/test/test_bug397234.html create mode 100644 dom/base/test/test_bug398243.html create mode 100644 dom/base/test/test_bug401662.html create mode 100644 dom/base/test/test_bug402150.html create mode 100644 dom/base/test/test_bug402150.html^headers^ create mode 100644 dom/base/test/test_bug403841.html create mode 100644 dom/base/test/test_bug403852.html create mode 100644 dom/base/test/test_bug403868.xml create mode 100644 dom/base/test/test_bug405182.html create mode 100644 dom/base/test/test_bug409380.html create mode 100644 dom/base/test/test_bug410229.html create mode 100644 dom/base/test/test_bug413974.html create mode 100644 dom/base/test/test_bug414190.html create mode 100644 dom/base/test/test_bug415860.html create mode 100644 dom/base/test/test_bug416317-1.html create mode 100644 dom/base/test/test_bug416317-2.html create mode 100644 dom/base/test/test_bug416383.html create mode 100644 dom/base/test/test_bug417255.html create mode 100644 dom/base/test/test_bug417384.html create mode 100644 dom/base/test/test_bug418214.html create mode 100644 dom/base/test/test_bug418986-1.html create mode 100644 dom/base/test/test_bug419132.html create mode 100644 dom/base/test/test_bug419527.xhtml create mode 100644 dom/base/test/test_bug420609.xhtml create mode 100644 dom/base/test/test_bug420700.html create mode 100644 dom/base/test/test_bug421602.html create mode 100644 dom/base/test/test_bug422403-1.html create mode 100644 dom/base/test/test_bug422403-2.xhtml create mode 100644 dom/base/test/test_bug422537.html create mode 100644 dom/base/test/test_bug424212.html create mode 100644 dom/base/test/test_bug424359-1.html create mode 100644 dom/base/test/test_bug424359-2.html create mode 100644 dom/base/test/test_bug426308.html create mode 100644 dom/base/test/test_bug426646.html create mode 100644 dom/base/test/test_bug428847.html create mode 100644 dom/base/test/test_bug431082.html create mode 100644 dom/base/test/test_bug431701.html create mode 100644 dom/base/test/test_bug431833.html create mode 100644 dom/base/test/test_bug433533.html create mode 100644 dom/base/test/test_bug433662.html create mode 100644 dom/base/test/test_bug435425.html create mode 100644 dom/base/test/test_bug444322.html create mode 100644 dom/base/test/test_bug444546.html create mode 100644 dom/base/test/test_bug444722.html create mode 100644 dom/base/test/test_bug448993.html create mode 100644 dom/base/test/test_bug450160.html create mode 100644 dom/base/test/test_bug451376.html create mode 100644 dom/base/test/test_bug453521.html create mode 100644 dom/base/test/test_bug453736.html create mode 100644 dom/base/test/test_bug454325.html create mode 100644 dom/base/test/test_bug454326.html create mode 100644 dom/base/test/test_bug455472.html create mode 100644 dom/base/test/test_bug455629.html create mode 100644 dom/base/test/test_bug456262.html create mode 100644 dom/base/test/test_bug457746.html create mode 100644 dom/base/test/test_bug459424.html create mode 100644 dom/base/test/test_bug461555.html create mode 100644 dom/base/test/test_bug461735.html create mode 100644 dom/base/test/test_bug465767.html create mode 100644 dom/base/test/test_bug466080.html create mode 100644 dom/base/test/test_bug466409.html create mode 100644 dom/base/test/test_bug466751.xhtml create mode 100644 dom/base/test/test_bug469020.html create mode 100644 dom/base/test/test_bug469304.html create mode 100644 dom/base/test/test_bug473162-1.html create mode 100644 dom/base/test/test_bug473162-2.html create mode 100644 dom/base/test/test_bug475156.html create mode 100644 dom/base/test/test_bug482935.html create mode 100644 dom/base/test/test_bug484396.html create mode 100644 dom/base/test/test_bug493881.html create mode 100644 dom/base/test/test_bug493881.js create mode 100644 dom/base/test/test_bug498240.html create mode 100644 dom/base/test/test_bug498433.html create mode 100644 dom/base/test/test_bug498897.html create mode 100644 dom/base/test/test_bug499656.html create mode 100644 dom/base/test/test_bug499656.xhtml create mode 100644 dom/base/test/test_bug500937.html create mode 100644 dom/base/test/test_bug503473.html create mode 100644 dom/base/test/test_bug503481.html create mode 100644 dom/base/test/test_bug503481b.html create mode 100644 dom/base/test/test_bug51034.html create mode 100644 dom/base/test/test_bug513194.html create mode 100644 dom/base/test/test_bug5141.html create mode 100644 dom/base/test/test_bug514487.html create mode 100644 dom/base/test/test_bug515401.html create mode 100644 dom/base/test/test_bug518104.html create mode 100644 dom/base/test/test_bug527896.html create mode 100644 dom/base/test/test_bug540854.html create mode 100644 dom/base/test/test_bug541937.html create mode 100644 dom/base/test/test_bug544642.html create mode 100644 dom/base/test/test_bug545644.html create mode 100644 dom/base/test/test_bug545644.xhtml create mode 100644 dom/base/test/test_bug548463.html create mode 100644 dom/base/test/test_bug553896.xhtml create mode 100644 dom/base/test/test_bug557892.html create mode 100644 dom/base/test/test_bug558726.html create mode 100644 dom/base/test/test_bug559526.html create mode 100644 dom/base/test/test_bug560780.html create mode 100644 dom/base/test/test_bug562137.html create mode 100644 dom/base/test/test_bug562169-1.html create mode 100644 dom/base/test/test_bug562169-2.html create mode 100644 dom/base/test/test_bug562652.html create mode 100644 dom/base/test/test_bug564047.html create mode 100644 dom/base/test/test_bug564863-2.xhtml create mode 100644 dom/base/test/test_bug564863.xhtml create mode 100644 dom/base/test/test_bug567350.html create mode 100644 dom/base/test/test_bug574596.html create mode 100644 dom/base/test/test_bug578096.html create mode 100644 dom/base/test/test_bug585978.html create mode 100644 dom/base/test/test_bug587931.html create mode 100644 dom/base/test/test_bug588990.html create mode 100644 dom/base/test/test_bug590812.html create mode 100644 dom/base/test/test_bug590870.html create mode 100644 dom/base/test/test_bug592366.html create mode 100644 dom/base/test/test_bug592829.html create mode 100644 dom/base/test/test_bug597345.html create mode 100644 dom/base/test/test_bug599295.html create mode 100644 dom/base/test/test_bug599588.html create mode 100644 dom/base/test/test_bug601803.html create mode 100644 dom/base/test/test_bug602838.html create mode 100644 dom/base/test/test_bug604592.html create mode 100644 dom/base/test/test_bug604660.html create mode 100644 dom/base/test/test_bug605982.html create mode 100644 dom/base/test/test_bug606729.html create mode 100644 dom/base/test/test_bug614058.html create mode 100644 dom/base/test/test_bug622088.html create mode 100644 dom/base/test/test_bug622117.html create mode 100644 dom/base/test/test_bug622246.html create mode 100644 dom/base/test/test_bug625722.html create mode 100644 dom/base/test/test_bug626262.html create mode 100644 dom/base/test/test_bug628938.html create mode 100644 dom/base/test/test_bug631615.html create mode 100644 dom/base/test/test_bug638112.html create mode 100644 dom/base/test/test_bug647518.html create mode 100644 dom/base/test/test_bug650001.html create mode 100644 dom/base/test/test_bug650776.html create mode 100644 dom/base/test/test_bug650784.html create mode 100644 dom/base/test/test_bug656283.html create mode 100644 dom/base/test/test_bug664916.html create mode 100644 dom/base/test/test_bug666604.html create mode 100644 dom/base/test/test_bug675121.html create mode 100644 dom/base/test/test_bug675166.html create mode 100644 dom/base/test/test_bug682463.html create mode 100644 dom/base/test/test_bug682554.html create mode 100644 dom/base/test/test_bug682592.html create mode 100644 dom/base/test/test_bug684671.html create mode 100644 dom/base/test/test_bug685798.html create mode 100644 dom/base/test/test_bug686449.xhtml create mode 100644 dom/base/test/test_bug687859.html create mode 100644 dom/base/test/test_bug690056.html create mode 100644 dom/base/test/test_bug692434.html create mode 100644 dom/base/test/test_bug693615.html create mode 100644 dom/base/test/test_bug693875.html create mode 100644 dom/base/test/test_bug694754.xhtml create mode 100644 dom/base/test/test_bug696301-1.html create mode 100644 dom/base/test/test_bug696301-2.html create mode 100644 dom/base/test/test_bug698381.html create mode 100644 dom/base/test/test_bug698384.html create mode 100644 dom/base/test/test_bug704063.html create mode 100644 dom/base/test/test_bug704320-1.html create mode 100644 dom/base/test/test_bug704320-2.html create mode 100644 dom/base/test/test_bug704320_policyset.html create mode 100644 dom/base/test/test_bug704320_policyset2.html create mode 100644 dom/base/test/test_bug704320_preload.html create mode 100644 dom/base/test/test_bug707142.html create mode 100644 dom/base/test/test_bug708620.html create mode 100644 dom/base/test/test_bug711047.html create mode 100644 dom/base/test/test_bug711180.html create mode 100644 dom/base/test/test_bug719533.html create mode 100644 dom/base/test/test_bug726364.html create mode 100644 dom/base/test/test_bug737087.html create mode 100644 dom/base/test/test_bug737565.html create mode 100644 dom/base/test/test_bug737612.html create mode 100644 dom/base/test/test_bug738108.html create mode 100644 dom/base/test/test_bug744830.html create mode 100644 dom/base/test/test_bug749367.html create mode 100644 dom/base/test/test_bug750096.html create mode 100644 dom/base/test/test_bug753278.html create mode 100644 dom/base/test/test_bug761120.html create mode 100644 dom/base/test/test_bug769117.html create mode 100644 dom/base/test/test_bug782342.html create mode 100644 dom/base/test/test_bug787778.html create mode 100644 dom/base/test/test_bug789315.html create mode 100644 dom/base/test/test_bug789856.html create mode 100644 dom/base/test/test_bug809003.html create mode 100644 dom/base/test/test_bug810494.html create mode 100644 dom/base/test/test_bug811701.html create mode 100644 dom/base/test/test_bug811701.xhtml create mode 100644 dom/base/test/test_bug813919.html create mode 100644 dom/base/test/test_bug814576.html create mode 100644 dom/base/test/test_bug819051.html create mode 100644 dom/base/test/test_bug820909.html create mode 100644 dom/base/test/test_bug864595.html create mode 100644 dom/base/test/test_bug868999.html create mode 100644 dom/base/test/test_bug869000.html create mode 100644 dom/base/test/test_bug869002.html create mode 100644 dom/base/test/test_bug869006.html create mode 100644 dom/base/test/test_bug876282.html create mode 100644 dom/base/test/test_bug891952.html create mode 100644 dom/base/test/test_bug894874.html create mode 100644 dom/base/test/test_bug895974.html create mode 100644 dom/base/test/test_bug907892.html create mode 100644 dom/base/test/test_bug913761.html create mode 100644 dom/base/test/test_bug922681.html create mode 100644 dom/base/test/test_bug927196.html create mode 100644 dom/base/test/test_bug945152.html create mode 100644 dom/base/test/test_bug962251.html create mode 100644 dom/base/test/test_bug976673.html create mode 100644 dom/base/test/test_bug982153.html create mode 100644 dom/base/test/test_bug999456.html create mode 100644 dom/base/test/test_caretPositionFromPoint.html create mode 100644 dom/base/test/test_change_policy.html create mode 100644 dom/base/test/test_clearTimeoutIntervalNoArg.html create mode 100644 dom/base/test/test_clipboard_nbsp.html create mode 100644 dom/base/test/test_constructor-assignment.html create mode 100644 dom/base/test/test_constructor.html create mode 100644 dom/base/test/test_content_iterator_post_order.html create mode 100644 dom/base/test/test_content_iterator_pre_order.html create mode 100644 dom/base/test/test_content_iterator_subtree.html create mode 100644 dom/base/test/test_copyimage.html create mode 100644 dom/base/test/test_copypaste.html create mode 100644 dom/base/test/test_copypaste.xhtml create mode 100644 dom/base/test/test_copypaste_disabled.html create mode 100644 dom/base/test/test_createHTMLDocument.html create mode 100644 dom/base/test/test_current_inner_window.html create mode 100644 dom/base/test/test_custom_element.html create mode 100644 dom/base/test/test_custom_element_reflector.html create mode 100644 dom/base/test/test_data_uri.html create mode 100644 dom/base/test/test_delazification_strategy.html create mode 100644 dom/base/test/test_document.all_iteration.html create mode 100644 dom/base/test/test_document.all_unqualified.html create mode 100644 dom/base/test/test_document_constructor.html create mode 100644 dom/base/test/test_document_importNode_document.html create mode 100644 dom/base/test/test_document_wireframe.html create mode 100644 dom/base/test/test_domparser_null_char.html create mode 100644 dom/base/test/test_domparsing.html create mode 100644 dom/base/test/test_domrequest.html create mode 100644 dom/base/test/test_domrequesthelper.xhtml create mode 100644 dom/base/test/test_domwindowutils.html create mode 100644 dom/base/test/test_element.matches.html create mode 100644 dom/base/test/test_elementTraversal.html create mode 100644 dom/base/test/test_element_closest.html create mode 100644 dom/base/test/test_embed_xorigin_document.html create mode 100644 dom/base/test/test_encodeToStringWithMaxLength.html create mode 100644 dom/base/test/test_encodeToStringWithRequiresReinitAfterOutput.html create mode 100644 dom/base/test/test_eventsource_event_listener_leaks.html create mode 100644 dom/base/test/test_eventsourceservice_basic.html create mode 100644 dom/base/test/test_eventsourceservice_reconnect_error.html create mode 100644 dom/base/test/test_eventsourceservice_status_error.html create mode 100644 dom/base/test/test_eventsourceservice_worker.html create mode 100644 dom/base/test/test_explicit_user_agent.html create mode 100644 dom/base/test/test_find.html create mode 100644 dom/base/test/test_find_bug1601118.html create mode 100644 dom/base/test/test_find_bug1654683.html create mode 100644 dom/base/test/test_find_nac.html create mode 100644 dom/base/test/test_focus_design_mode.html create mode 100644 dom/base/test/test_focus_display_none_xorigin_iframe.html create mode 100644 dom/base/test/test_focus_keyboard_event.html create mode 100644 dom/base/test/test_focus_scroll_padding_tab.html create mode 100644 dom/base/test/test_focus_scrollable_fieldset.html create mode 100644 dom/base/test/test_focus_scrollable_input.html create mode 100644 dom/base/test/test_focus_shadow_dom.html create mode 100644 dom/base/test/test_focus_shadow_dom_root.html create mode 100644 dom/base/test/test_fragment_sanitization.xhtml create mode 100644 dom/base/test/test_getAttribute_after_createAttribute.html create mode 100644 dom/base/test/test_getElementById.html create mode 100644 dom/base/test/test_getLastOverWindowPointerLocationInCSSPixels.html create mode 100644 dom/base/test/test_getTranslationNodes.html create mode 100644 dom/base/test/test_getTranslationNodes_limit.html create mode 100644 dom/base/test/test_gsp-qualified.html create mode 100644 dom/base/test/test_gsp-quirks.html create mode 100644 dom/base/test/test_gsp-standards.html create mode 100644 dom/base/test/test_history_document_open.html create mode 100644 dom/base/test/test_history_state_null.html create mode 100644 dom/base/test/test_html_colors_quirks.html create mode 100644 dom/base/test/test_html_colors_standards.html create mode 100644 dom/base/test/test_htmlcopyencoder.html create mode 100644 dom/base/test/test_htmlcopyencoder.xhtml create mode 100644 dom/base/test/test_iframe_event_listener_leaks.html create mode 100644 dom/base/test/test_iframe_referrer.html create mode 100644 dom/base/test/test_iframe_referrer_changing.html create mode 100644 dom/base/test/test_iframe_referrer_invalid.html create mode 100644 dom/base/test/test_innersize_scrollport.html create mode 100644 dom/base/test/test_input_vsync_alignment_inner_event_loop.html create mode 100644 dom/base/test/test_input_vsync_alignment_input_while_vsync.html create mode 100644 dom/base/test/test_input_vsync_alignment_lower_than_normal.html create mode 100644 dom/base/test/test_integer_attr_with_leading_zero.html create mode 100644 dom/base/test/test_intersectionobservers.html create mode 100644 dom/base/test/test_link_prefetch.html create mode 100644 dom/base/test/test_link_preload.html create mode 100644 dom/base/test/test_link_stylesheet.html create mode 100644 dom/base/test/test_location_href_unknown_protocol.html create mode 100644 dom/base/test/test_lock_orientation_after_fullscreen.html create mode 100644 dom/base/test/test_lock_orientation_with_pending_fullscreen.html create mode 100644 dom/base/test/test_messagePort.html create mode 100644 dom/base/test/test_messagemanager_send_principal.html create mode 100644 dom/base/test/test_meta_refresh_referrer.html create mode 100644 dom/base/test/test_mozMatchesSelector.html create mode 100644 dom/base/test/test_mutationobservers.html create mode 100644 dom/base/test/test_named_frames.html create mode 100644 dom/base/test/test_navigatorPrefOverride.html create mode 100644 dom/base/test/test_navigator_cookieEnabled.html create mode 100644 dom/base/test/test_navigator_hardwareConcurrency.html create mode 100644 dom/base/test/test_navigator_language.html create mode 100644 dom/base/test/test_navigator_resolve_identity_xrays.xhtml create mode 100644 dom/base/test/test_nested_event_loop_spin_and_idle_tasks.html create mode 100644 dom/base/test/test_nodelist_holes.html create mode 100644 dom/base/test/test_openDialogChromeOnly.html create mode 100644 dom/base/test/test_open_null_features.html create mode 100644 dom/base/test/test_pasting_svg_image.html create mode 100644 dom/base/test/test_pdf_print.html create mode 100644 dom/base/test/test_plugin_freezing.html create mode 100644 dom/base/test/test_postMessage_originAttributes.html create mode 100644 dom/base/test/test_postMessage_solidus.html create mode 100644 dom/base/test/test_postMessages_broadcastChannel.html create mode 100644 dom/base/test/test_postMessages_messagePort.html create mode 100644 dom/base/test/test_postMessages_window.html create mode 100644 dom/base/test/test_postMessages_workers.html create mode 100644 dom/base/test/test_processing_instruction_update_stylesheet.xhtml create mode 100644 dom/base/test/test_progress_events_for_gzip_data.html create mode 100644 dom/base/test/test_pushState_structuredclone.html create mode 100644 dom/base/test/test_range_bounds.html create mode 100644 dom/base/test/test_reentrant_flush.html create mode 100644 dom/base/test/test_root_iframe.html create mode 100644 dom/base/test/test_sandbox_and_document_uri.html create mode 100644 dom/base/test/test_sandbox_structuredclone.html create mode 100644 dom/base/test/test_sandboxed_blob_uri.html create mode 100644 dom/base/test/test_sanitize_xhr.html create mode 100644 dom/base/test/test_screen_orientation.html create mode 100644 dom/base/test/test_script_loader_crossorigin_data_url.html create mode 100644 dom/base/test/test_script_loader_js_cache.html create mode 100644 dom/base/test/test_script_loader_js_cache_frames.html create mode 100644 dom/base/test/test_script_loader_js_cache_module.html create mode 100644 dom/base/test/test_script_loader_js_cache_module_sri.html create mode 100644 dom/base/test/test_sendQueryContentAndSelectionSetEvent.html create mode 100644 dom/base/test/test_sendSelectionSetEvent_with_same_range.html create mode 100644 dom/base/test/test_serializer_noscript.html create mode 100644 dom/base/test/test_setInterval_from_start.html create mode 100644 dom/base/test/test_setInterval_uncatchable_exception.html create mode 100644 dom/base/test/test_setTimeoutWith0.html create mode 100644 dom/base/test/test_settimeout_extra_arguments.html create mode 100644 dom/base/test/test_settimeout_inner.html create mode 100644 dom/base/test/test_setting_opener.html create mode 100644 dom/base/test/test_shared_compartment1.html create mode 100644 dom/base/test/test_shared_compartment2.html create mode 100644 dom/base/test/test_structuredclone_backref.html create mode 100644 dom/base/test/test_structuredclone_error.html create mode 100644 dom/base/test/test_style_cssText.html create mode 100644 dom/base/test/test_suppressed_events_and_scrolling.html create mode 100644 dom/base/test/test_suppressed_events_nested_iframe.html create mode 100644 dom/base/test/test_suppressed_microtasks.html create mode 100644 dom/base/test/test_text_wholeText.html create mode 100644 dom/base/test/test_textnode_normalize_in_selection.html create mode 100644 dom/base/test/test_textnode_split_in_selection.html create mode 100644 dom/base/test/test_timeout_clamp.html create mode 100644 dom/base/test/test_timer_flood.html create mode 100644 dom/base/test/test_title.html create mode 100644 dom/base/test/test_toScreenRect.html create mode 100644 dom/base/test/test_treewalker_nextsibling.xml create mode 100644 dom/base/test/test_urgent_start.html create mode 100644 dom/base/test/test_user_select.html create mode 100644 dom/base/test/test_viewport_metrics_on_landscape_content.html create mode 100644 dom/base/test/test_viewport_scroll.html create mode 100644 dom/base/test/test_viewsource_forbidden_in_object.html create mode 100644 dom/base/test/test_w3element_traversal.html create mode 100644 dom/base/test/test_w3element_traversal.xhtml create mode 100644 dom/base/test/test_w3element_traversal_svg.html create mode 100644 dom/base/test/test_warning_for_blocked_cross_site_request.html create mode 100644 dom/base/test/test_window_close.html create mode 100644 dom/base/test/test_window_constructor.html create mode 100644 dom/base/test/test_window_content.html create mode 100644 dom/base/test/test_window_cross_origin_props.html create mode 100644 dom/base/test/test_window_define_nonconfigurable.html create mode 100644 dom/base/test/test_window_define_symbol.html create mode 100644 dom/base/test/test_window_element_enumeration.html create mode 100644 dom/base/test/test_window_enumeration.html create mode 100644 dom/base/test/test_window_extensible.html create mode 100644 dom/base/test/test_window_focus_by_close_and_open.html create mode 100644 dom/base/test/test_window_indexing.html create mode 100644 dom/base/test/test_window_keys.html create mode 100644 dom/base/test/test_window_named_frame_enumeration.html create mode 100644 dom/base/test/test_window_own_props.html create mode 100644 dom/base/test/test_window_proto.html create mode 100644 dom/base/test/test_writable-replaceable.html create mode 100644 dom/base/test/test_x-frame-options.html create mode 100644 dom/base/test/test_youtube_flash_embed.html create mode 100644 dom/base/test/unit/1_original.xml create mode 100644 dom/base/test/unit/1_result.xml create mode 100644 dom/base/test/unit/2_original.xml create mode 100644 dom/base/test/unit/2_result_1.xml create mode 100644 dom/base/test/unit/2_result_2.xml create mode 100644 dom/base/test/unit/2_result_3.xml create mode 100644 dom/base/test/unit/2_result_4.xml create mode 100644 dom/base/test/unit/3_original.xml create mode 100644 dom/base/test/unit/3_result.xml create mode 100644 dom/base/test/unit/3_result_2.xml create mode 100644 dom/base/test/unit/4_original.xml create mode 100644 dom/base/test/unit/4_result_1.xml create mode 100644 dom/base/test/unit/4_result_2.xml create mode 100644 dom/base/test/unit/4_result_3.xml create mode 100644 dom/base/test/unit/4_result_4.xml create mode 100644 dom/base/test/unit/4_result_5.xml create mode 100644 dom/base/test/unit/4_result_6.xml create mode 100644 dom/base/test/unit/empty_document.xml create mode 100644 dom/base/test/unit/head_utilities.js create mode 100644 dom/base/test/unit/head_xml.js create mode 100644 dom/base/test/unit/isequalnode_data.xml create mode 100644 dom/base/test/unit/nodelist_data_1.xml create mode 100644 dom/base/test/unit/nodelist_data_2.xhtml create mode 100644 dom/base/test/unit/test_blockParsing.js create mode 100644 dom/base/test/unit/test_bug553888.js create mode 100644 dom/base/test/unit/test_bug737966.js create mode 100644 dom/base/test/unit/test_cancelPrefetch.js create mode 100644 dom/base/test/unit/test_chromeutils_base64.js create mode 100644 dom/base/test/unit/test_chromeutils_defineLazyGetter.js create mode 100644 dom/base/test/unit/test_chromeutils_getXPCOMErrorName.js create mode 100644 dom/base/test/unit/test_chromeutils_shallowclone.js create mode 100644 dom/base/test/unit/test_delete_range.xml create mode 100644 dom/base/test/unit/test_error_codes.js create mode 100644 dom/base/test/unit/test_generate_xpath.js create mode 100644 dom/base/test/unit/test_htmlserializer.js create mode 100644 dom/base/test/unit/test_isequalnode.js create mode 100644 dom/base/test/unit/test_js_dev_error_interceptor.js create mode 100644 dom/base/test/unit/test_nodelist.js create mode 100644 dom/base/test/unit/test_normalize.js create mode 100644 dom/base/test/unit/test_range.js create mode 100644 dom/base/test/unit/test_serializers_entities.js create mode 100644 dom/base/test/unit/test_serializers_entities_in_attr.js create mode 100644 dom/base/test/unit/test_structuredcloneholder.js create mode 100644 dom/base/test/unit/test_thirdpartyutil.js create mode 100644 dom/base/test/unit/test_treewalker.js create mode 100644 dom/base/test/unit/test_xhr_document.js create mode 100644 dom/base/test/unit/test_xhr_origin_attributes.js create mode 100644 dom/base/test/unit/test_xhr_standalone.js create mode 100644 dom/base/test/unit/test_xml_parser.js create mode 100644 dom/base/test/unit/test_xml_serializer.js create mode 100644 dom/base/test/unit/test_xmlserializer.js create mode 100644 dom/base/test/unit/xpcshell.toml create mode 100644 dom/base/test/unit_ipc/test_bug553888_wrap.js create mode 100644 dom/base/test/unit_ipc/test_xhr_document_ipc.js create mode 100644 dom/base/test/unit_ipc/xpcshell.toml create mode 100644 dom/base/test/useractivation/file_clipboard_common.js create mode 100644 dom/base/test/useractivation/file_empty.html create mode 100644 dom/base/test/useractivation/file_iframe_check_user_activation.html create mode 100644 dom/base/test/useractivation/file_iframe_consume_user_activation.html create mode 100644 dom/base/test/useractivation/file_iframe_user_activated.html create mode 100644 dom/base/test/useractivation/file_useractivation_sandbox_transient_popup.html create mode 100644 dom/base/test/useractivation/mochitest.toml create mode 100644 dom/base/test/useractivation/moz.build create mode 100644 dom/base/test/useractivation/test_clipboard_editor.html create mode 100644 dom/base/test/useractivation/test_clipboard_noeditor.html create mode 100644 dom/base/test/useractivation/test_popup_blocker_async_callback.html create mode 100644 dom/base/test/useractivation/test_popup_blocker_mouse_event.html create mode 100644 dom/base/test/useractivation/test_popup_blocker_pointer_event.html create mode 100644 dom/base/test/useractivation/test_useractivation_has_been_activated.html create mode 100644 dom/base/test/useractivation/test_useractivation_key_events.html create mode 100644 dom/base/test/useractivation/test_useractivation_sandbox_transient.html create mode 100644 dom/base/test/useractivation/test_useractivation_scrollbar.html create mode 100644 dom/base/test/useractivation/test_useractivation_transient.html create mode 100644 dom/base/test/useractivation/test_useractivation_transient_consuming.html create mode 100644 dom/base/test/variable_style_sheet.sjs create mode 100644 dom/base/test/w3element_traversal.svg create mode 100644 dom/base/test/wholeTexty-helper.xml create mode 100644 dom/base/test/worker_postMessages.js create mode 100644 dom/base/use_counter_metrics.yaml create mode 100644 dom/base/usecounters.py (limited to 'dom/base') diff --git a/dom/base/AbstractRange.cpp b/dom/base/AbstractRange.cpp new file mode 100644 index 0000000000..91234bf0a7 --- /dev/null +++ b/dom/base/AbstractRange.cpp @@ -0,0 +1,398 @@ +/* -*- 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/AbstractRange.h" +#include "mozilla/dom/AbstractRangeBinding.h" + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/RangeUtils.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/StaticRange.h" +#include "mozilla/dom/Selection.h" +#include "nsContentUtils.h" +#include "nsCycleCollectionParticipant.h" +#include "nsGkAtoms.h" +#include "nsINode.h" +#include "nsRange.h" +#include "nsTArray.h" + +namespace mozilla::dom { + +template nsresult AbstractRange::SetStartAndEndInternal( + const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + nsRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary, + nsRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + nsRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RawRangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary, nsRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + StaticRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary, + StaticRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + StaticRange* aRange); +template nsresult AbstractRange::SetStartAndEndInternal( + const RawRangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary, StaticRange* aRange); +template bool AbstractRange::MaybeCacheToReuse(nsRange& aInstance); +template bool AbstractRange::MaybeCacheToReuse(StaticRange& aInstance); + +bool AbstractRange::sHasShutDown = false; + +NS_IMPL_CYCLE_COLLECTING_ADDREF(AbstractRange) +NS_IMPL_CYCLE_COLLECTING_RELEASE(AbstractRange) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbstractRange) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(AbstractRange) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AbstractRange) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner); + // mStart and mEnd may depend on or be depended on some other members in + // concrete classes so that they should be unlinked in sub classes. + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + tmp->mSelections.Clear(); + // Unregistering of the common inclusive ancestors would by design + // also happen when the actual implementations unlink `mStart`/`mEnd`. + // This may introduce additional overhead which is not needed when unlinking, + // therefore this is done here beforehand. + if (tmp->mRegisteredClosestCommonInclusiveAncestor) { + tmp->UnregisterClosestCommonInclusiveAncestor( + tmp->mRegisteredClosestCommonInclusiveAncestor, true); + } + MOZ_DIAGNOSTIC_ASSERT(!tmp->isInList(), + "Shouldn't be registered now that we're unlinking"); + +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AbstractRange) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStart) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEnd) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRegisteredClosestCommonInclusiveAncestor) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +void AbstractRange::MarkDescendants(const nsINode& aNode) { + // Set NodeIsDescendantOfClosestCommonInclusiveAncestorForRangeInSelection on + // aNode's descendants unless aNode is already marked as a range common + // ancestor or a descendant of one, in which case all of our descendants have + // the bit set already. + if (!aNode.IsMaybeSelected()) { + // don't set the Descendant bit on |aNode| itself + nsINode* node = aNode.GetNextNode(&aNode); + while (node) { + node->SetDescendantOfClosestCommonInclusiveAncestorForRangeInSelection(); + if (!node->IsClosestCommonInclusiveAncestorForRangeInSelection()) { + node = node->GetNextNode(&aNode); + } else { + // optimize: skip this sub-tree since it's marked already. + node = node->GetNextNonChildNode(&aNode); + } + } + } +} + +void AbstractRange::UnmarkDescendants(const nsINode& aNode) { + // Unset NodeIsDescendantOfClosestCommonInclusiveAncestorForRangeInSelection + // on aNode's descendants unless aNode is a descendant of another range common + // ancestor. Also, exclude descendants of range common ancestors (but not the + // common ancestor itself). + if (!aNode + .IsDescendantOfClosestCommonInclusiveAncestorForRangeInSelection()) { + // we know |aNode| doesn't have any bit set + nsINode* node = aNode.GetNextNode(&aNode); + while (node) { + node->ClearDescendantOfClosestCommonInclusiveAncestorForRangeInSelection(); + if (!node->IsClosestCommonInclusiveAncestorForRangeInSelection()) { + node = node->GetNextNode(&aNode); + } else { + // We found an ancestor of an overlapping range, skip its descendants. + node = node->GetNextNonChildNode(&aNode); + } + } + } +} + +// NOTE: If you need to change default value of members of AbstractRange, +// update nsRange::Create(nsINode* aNode) and ClearForReuse() too. +AbstractRange::AbstractRange(nsINode* aNode, bool aIsDynamicRange) + : mRegisteredClosestCommonInclusiveAncestor(nullptr), + mIsPositioned(false), + mIsGenerated(false), + mCalledByJS(false), + mIsDynamicRange(aIsDynamicRange) { + mRefCnt.SetIsOnMainThread(); + Init(aNode); +} + +AbstractRange::~AbstractRange() = default; + +void AbstractRange::Init(nsINode* aNode) { + MOZ_ASSERT(aNode, "range isn't in a document!"); + mOwner = aNode->OwnerDoc(); +} + +// static +void AbstractRange::Shutdown() { + sHasShutDown = true; + if (nsTArray>* cachedRanges = nsRange::sCachedRanges) { + nsRange::sCachedRanges = nullptr; + cachedRanges->Clear(); + delete cachedRanges; + } + if (nsTArray>* cachedRanges = + StaticRange::sCachedRanges) { + StaticRange::sCachedRanges = nullptr; + cachedRanges->Clear(); + delete cachedRanges; + } +} + +// static +template +bool AbstractRange::MaybeCacheToReuse(RangeType& aInstance) { + static const size_t kMaxRangeCache = 64; + + // If the instance is not used by JS and the cache is not yet full, we + // should reuse it. Otherwise, delete it. + if (sHasShutDown || aInstance.GetWrapperMaybeDead() || aInstance.GetFlags() || + (RangeType::sCachedRanges && + RangeType::sCachedRanges->Length() == kMaxRangeCache)) { + return false; + } + + aInstance.ClearForReuse(); + + if (!RangeType::sCachedRanges) { + RangeType::sCachedRanges = new nsTArray>(16); + } + RangeType::sCachedRanges->AppendElement(&aInstance); + return true; +} + +nsINode* AbstractRange::GetClosestCommonInclusiveAncestor() const { + return mIsPositioned ? nsContentUtils::GetClosestCommonInclusiveAncestor( + mStart.Container(), mEnd.Container()) + : nullptr; +} + +// static +template +nsresult AbstractRange::SetStartAndEndInternal( + const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary, RangeType* aRange) { + if (NS_WARN_IF(!aStartBoundary.IsSet()) || + NS_WARN_IF(!aEndBoundary.IsSet())) { + return NS_ERROR_INVALID_ARG; + } + + nsINode* newStartRoot = + RangeUtils::ComputeRootNode(aStartBoundary.Container()); + if (!newStartRoot) { + return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; + } + if (!aStartBoundary.IsSetAndValid()) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + if (aStartBoundary.Container() == aEndBoundary.Container()) { + if (!aEndBoundary.IsSetAndValid()) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + // XXX: Offsets - handle this more efficiently. + // If the end offset is less than the start offset, this should be + // collapsed at the end offset. + if (*aStartBoundary.Offset( + RangeBoundaryBase::OffsetFilter::kValidOffsets) > + *aEndBoundary.Offset( + RangeBoundaryBase::OffsetFilter::kValidOffsets)) { + aRange->DoSetRange(aEndBoundary, aEndBoundary, newStartRoot); + } else { + aRange->DoSetRange(aStartBoundary, aEndBoundary, newStartRoot); + } + return NS_OK; + } + + nsINode* newEndRoot = RangeUtils::ComputeRootNode(aEndBoundary.Container()); + if (!newEndRoot) { + return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; + } + if (!aEndBoundary.IsSetAndValid()) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + // If they have different root, this should be collapsed at the end point. + if (newStartRoot != newEndRoot) { + aRange->DoSetRange(aEndBoundary, aEndBoundary, newEndRoot); + return NS_OK; + } + + const Maybe pointOrder = + nsContentUtils::ComparePoints(aStartBoundary, aEndBoundary); + if (!pointOrder) { + // Safely return a value but also detected this in debug builds. + MOZ_ASSERT_UNREACHABLE(); + return NS_ERROR_INVALID_ARG; + } + + // If the end point is before the start point, this should be collapsed at + // the end point. + if (*pointOrder == 1) { + aRange->DoSetRange(aEndBoundary, aEndBoundary, newEndRoot); + return NS_OK; + } + + // Otherwise, set the range as specified. + aRange->DoSetRange(aStartBoundary, aEndBoundary, newStartRoot); + return NS_OK; +} + +bool AbstractRange::IsInSelection(const Selection& aSelection) const { + return mSelections.Contains(&aSelection); +} + +void AbstractRange::RegisterSelection(Selection& aSelection) { + if (IsInSelection(aSelection)) { + return; + } + bool isFirstSelection = mSelections.IsEmpty(); + mSelections.AppendElement(&aSelection); + if (isFirstSelection && !mRegisteredClosestCommonInclusiveAncestor) { + nsINode* commonAncestor = GetClosestCommonInclusiveAncestor(); + MOZ_ASSERT(commonAncestor, "unexpected disconnected nodes"); + RegisterClosestCommonInclusiveAncestor(commonAncestor); + } +} + +const nsTArray>& AbstractRange::GetSelections() const { + return mSelections; +} + +void AbstractRange::UnregisterSelection(const Selection& aSelection) { + mSelections.RemoveElement(&aSelection); + if (mSelections.IsEmpty() && mRegisteredClosestCommonInclusiveAncestor) { + UnregisterClosestCommonInclusiveAncestor( + mRegisteredClosestCommonInclusiveAncestor, false); + MOZ_DIAGNOSTIC_ASSERT( + !mRegisteredClosestCommonInclusiveAncestor, + "How can we have a registered common ancestor when we " + "just unregistered?"); + MOZ_DIAGNOSTIC_ASSERT( + !isInList(), + "Shouldn't be registered if we have no " + "mRegisteredClosestCommonInclusiveAncestor after unregistering"); + } +} + +void AbstractRange::RegisterClosestCommonInclusiveAncestor(nsINode* aNode) { + MOZ_ASSERT(aNode, "bad arg"); + + MOZ_DIAGNOSTIC_ASSERT(IsInAnySelection(), + "registering range not in selection"); + + mRegisteredClosestCommonInclusiveAncestor = aNode; + + MarkDescendants(*aNode); + + UniquePtr>& ranges = + aNode->GetClosestCommonInclusiveAncestorRangesPtr(); + if (!ranges) { + ranges = MakeUnique>(); + } + + MOZ_DIAGNOSTIC_ASSERT(!isInList()); + ranges->insertBack(this); + aNode->SetClosestCommonInclusiveAncestorForRangeInSelection(); +} + +void AbstractRange::UnregisterClosestCommonInclusiveAncestor( + nsINode* aNode, bool aIsUnlinking) { + MOZ_ASSERT(aNode, "bad arg"); + NS_ASSERTION(aNode->IsClosestCommonInclusiveAncestorForRangeInSelection(), + "wrong node"); + MOZ_DIAGNOSTIC_ASSERT(aNode == mRegisteredClosestCommonInclusiveAncestor, + "wrong node"); + LinkedList* ranges = + aNode->GetExistingClosestCommonInclusiveAncestorRanges(); + MOZ_ASSERT(ranges); + + mRegisteredClosestCommonInclusiveAncestor = nullptr; + +#ifdef DEBUG + bool found = false; + for (AbstractRange* range : *ranges) { + if (range == this) { + found = true; + break; + } + } + MOZ_ASSERT(found, + "We should be in the list on our registered common ancestor"); +#endif // DEBUG + + remove(); + + // We don't want to waste time unmarking flags on nodes that are + // being unlinked anyway. + if (!aIsUnlinking && ranges->isEmpty()) { + aNode->ClearClosestCommonInclusiveAncestorForRangeInSelection(); + UnmarkDescendants(*aNode); + } +} + +void AbstractRange::UpdateCommonAncestorIfNecessary() { + nsINode* oldCommonAncestor = mRegisteredClosestCommonInclusiveAncestor; + nsINode* newCommonAncestor = GetClosestCommonInclusiveAncestor(); + if (newCommonAncestor != oldCommonAncestor) { + if (oldCommonAncestor) { + UnregisterClosestCommonInclusiveAncestor(oldCommonAncestor, false); + } + if (newCommonAncestor) { + RegisterClosestCommonInclusiveAncestor(newCommonAncestor); + } else { + MOZ_DIAGNOSTIC_ASSERT(!mIsPositioned, "unexpected disconnected nodes"); + mSelections.Clear(); + MOZ_DIAGNOSTIC_ASSERT( + !mRegisteredClosestCommonInclusiveAncestor, + "How can we have a registered common ancestor when we " + "didn't register ourselves?"); + MOZ_DIAGNOSTIC_ASSERT(!isInList(), + "Shouldn't be registered if we have no " + "mRegisteredClosestCommonInclusiveAncestor"); + } + } +} + +nsINode* AbstractRange::GetParentObject() const { return mOwner; } + +JSObject* AbstractRange::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + MOZ_CRASH("Must be overridden"); +} + +void AbstractRange::ClearForReuse() { + mOwner = nullptr; + mStart = RangeBoundary(); + mEnd = RangeBoundary(); + mIsPositioned = false; + mIsGenerated = false; + mCalledByJS = false; +} + +} // namespace mozilla::dom diff --git a/dom/base/AbstractRange.h b/dom/base/AbstractRange.h new file mode 100644 index 0000000000..c70aaf19ec --- /dev/null +++ b/dom/base/AbstractRange.h @@ -0,0 +1,208 @@ +/* -*- 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_AbstractRange_h +#define mozilla_dom_AbstractRange_h + +#include +#include +#include "ErrorList.h" +#include "js/RootingAPI.h" +#include "mozilla/Assertions.h" +#include "mozilla/Maybe.h" +#include "mozilla/RangeBoundary.h" +#include "mozilla/RefPtr.h" +#include "mozilla/WeakPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsISupports.h" +#include "nsWrapperCache.h" + +class JSObject; +class nsIContent; +class nsINode; +class nsRange; +struct JSContext; + +namespace mozilla::dom { +class Document; +class Selection; +class StaticRange; + +class AbstractRange : public nsISupports, + public nsWrapperCache, + // For linking together selection-associated ranges. + public mozilla::LinkedListElement { + protected: + explicit AbstractRange(nsINode* aNode, bool aIsDynamicRange); + virtual ~AbstractRange(); + + public: + AbstractRange() = delete; + explicit AbstractRange(const AbstractRange& aOther) = delete; + + /** + * Called when the process is shutting down. + */ + static void Shutdown(); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(AbstractRange) + + const RangeBoundary& StartRef() const { return mStart; } + const RangeBoundary& EndRef() const { return mEnd; } + + nsIContent* GetChildAtStartOffset() const { + return mStart.GetChildAtOffset(); + } + nsIContent* GetChildAtEndOffset() const { return mEnd.GetChildAtOffset(); } + bool IsPositioned() const { return mIsPositioned; } + /** + * https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor + */ + nsINode* GetClosestCommonInclusiveAncestor() const; + + // WebIDL + + // If Range is created from JS, it's initialized with Document.createRange() + // and it collaps the range to start of the Document. Therefore, the + // following WebIDL methods are called only when `mIsPositioned` is true. + // So, it does not make sense to take `ErrorResult` as their parameter + // since its destruction cost may appear in profile. If you create range + // object from C++ and needs to check whether it's positioned, should call + // `IsPositioned()` directly. + + nsINode* GetStartContainer() const { return mStart.Container(); } + nsINode* GetEndContainer() const { return mEnd.Container(); } + + Document* GetComposedDocOfContainers() const { + return mStart.Container() ? mStart.Container()->GetComposedDoc() : nullptr; + } + + // FYI: Returns 0 if it's not positioned. + uint32_t StartOffset() const { + return static_cast( + *mStart.Offset(RangeBoundary::OffsetFilter::kValidOrInvalidOffsets)); + } + + // FYI: Returns 0 if it's not positioned. + uint32_t EndOffset() const { + return static_cast( + *mEnd.Offset(RangeBoundary::OffsetFilter::kValidOrInvalidOffsets)); + } + bool Collapsed() const { + return !mIsPositioned || (mStart.Container() == mEnd.Container() && + StartOffset() == EndOffset()); + } + + nsINode* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + bool HasEqualBoundaries(const AbstractRange& aOther) const { + return (mStart == aOther.mStart) && (mEnd == aOther.mEnd); + } + bool IsDynamicRange() const { return mIsDynamicRange; } + bool IsStaticRange() const { return !mIsDynamicRange; } + inline nsRange* AsDynamicRange(); + inline const nsRange* AsDynamicRange() const; + inline StaticRange* AsStaticRange(); + inline const StaticRange* AsStaticRange() const; + + /** + * Return true if this range is part of a Selection object + * and isn't detached. + */ + bool IsInAnySelection() const { return !mSelections.IsEmpty(); } + + MOZ_CAN_RUN_SCRIPT void RegisterSelection( + mozilla::dom::Selection& aSelection); + + void UnregisterSelection(const mozilla::dom::Selection& aSelection); + + /** + * Returns a list of all Selections the range is associated with. + */ + const nsTArray>& GetSelections() const; + + /** + * Return true if this range is in |aSelection|. + */ + bool IsInSelection(const mozilla::dom::Selection& aSelection) const; + + protected: + template + static nsresult SetStartAndEndInternal( + const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary, RangeType* aRange); + + template + static bool MaybeCacheToReuse(RangeType& aInstance); + + void Init(nsINode* aNode); + + friend std::ostream& operator<<(std::ostream& aStream, + const AbstractRange& aRange) { + if (aRange.Collapsed()) { + aStream << "{ mStart=mEnd=" << aRange.mStart; + } else { + aStream << "{ mStart=" << aRange.mStart << ", mEnd=" << aRange.mEnd; + } + return aStream << ", mIsGenerated=" + << (aRange.mIsGenerated ? "true" : "false") + << ", mCalledByJS=" + << (aRange.mIsPositioned ? "true" : "false") + << ", mIsDynamicRange=" + << (aRange.mIsDynamicRange ? "true" : "false") << " }"; + } + + /** + * https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor + */ + void RegisterClosestCommonInclusiveAncestor(nsINode* aNode); + /** + * https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor + */ + void UnregisterClosestCommonInclusiveAncestor(nsINode* aNode, + bool aIsUnlinking); + + void UpdateCommonAncestorIfNecessary(); + + static void MarkDescendants(const nsINode& aNode); + static void UnmarkDescendants(const nsINode& aNode); + + private: + void ClearForReuse(); + + protected: + RefPtr mOwner; + RangeBoundary mStart; + RangeBoundary mEnd; + + // A Range can be part of multiple |Selection|s. This is a very rare use case. + AutoTArray, 1> mSelections; + // mRegisteredClosestCommonInclusiveAncestor is only non-null when the range + // IsInAnySelection(). + nsCOMPtr mRegisteredClosestCommonInclusiveAncestor; + + // `true` if `mStart` and `mEnd` are set for StaticRange or set and valid + // for nsRange. + bool mIsPositioned; + + // Used by nsRange, but this should have this for minimizing the size. + bool mIsGenerated; + // Used by nsRange, but this should have this for minimizing the size. + bool mCalledByJS; + + // true if this is an `nsRange` object. + const bool mIsDynamicRange; + + static bool sHasShutDown; +}; + +} // namespace mozilla::dom + +#endif // #ifndef mozilla_dom_AbstractRange_h diff --git a/dom/base/AncestorIterator.h b/dom/base/AncestorIterator.h new file mode 100644 index 0000000000..d8a56267fd --- /dev/null +++ b/dom/base/AncestorIterator.h @@ -0,0 +1,107 @@ +/* -*- 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/. */ + +/** + * Implementation of some generic iterators over ancestor nodes. + * + * Note that these keep raw pointers to the nodes they iterate from, and as + * such the DOM should not be mutated while they're in use. There are debug + * assertions (via nsMutationGuard) that check this in debug builds. + */ + +#ifndef mozilla_dom_AncestorIterator_h +#define mozilla_dom_AncestorIterator_h + +#include "nsINode.h" +#include "nsIContentInlines.h" +#include "FilteredNodeIterator.h" + +namespace mozilla::dom { + +#ifdef DEBUG +# define MUTATION_GUARD(class_name_) \ + nsMutationGuard mMutationGuard; \ + ~class_name_() { MOZ_ASSERT(!mMutationGuard.Mutated(0)); } +#else +# define MUTATION_GUARD(class_name_) +#endif + +#define DEFINE_ANCESTOR_ITERATOR(name_, method_) \ + class Inclusive##name_ { \ + using Self = Inclusive##name_; \ + \ + public: \ + explicit Inclusive##name_(const nsINode& aNode) \ + : mCurrent(const_cast(&aNode)) {} \ + Self& begin() { return *this; } \ + std::nullptr_t end() const { return nullptr; } \ + bool operator!=(std::nullptr_t) const { return !!mCurrent; } \ + void operator++() { mCurrent = mCurrent->method_(); } \ + nsINode* operator*() { return mCurrent; } \ + \ + MUTATION_GUARD(Inclusive##name_) \ + \ + protected: \ + explicit Inclusive##name_(nsINode* aCurrent) : mCurrent(aCurrent) {} \ + nsINode* mCurrent; \ + }; \ + class name_ : public Inclusive##name_ { \ + public: \ + using Super = Inclusive##name_; \ + explicit name_(const nsINode& aNode) \ + : Inclusive##name_(aNode.method_()) {} \ + }; \ + template \ + class name_##OfTypeIterator : public FilteredNodeIterator { \ + public: \ + explicit name_##OfTypeIterator(const nsINode& aNode) \ + : FilteredNodeIterator(aNode) {} \ + }; \ + template \ + class Inclusive##name_##OfTypeIterator \ + : public FilteredNodeIterator { \ + public: \ + explicit Inclusive##name_##OfTypeIterator(const nsINode& aNode) \ + : FilteredNodeIterator(aNode) {} \ + }; + +DEFINE_ANCESTOR_ITERATOR(Ancestors, GetParentNode) +DEFINE_ANCESTOR_ITERATOR(FlatTreeAncestors, GetFlattenedTreeParentNode) + +#undef MUTATION_GUARD + +} // namespace mozilla::dom + +template +inline mozilla::dom::AncestorsOfTypeIterator nsINode::AncestorsOfType() + const { + return mozilla::dom::AncestorsOfTypeIterator(*this); +} + +template +inline mozilla::dom::InclusiveAncestorsOfTypeIterator +nsINode::InclusiveAncestorsOfType() const { + return mozilla::dom::InclusiveAncestorsOfTypeIterator(*this); +} + +template +inline mozilla::dom::FlatTreeAncestorsOfTypeIterator +nsINode::FlatTreeAncestorsOfType() const { + return mozilla::dom::FlatTreeAncestorsOfTypeIterator(*this); +} + +template +inline mozilla::dom::InclusiveFlatTreeAncestorsOfTypeIterator +nsINode::InclusiveFlatTreeAncestorsOfType() const { + return mozilla::dom::InclusiveFlatTreeAncestorsOfTypeIterator(*this); +} + +template +inline T* nsINode::FirstAncestorOfType() const { + return *(AncestorsOfType()); +} + +#endif // mozilla_dom_AncestorIterator.h diff --git a/dom/base/AnimationFrameProvider.cpp b/dom/base/AnimationFrameProvider.cpp new file mode 100644 index 0000000000..ba2ee8849b --- /dev/null +++ b/dom/base/AnimationFrameProvider.cpp @@ -0,0 +1,53 @@ +/* -*- 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/AnimationFrameProvider.h" +#include "nsThreadUtils.h" + +namespace mozilla::dom { + +FrameRequest::FrameRequest(FrameRequestCallback& aCallback, int32_t aHandle) + : mCallback(&aCallback), mHandle(aHandle) { + LogFrameRequestCallback::LogDispatch(mCallback); +} + +FrameRequest::~FrameRequest() = default; + +nsresult FrameRequestManager::Schedule(FrameRequestCallback& aCallback, + int32_t* aHandle) { + if (mCallbackCounter == INT32_MAX) { + // Can't increment without overflowing; bail out + return NS_ERROR_NOT_AVAILABLE; + } + int32_t newHandle = ++mCallbackCounter; + + mCallbacks.AppendElement(FrameRequest(aCallback, newHandle)); + + *aHandle = newHandle; + return NS_OK; +} + +bool FrameRequestManager::Cancel(int32_t aHandle) { + // mCallbacks is stored sorted by handle + if (mCallbacks.RemoveElementSorted(aHandle)) { + return true; + } + + Unused << mCanceledCallbacks.put(aHandle); + return false; +} + +void FrameRequestManager::Unlink() { mCallbacks.Clear(); } + +void FrameRequestManager::Traverse(nsCycleCollectionTraversalCallback& aCB) { + for (auto& i : mCallbacks) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCB, + "FrameRequestManager::mCallbacks[i]"); + aCB.NoteXPCOMChild(i.mCallback); + } +} + +} // namespace mozilla::dom diff --git a/dom/base/AnimationFrameProvider.h b/dom/base/AnimationFrameProvider.h new file mode 100644 index 0000000000..bbc01910ee --- /dev/null +++ b/dom/base/AnimationFrameProvider.h @@ -0,0 +1,78 @@ +/* -*- 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_AnimationFrameProvider_h +#define mozilla_dom_AnimationFrameProvider_h + +#include "mozilla/dom/AnimationFrameProviderBinding.h" +#include "mozilla/HashTable.h" +#include "mozilla/RefPtr.h" +#include "nsTArray.h" + +namespace mozilla::dom { + +struct FrameRequest { + FrameRequest(FrameRequestCallback& aCallback, int32_t aHandle); + ~FrameRequest(); + + // Comparator operators to allow RemoveElementSorted with an + // integer argument on arrays of FrameRequest + bool operator==(int32_t aHandle) const { return mHandle == aHandle; } + bool operator<(int32_t aHandle) const { return mHandle < aHandle; } + + RefPtr mCallback; + int32_t mHandle; +}; + +class FrameRequestManager { + public: + FrameRequestManager() = default; + ~FrameRequestManager() = default; + + nsresult Schedule(FrameRequestCallback& aCallback, int32_t* aHandle); + bool Cancel(int32_t aHandle); + + bool IsEmpty() const { return mCallbacks.IsEmpty(); } + + bool IsCanceled(int32_t aHandle) const { + return !mCanceledCallbacks.empty() && mCanceledCallbacks.has(aHandle); + } + + void Take(nsTArray& aCallbacks) { + aCallbacks = std::move(mCallbacks); + mCanceledCallbacks.clear(); + } + + void Unlink(); + + void Traverse(nsCycleCollectionTraversalCallback& aCB); + + private: + nsTArray mCallbacks; + + // The set of frame request callbacks that were canceled but which we failed + // to find in mFrameRequestCallbacks. + HashSet mCanceledCallbacks; + + /** + * The current frame request callback handle + */ + int32_t mCallbackCounter = 0; +}; + +inline void ImplCycleCollectionUnlink(FrameRequestManager& aField) { + aField.Unlink(); +} + +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, FrameRequestManager& aField, + const char* aName, uint32_t aFlags) { + aField.Traverse(aCallback); +} + +} // namespace mozilla::dom + +#endif diff --git a/dom/base/AnonymousContent.cpp b/dom/base/AnonymousContent.cpp new file mode 100644 index 0000000000..d4e07869dd --- /dev/null +++ b/dom/base/AnonymousContent.cpp @@ -0,0 +1,47 @@ +/* -*- 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 "AnonymousContent.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ShadowRoot.h" +#include "mozilla/dom/AnonymousContentBinding.h" +#include "nsCycleCollectionParticipant.h" + +namespace mozilla::dom { + +// Ref counting and cycle collection +NS_IMPL_CYCLE_COLLECTION(AnonymousContent, mHost, mRoot) + +already_AddRefed AnonymousContent::Create(Document& aDoc) { + RefPtr host = aDoc.CreateHTMLElement(nsGkAtoms::div); + if (!host) { + return nullptr; + } + host->SetAttr(kNameSpaceID_None, nsGkAtoms::role, u"presentation"_ns, false); + host->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, + u"anonymous-content-host"_ns, false); + RefPtr root = host->AttachShadowWithoutNameChecks( + ShadowRootMode::Closed, Element::DelegatesFocus::No); + root->SetIsUAWidget(); + return do_AddRef(new AnonymousContent(host.forget(), root.forget())); +} + +AnonymousContent::AnonymousContent(already_AddRefed aHost, + already_AddRefed aRoot) + : mHost(aHost), mRoot(aRoot) { + MOZ_ASSERT(mHost); + MOZ_ASSERT(mRoot); +} + +AnonymousContent::~AnonymousContent() = default; + +bool AnonymousContent::WrapObject(JSContext* aCx, + JS::Handle aGivenProto, + JS::MutableHandle aReflector) { + return AnonymousContent_Binding::Wrap(aCx, this, aGivenProto, aReflector); +} +} // namespace mozilla::dom diff --git a/dom/base/AnonymousContent.h b/dom/base/AnonymousContent.h new file mode 100644 index 0000000000..024b315cad --- /dev/null +++ b/dom/base/AnonymousContent.h @@ -0,0 +1,45 @@ +/* -*- 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_AnonymousContent_h +#define mozilla_dom_AnonymousContent_h + +#include "mozilla/AlreadyAddRefed.h" +#include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" + +namespace mozilla::dom { + +class Element; +class Document; +class ShadowRoot; + +class AnonymousContent final { + public: + // Ref counting and cycle collection + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnonymousContent) + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnonymousContent) + + static already_AddRefed Create(Document&); + + Element* Host() const { return mHost.get(); } + ShadowRoot* Root() const { return mRoot.get(); } + + bool WrapObject(JSContext* aCx, JS::Handle aGivenProto, + JS::MutableHandle aReflector); + + private: + ~AnonymousContent(); + + explicit AnonymousContent(already_AddRefed aHost, + already_AddRefed aRoot); + RefPtr mHost; + RefPtr mRoot; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_AnonymousContent_h diff --git a/dom/base/Attr.cpp b/dom/base/Attr.cpp new file mode 100644 index 0000000000..7ac76be544 --- /dev/null +++ b/dom/base/Attr.cpp @@ -0,0 +1,221 @@ +/* -*- 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/. */ + +/* + * Implementation of DOM Core's Attr node. + */ + +#include "mozilla/dom/Attr.h" +#include "mozilla/dom/AttrBinding.h" +#include "mozilla/dom/Element.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/InternalMutationEvent.h" +#include "mozilla/StaticPrefs_dom.h" +#include "nsContentCreatorFunctions.h" +#include "nsError.h" +#include "nsUnicharUtils.h" +#include "nsDOMString.h" +#include "nsIContentInlines.h" +#include "mozilla/dom/Document.h" +#include "nsGkAtoms.h" +#include "nsCOMArray.h" +#include "nsNameSpaceManager.h" +#include "nsTextNode.h" +#include "mozAutoDocUpdate.h" +#include "nsWrapperCacheInlines.h" +#include "NodeUbiReporting.h" + +namespace mozilla::dom { + +//---------------------------------------------------------------------- +bool Attr::sInitialized; + +Attr::Attr(nsDOMAttributeMap* aAttrMap, + already_AddRefed&& aNodeInfo, const nsAString& aValue) + : nsINode(std::move(aNodeInfo)), mAttrMap(aAttrMap), mValue(aValue) { + MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!"); + MOZ_ASSERT(mNodeInfo->NodeType() == ATTRIBUTE_NODE, "Wrong nodeType"); + + // We don't add a reference to our content. It will tell us + // to drop our reference when it goes away. +} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Attr) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr) + if (!nsINode::Traverse(tmp, cb)) { + return NS_SUCCESS_INTERRUPTED_TRAVERSE; + } + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr) + nsINode::Unlink(tmp); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr) + Element* ownerElement = tmp->GetElement(); + if (tmp->HasKnownLiveWrapper()) { + if (ownerElement) { + // The attribute owns the element via attribute map so we can + // mark it when the attribute is certainly alive. + mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement); + } + return true; + } + if (ownerElement && + mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) { + return true; + } +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr) + return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr) + return tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + +// QueryInterface implementation for Attr +NS_INTERFACE_TABLE_HEAD(Attr) + NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY + NS_INTERFACE_TABLE(Attr, nsINode, EventTarget) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, + new nsNodeSupportsWeakRefTearoff(this)) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr) + +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE_AND_DESTROY(Attr, + LastRelease(), + Destroy()) + +NS_IMPL_DOMARENA_DESTROY(Attr) + +void Attr::SetMap(nsDOMAttributeMap* aMap) { + if (mAttrMap && !aMap && sInitialized) { + // We're breaking a relationship with content and not getting a new one, + // need to locally cache value. GetValue() does that. + GetValue(mValue); + } + + mAttrMap = aMap; +} + +Element* Attr::GetElement() const { + if (!mAttrMap) { + return nullptr; + } + nsIContent* content = mAttrMap->GetContent(); + return content ? content->AsElement() : nullptr; +} + +nsresult Attr::SetOwnerDocument(Document* aDocument) { + NS_ASSERTION(aDocument, "Missing document"); + + Document* doc = OwnerDoc(); + NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument"); + doc->RemoveAllPropertiesFor(this); + + RefPtr newNodeInfo = aDocument->NodeInfoManager()->GetNodeInfo( + mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(), + mNodeInfo->NamespaceID(), ATTRIBUTE_NODE); + NS_ASSERTION(newNodeInfo, "GetNodeInfo lies"); + mNodeInfo.swap(newNodeInfo); + + return NS_OK; +} + +void Attr::GetName(nsAString& aName) { aName = NodeName(); } + +void Attr::GetValue(nsAString& aValue) { + Element* element = GetElement(); + if (element) { + RefPtr nameAtom = mNodeInfo->NameAtom(); + element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue); + } else { + aValue = mValue; + } +} + +void Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, + ErrorResult& aRv) { + Element* element = GetElement(); + if (!element) { + mValue = aValue; + return; + } + + RefPtr nameAtom = mNodeInfo->NameAtom(); + aRv = element->SetAttr(mNodeInfo->NamespaceID(), nameAtom, + mNodeInfo->GetPrefixAtom(), aValue, + aTriggeringPrincipal, true); +} + +void Attr::SetValue(const nsAString& aValue, ErrorResult& aRv) { + SetValue(aValue, nullptr, aRv); +} + +bool Attr::Specified() const { return true; } + +Element* Attr::GetOwnerElement() { return GetElement(); } + +void Attr::GetNodeValueInternal(nsAString& aNodeValue) { GetValue(aNodeValue); } + +void Attr::SetNodeValueInternal(const nsAString& aNodeValue, + ErrorResult& aError) { + SetValue(aNodeValue, nullptr, aError); +} + +nsresult Attr::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const { + nsAutoString value; + const_cast(this)->GetValue(value); + *aResult = new (aNodeInfo->NodeInfoManager()) + Attr(nullptr, do_AddRef(aNodeInfo), value); + + NS_ADDREF(*aResult); + + return NS_OK; +} + +nsIURI* Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const { + Element* parent = GetElement(); + + return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) + : OwnerDoc()->GetBaseURI(aTryUseXHRDocBaseURI); +} + +void Attr::GetTextContentInternal(nsAString& aTextContent, + OOMReporter& aError) { + GetValue(aTextContent); +} + +void Attr::SetTextContentInternal(const nsAString& aTextContent, + nsIPrincipal* aSubjectPrincipal, + ErrorResult& aError) { + SetNodeValueInternal(aTextContent, aError); +} + +void Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor) { + aVisitor.mCanHandle = true; +} + +void Attr::Initialize() { sInitialized = true; } + +void Attr::Shutdown() { sInitialized = false; } + +JSObject* Attr::WrapNode(JSContext* aCx, JS::Handle aGivenProto) { + return Attr_Binding::Wrap(aCx, this, aGivenProto); +} + +void Attr::ConstructUbiNode(void* storage) { + JS::ubi::Concrete::construct(storage, this); +} + +} // namespace mozilla::dom diff --git a/dom/base/Attr.h b/dom/base/Attr.h new file mode 100644 index 0000000000..311f7aa597 --- /dev/null +++ b/dom/base/Attr.h @@ -0,0 +1,111 @@ +/* -*- 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/. */ + +/* + * Implementation of DOM Core's Attr node. + */ + +#ifndef mozilla_dom_Attr_h +#define mozilla_dom_Attr_h + +#include "mozilla/Attributes.h" +#include "nsDOMAttributeMap.h" +#include "nsINode.h" +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsStubMutationObserver.h" + +namespace mozilla { +class EventChainPreVisitor; +namespace dom { + +class Document; + +// Attribute helper class used to wrap up an attribute with a dom +// object that implements the DOM Attr interface. +class Attr final : public nsINode { + virtual ~Attr() = default; + + public: + Attr(nsDOMAttributeMap* aAttrMap, already_AddRefed&& aNodeInfo, + const nsAString& aValue); + + NS_DECL_ISUPPORTS_INHERITED + NS_IMETHOD_(void) DeleteCycleCollectable(void) final; + + NS_DECL_DOMARENA_DESTROY + + NS_IMPL_FROMNODE_HELPER(Attr, IsAttr()) + + // nsINode interface + virtual void GetTextContentInternal(nsAString& aTextContent, + OOMReporter& aError) override; + virtual void SetTextContentInternal(const nsAString& aTextContent, + nsIPrincipal* aSubjectPrincipal, + ErrorResult& aError) override; + virtual void GetNodeValueInternal(nsAString& aNodeValue) override; + virtual void SetNodeValueInternal(const nsAString& aNodeValue, + ErrorResult& aError) override; + + void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; + + void ConstructUbiNode(void* storage) override; + + nsDOMAttributeMap* GetMap() { return mAttrMap; } + + void SetMap(nsDOMAttributeMap* aMap); + + Element* GetElement() const; + + /** + * Called when our ownerElement is moved into a new document. + * Updates the nodeinfo of this node. + */ + nsresult SetOwnerDocument(Document* aDocument); + + // nsINode interface + nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; + nsIURI* GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override; + + static void Initialize(); + static void Shutdown(); + + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS(Attr) + + // WebIDL + virtual JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; + + void GetName(nsAString& aName); + void GetValue(nsAString& aValue); + + void SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, + ErrorResult& aRv); + void SetValue(const nsAString& aValue, ErrorResult& aRv); + + bool Specified() const; + + // XPCOM GetNamespaceURI() is OK + // XPCOM GetPrefix() is OK + // XPCOM GetLocalName() is OK + + Element* GetOwnerElement(); + + protected: + virtual Element* GetNameSpaceElement() override { return GetElement(); } + + static bool sInitialized; + + private: + RefPtr mAttrMap; + nsString mValue; +}; + +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_Attr_h */ diff --git a/dom/base/AttrArray.cpp b/dom/base/AttrArray.cpp new file mode 100644 index 0000000000..83656ede89 --- /dev/null +++ b/dom/base/AttrArray.cpp @@ -0,0 +1,377 @@ +/* -*- 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/. */ + +/* + * Storage of the children and attributes of a DOM node; storage for + * the two is unified to minimize footprint. + */ + +#include "AttrArray.h" + +#include "mozilla/AttributeStyles.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/MathAlgorithms.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/ServoBindings.h" + +#include "nsString.h" +#include "nsUnicharUtils.h" +#include "nsContentUtils.h" // nsAutoScriptBlocker + +using mozilla::CheckedUint32; + +AttrArray::Impl::~Impl() { + for (InternalAttr& attr : Attrs()) { + attr.~InternalAttr(); + } + if (auto* decl = GetMappedDeclarationBlock()) { + Servo_DeclarationBlock_Release(decl); + mMappedAttributeBits = 0; + } +} + +void AttrArray::SetMappedDeclarationBlock( + already_AddRefed aBlock) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl); + MOZ_ASSERT(IsPendingMappedAttributeEvaluation()); + if (auto* decl = GetMappedDeclarationBlock()) { + Servo_DeclarationBlock_Release(decl); + } + mImpl->mMappedAttributeBits = reinterpret_cast(aBlock.take()); + MOZ_ASSERT(!IsPendingMappedAttributeEvaluation()); +} + +const nsAttrValue* AttrArray::GetAttr(const nsAtom* aLocalName) const { + NS_ASSERTION(aLocalName, "Must have attr name"); + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName)) { + return &attr.mValue; + } + } + return nullptr; +} + +const nsAttrValue* AttrArray::GetAttr(const nsAtom* aLocalName, + int32_t aNamespaceID) const { + NS_ASSERTION(aLocalName, "Must have attr name"); + NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, "Must have namespace"); + if (aNamespaceID == kNameSpaceID_None) { + // This should be the common case so lets use the optimized loop + return GetAttr(aLocalName); + } + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName, aNamespaceID)) { + return &attr.mValue; + } + } + return nullptr; +} + +const nsAttrValue* AttrArray::GetAttr(const nsAString& aLocalName) const { + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName)) { + return &attr.mValue; + } + } + return nullptr; +} + +const nsAttrValue* AttrArray::GetAttr(const nsAString& aName, + nsCaseTreatment aCaseSensitive) const { + // Check whether someone is being silly and passing non-lowercase + // attr names. + if (aCaseSensitive == eIgnoreCase && + nsContentUtils::StringContainsASCIIUpper(aName)) { + // Try again with a lowercased name, but make sure we can't reenter this + // block by passing eCaseSensitive for aCaseSensitive. + nsAutoString lowercase; + nsContentUtils::ASCIIToLower(aName, lowercase); + return GetAttr(lowercase, eCaseMatters); + } + + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.QualifiedNameEquals(aName)) { + return &attr.mValue; + } + } + + return nullptr; +} + +const nsAttrValue* AttrArray::AttrAt(uint32_t aPos) const { + NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray"); + return &mImpl->Attrs()[aPos].mValue; +} + +template +inline nsresult AttrArray::AddNewAttribute(Name* aName, nsAttrValue& aValue) { + MOZ_ASSERT(!mImpl || mImpl->mCapacity >= mImpl->mAttrCount); + if (!mImpl || mImpl->mCapacity == mImpl->mAttrCount) { + if (!GrowBy(1)) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + InternalAttr& attr = mImpl->mBuffer[mImpl->mAttrCount++]; + new (&attr.mName) nsAttrName(aName); + new (&attr.mValue) nsAttrValue(); + attr.mValue.SwapValueWith(aValue); + return NS_OK; +} + +nsresult AttrArray::SetAndSwapAttr(nsAtom* aLocalName, nsAttrValue& aValue, + bool* aHadValue) { + *aHadValue = false; + + for (InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName)) { + attr.mValue.SwapValueWith(aValue); + *aHadValue = true; + return NS_OK; + } + } + + return AddNewAttribute(aLocalName, aValue); +} + +nsresult AttrArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName, + nsAttrValue& aValue, bool* aHadValue) { + int32_t namespaceID = aName->NamespaceID(); + nsAtom* localName = aName->NameAtom(); + if (namespaceID == kNameSpaceID_None) { + return SetAndSwapAttr(localName, aValue, aHadValue); + } + + *aHadValue = false; + for (InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(localName, namespaceID)) { + attr.mName.SetTo(aName); + attr.mValue.SwapValueWith(aValue); + *aHadValue = true; + return NS_OK; + } + } + + return AddNewAttribute(aName, aValue); +} + +nsresult AttrArray::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue) { + NS_ASSERTION(aPos < AttrCount(), "out-of-bounds"); + + mImpl->mBuffer[aPos].mValue.SwapValueWith(aValue); + mImpl->mBuffer[aPos].~InternalAttr(); + + memmove(mImpl->mBuffer + aPos, mImpl->mBuffer + aPos + 1, + (mImpl->mAttrCount - aPos - 1) * sizeof(InternalAttr)); + + --mImpl->mAttrCount; + return NS_OK; +} + +mozilla::dom::BorrowedAttrInfo AttrArray::AttrInfoAt(uint32_t aPos) const { + NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray"); + InternalAttr& attr = mImpl->mBuffer[aPos]; + return BorrowedAttrInfo(&attr.mName, &attr.mValue); +} + +const nsAttrName* AttrArray::AttrNameAt(uint32_t aPos) const { + NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray"); + return &mImpl->mBuffer[aPos].mName; +} + +const nsAttrName* AttrArray::GetSafeAttrNameAt(uint32_t aPos) const { + if (aPos >= AttrCount()) { + return nullptr; + } + return &mImpl->mBuffer[aPos].mName; +} + +const nsAttrName* AttrArray::GetExistingAttrNameFromQName( + const nsAString& aName) const { + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.QualifiedNameEquals(aName)) { + return &attr.mName; + } + } + return nullptr; +} + +int32_t AttrArray::IndexOfAttr(const nsAtom* aLocalName) const { + int32_t i = 0; + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName)) { + return i; + } + ++i; + } + return -1; +} + +int32_t AttrArray::IndexOfAttr(const nsAtom* aLocalName, + int32_t aNamespaceID) const { + if (aNamespaceID == kNameSpaceID_None) { + // This should be the common case so lets use the optimized loop + return IndexOfAttr(aLocalName); + } + int32_t i = 0; + for (const InternalAttr& attr : Attrs()) { + if (attr.mName.Equals(aLocalName, aNamespaceID)) { + return i; + } + ++i; + } + return -1; +} + +void AttrArray::Compact() { + if (!mImpl) { + return; + } + + if (!mImpl->mAttrCount && !mImpl->mMappedAttributeBits) { + mImpl.reset(); + return; + } + + // Nothing to do. + if (mImpl->mAttrCount == mImpl->mCapacity) { + return; + } + + Impl* oldImpl = mImpl.release(); + Impl* impl = static_cast( + realloc(oldImpl, Impl::AllocationSizeForAttributes(oldImpl->mAttrCount))); + if (!impl) { + mImpl.reset(oldImpl); + return; + } + impl->mCapacity = impl->mAttrCount; + mImpl.reset(impl); +} + +nsresult AttrArray::EnsureCapacityToClone(const AttrArray& aOther) { + MOZ_ASSERT(!mImpl, + "AttrArray::EnsureCapacityToClone requires the array be empty " + "when called"); + + uint32_t attrCount = aOther.AttrCount(); + if (!attrCount) { + return NS_OK; + } + + // No need to use a CheckedUint32 because we are cloning. We know that we + // have already allocated an AttrArray of this size. + mImpl.reset( + static_cast(malloc(Impl::AllocationSizeForAttributes(attrCount)))); + NS_ENSURE_TRUE(mImpl, NS_ERROR_OUT_OF_MEMORY); + + mImpl->mMappedAttributeBits = 0; + mImpl->mCapacity = attrCount; + mImpl->mAttrCount = 0; + + return NS_OK; +} + +bool AttrArray::GrowBy(uint32_t aGrowSize) { + const uint32_t kLinearThreshold = 16; + const uint32_t kLinearGrowSize = 4; + + CheckedUint32 capacity = mImpl ? mImpl->mCapacity : 0; + CheckedUint32 minCapacity = capacity; + minCapacity += aGrowSize; + if (!minCapacity.isValid()) { + return false; + } + + if (capacity.value() <= kLinearThreshold) { + do { + capacity += kLinearGrowSize; + if (!capacity.isValid()) { + return false; + } + } while (capacity.value() < minCapacity.value()); + } else { + uint32_t shift = mozilla::CeilingLog2(minCapacity.value()); + if (shift >= 32) { + return false; + } + capacity = 1u << shift; + } + + return GrowTo(capacity.value()); +} + +bool AttrArray::GrowTo(uint32_t aCapacity) { + uint32_t oldCapacity = mImpl ? mImpl->mCapacity : 0; + if (aCapacity <= oldCapacity) { + return true; + } + + CheckedUint32 sizeInBytes = aCapacity; + sizeInBytes *= sizeof(InternalAttr); + if (!sizeInBytes.isValid()) { + return false; + } + + sizeInBytes += sizeof(Impl); + if (!sizeInBytes.isValid()) { + return false; + } + + MOZ_ASSERT(sizeInBytes.value() == + Impl::AllocationSizeForAttributes(aCapacity)); + + const bool needToInitialize = !mImpl; + Impl* oldImpl = mImpl.release(); + Impl* newImpl = static_cast(realloc(oldImpl, sizeInBytes.value())); + if (!newImpl) { + mImpl.reset(oldImpl); + return false; + } + + mImpl.reset(newImpl); + + // Set initial counts if we didn't have a buffer before + if (needToInitialize) { + mImpl->mMappedAttributeBits = 0; + mImpl->mAttrCount = 0; + } + + mImpl->mCapacity = aCapacity; + return true; +} + +size_t AttrArray::SizeOfExcludingThis( + mozilla::MallocSizeOf aMallocSizeOf) const { + if (!mImpl) { + return 0; + } + size_t n = aMallocSizeOf(mImpl.get()); + for (const InternalAttr& attr : Attrs()) { + n += attr.mValue.SizeOfExcludingThis(aMallocSizeOf); + } + return n; +} + +int32_t AttrArray::FindAttrValueIn(int32_t aNameSpaceID, const nsAtom* aName, + AttrValuesArray* aValues, + nsCaseTreatment aCaseSensitive) const { + NS_ASSERTION(aName, "Must have attr name"); + NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace"); + NS_ASSERTION(aValues, "Null value array"); + + const nsAttrValue* val = GetAttr(aName, aNameSpaceID); + if (val) { + for (int32_t i = 0; aValues[i]; ++i) { + if (val->Equals(aValues[i], aCaseSensitive)) { + return i; + } + } + return ATTR_VALUE_NO_MATCH; + } + return ATTR_MISSING; +} diff --git a/dom/base/AttrArray.h b/dom/base/AttrArray.h new file mode 100644 index 0000000000..9331ac2326 --- /dev/null +++ b/dom/base/AttrArray.h @@ -0,0 +1,246 @@ +/* -*- 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/. */ + +/* + * Storage of the attributes of a DOM node. + */ + +#ifndef AttrArray_h___ +#define AttrArray_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/Span.h" +#include "mozilla/dom/BorrowedAttrInfo.h" + +#include "nscore.h" +#include "nsAttrName.h" +#include "nsAttrValue.h" +#include "nsCaseTreatment.h" + +namespace mozilla { +class AttributeStyles; +struct StyleLockedDeclarationBlock; +} // namespace mozilla + +class AttrArray { + using BorrowedAttrInfo = mozilla::dom::BorrowedAttrInfo; + + public: + AttrArray() = default; + ~AttrArray() = default; + + bool HasAttrs() const { return !!AttrCount(); } + + uint32_t AttrCount() const { return mImpl ? mImpl->mAttrCount : 0; } + + const nsAttrValue* GetAttr(const nsAtom* aLocalName) const; + + const nsAttrValue* GetAttr(const nsAtom* aLocalName, + int32_t aNamespaceID) const; + // As above but using a string attr name and always using + // kNameSpaceID_None. This is always case-sensitive. + const nsAttrValue* GetAttr(const nsAString& aName) const; + // Get an nsAttrValue by qualified name. Can optionally do + // ASCII-case-insensitive name matching. + const nsAttrValue* GetAttr(const nsAString& aName, + nsCaseTreatment aCaseSensitive) const; + const nsAttrValue* AttrAt(uint32_t aPos) const; + // SetAndSwapAttr swaps the current attribute value with aValue. + // If the attribute was unset, an empty value will be swapped into aValue + // and aHadValue will be set to false. Otherwise, aHadValue will be set to + // true. + nsresult SetAndSwapAttr(nsAtom* aLocalName, nsAttrValue& aValue, + bool* aHadValue); + nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue, + bool* aHadValue); + + // This stores the argument and clears the pending mapped attribute evaluation + // bit, so after calling this IsPendingMappedAttributeEvaluation() is + // guaranteed to return false. + void SetMappedDeclarationBlock( + already_AddRefed); + + bool IsPendingMappedAttributeEvaluation() const { + return mImpl && mImpl->mMappedAttributeBits & 1; + } + + mozilla::StyleLockedDeclarationBlock* GetMappedDeclarationBlock() const { + return mImpl ? mImpl->GetMappedDeclarationBlock() : nullptr; + } + + // Remove the attr at position aPos. The value of the attr is placed in + // aValue; any value that was already in aValue is destroyed. + nsresult RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue); + + // Returns attribute name at given position, *not* out-of-bounds safe + const nsAttrName* AttrNameAt(uint32_t aPos) const; + + // Returns the attribute info at a given position, *not* out-of-bounds safe + BorrowedAttrInfo AttrInfoAt(uint32_t aPos) const; + + // Returns attribute name at given position or null if aPos is out-of-bounds + const nsAttrName* GetSafeAttrNameAt(uint32_t aPos) const; + + const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const; + int32_t IndexOfAttr(const nsAtom* aLocalName) const; + int32_t IndexOfAttr(const nsAtom* aLocalName, int32_t aNamespaceID) const; + + void Compact(); + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + // Mark the element as pending mapped attribute evaluation. This should be + // called when a mapped attribute is changed (regardless of connectedness). + bool MarkAsPendingPresAttributeEvaluation() { + // It'd be great to be able to assert that mImpl is non-null or we're the + // element. + if (MOZ_UNLIKELY(!mImpl) && !GrowBy(1)) { + return false; + } + InfallibleMarkAsPendingPresAttributeEvaluation(); + return true; + } + + // See above. + void InfallibleMarkAsPendingPresAttributeEvaluation() { + MOZ_ASSERT(mImpl); + mImpl->mMappedAttributeBits |= 1; + } + + // Clear the servo declaration block on the mapped attributes, if any + // Will assert off main thread + void ClearMappedServoStyle(); + + // Increases capacity (if necessary) to have enough space to accomodate the + // unmapped attributes of |aOther|. + nsresult EnsureCapacityToClone(const AttrArray& aOther); + + enum AttrValuesState { ATTR_MISSING = -1, ATTR_VALUE_NO_MATCH = -2 }; + using AttrValuesArray = nsStaticAtom* const; + int32_t FindAttrValueIn(int32_t aNameSpaceID, const nsAtom* aName, + AttrValuesArray* aValues, + nsCaseTreatment aCaseSensitive) const; + + inline bool GetAttr(int32_t aNameSpaceID, const nsAtom* aName, + nsAString& aResult) const { + MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in"); + const nsAttrValue* val = GetAttr(aName, aNameSpaceID); + if (!val) { + return false; + } + val->ToString(aResult); + return true; + } + + inline bool GetAttr(const nsAtom* aName, nsAString& aResult) const { + MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in"); + const nsAttrValue* val = GetAttr(aName); + if (!val) { + return false; + } + val->ToString(aResult); + return true; + } + + inline bool HasAttr(const nsAtom* aName) const { return !!GetAttr(aName); } + + inline bool HasAttr(int32_t aNameSpaceID, const nsAtom* aName) const { + return !!GetAttr(aName, aNameSpaceID); + } + + inline bool AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName, + const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + NS_ASSERTION(aName, "Must have attr name"); + NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace"); + const nsAttrValue* val = GetAttr(aName, aNameSpaceID); + return val && val->Equals(aValue, aCaseSensitive); + } + + inline bool AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName, + const nsAtom* aValue, + nsCaseTreatment aCaseSensitive) const { + NS_ASSERTION(aName, "Must have attr name"); + NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace"); + NS_ASSERTION(aValue, "Null value atom"); + + const nsAttrValue* val = GetAttr(aName, aNameSpaceID); + return val && val->Equals(aValue, aCaseSensitive); + } + + struct InternalAttr { + nsAttrName mName; + nsAttrValue mValue; + }; + + AttrArray(const AttrArray& aOther) = delete; + AttrArray& operator=(const AttrArray& aOther) = delete; + + bool GrowBy(uint32_t aGrowSize); + bool GrowTo(uint32_t aCapacity); + + private: + // Tries to create an attribute, growing the buffer if needed, with the given + // name and value. + // + // The value is moved from the argument. + // + // `Name` can be anything you construct a `nsAttrName` with (either an atom or + // a NodeInfo pointer). + template + nsresult AddNewAttribute(Name*, nsAttrValue&); + + class Impl { + public: + constexpr static size_t AllocationSizeForAttributes(uint32_t aAttrCount) { + return sizeof(Impl) + aAttrCount * sizeof(InternalAttr); + } + + mozilla::StyleLockedDeclarationBlock* GetMappedDeclarationBlock() const { + return reinterpret_cast( + mMappedAttributeBits & ~uintptr_t(1)); + } + + auto Attrs() const { + return mozilla::Span{mBuffer, mAttrCount}; + } + + auto Attrs() { return mozilla::Span{mBuffer, mAttrCount}; } + + Impl(const Impl&) = delete; + Impl(Impl&&) = delete; + ~Impl(); + + uint32_t mAttrCount; + uint32_t mCapacity; // In number of InternalAttrs + + // mMappedAttributeBits is a tagged pointer of a + // StyleLockedDeclarationBlock, which holds the style information that our + // attributes map to. + // + // If the lower bit is set, then our mapped attributes are dirty. This just + // means that we might have mapped attributes (or used to and no longer + // have), and are pending an update to recompute our declaration. + uintptr_t mMappedAttributeBits = 0; + + // Allocated in the same buffer as `Impl`. + InternalAttr mBuffer[0]; + }; + + mozilla::Span Attrs() { + return mImpl ? mImpl->Attrs() : mozilla::Span(); + } + + mozilla::Span Attrs() const { + return mImpl ? mImpl->Attrs() : mozilla::Span(); + } + + mozilla::UniquePtr mImpl; +}; + +#endif diff --git a/dom/base/AutoPrintEventDispatcher.h b/dom/base/AutoPrintEventDispatcher.h new file mode 100644 index 0000000000..8c91285f38 --- /dev/null +++ b/dom/base/AutoPrintEventDispatcher.h @@ -0,0 +1,65 @@ +/* -*- 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_AutoPrintEventDispatcher_h +#define mozilla_dom_AutoPrintEventDispatcher_h + +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentInlines.h" +#include "nsContentUtils.h" +#include "nsGlobalWindowOuter.h" +#include "nsIPrintSettings.h" + +namespace mozilla::dom { + +class AutoPrintEventDispatcher { + // NOTE(emilio): For fission iframes, we dispatch this event in + // RecvCloneDocumentTreeIntoSelf. + static void CollectInProcessSubdocuments( + Document& aDoc, nsTArray>& aDocs) { + aDoc.EnumerateSubDocuments([&aDocs](Document& aSubDoc) { + aDocs.AppendElement(&aSubDoc); + CollectInProcessSubdocuments(aSubDoc, aDocs); + return CallState::Continue; + }); + } + + MOZ_CAN_RUN_SCRIPT void DispatchEvent(bool aBefore) { + for (auto& doc : mDocuments) { + nsContentUtils::DispatchTrustedEvent( + doc, nsGlobalWindowOuter::Cast(doc->GetWindow()), + aBefore ? u"beforeprint"_ns : u"afterprint"_ns, CanBubble::eNo, + Cancelable::eNo, nullptr); + if (RefPtr presContext = doc->GetPresContext()) { + presContext->EmulateMedium(aBefore ? nsGkAtoms::print : nullptr); + // Ensure media query listeners fire. + // FIXME(emilio): This is hacky, at best, but is required for compat + // with some pages, see bug 774398. + doc->EvaluateMediaQueriesAndReportChanges(/* aRecurse = */ false); + } + } + } + + public: + MOZ_CAN_RUN_SCRIPT explicit AutoPrintEventDispatcher(Document& aDoc) { + if (!aDoc.IsStaticDocument()) { + mDocuments.AppendElement(&aDoc); + CollectInProcessSubdocuments(aDoc, mDocuments); + } + + DispatchEvent(true); + } + + MOZ_CAN_RUN_SCRIPT ~AutoPrintEventDispatcher() { DispatchEvent(false); } + + AutoTArray, 8> mDocuments; + const nsSize mPageSize; + nsRect mVisibleAreaToRestore; +}; + +} // namespace mozilla::dom + +#endif diff --git a/dom/base/AutoSuppressEventHandlingAndSuspend.h b/dom/base/AutoSuppressEventHandlingAndSuspend.h new file mode 100644 index 0000000000..6f23fce475 --- /dev/null +++ b/dom/base/AutoSuppressEventHandlingAndSuspend.h @@ -0,0 +1,66 @@ +/* -*- 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 dom_base_AutoSuppressEventHandlingAndSuspend_h +#define dom_base_AutoSuppressEventHandlingAndSuspend_h + +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/BrowsingContextGroup.h" +#include "mozilla/dom/Document.h" +#include "nsCOMPtr.h" +#include "nsPIDOMWindow.h" +#include "nsTArray.h" + +namespace mozilla::dom { + +/** + * Suppresses event handling and suspends for all in-process documents in a + * BrowsingContext subtree. + */ +class MOZ_RAII AutoSuppressEventHandling : public AutoWalkBrowsingContextGroup { + public: + AutoSuppressEventHandling() = default; + + explicit AutoSuppressEventHandling(BrowsingContext* aContext) { + if (aContext) { + SuppressBrowsingContext(aContext); + } + } + + ~AutoSuppressEventHandling(); + + protected: + virtual void SuppressDocument(Document* aDocument) override; + void UnsuppressDocument(Document* aDocument) override; +}; + +/** + * Suppresses event handling and suspends the active inner window for all + * in-process documents in a BrowsingContextGroup. This should be used while + * spinning the event loop for a synchronous operation (like `window.open()`) + * which affects operations in any other window in the same BrowsingContext + * group. + */ +class MOZ_RAII AutoSuppressEventHandlingAndSuspend + : private AutoSuppressEventHandling { + public: + explicit AutoSuppressEventHandlingAndSuspend(BrowsingContextGroup* aGroup) { + if (aGroup) { + SuppressBrowsingContextGroup(aGroup); + } + } + + ~AutoSuppressEventHandlingAndSuspend(); + + protected: + void SuppressDocument(Document* aDocument) override; + + private: + AutoTArray, 16> mWindows; +}; +} // namespace mozilla::dom + +#endif diff --git a/dom/base/AutocompleteFieldList.h b/dom/base/AutocompleteFieldList.h new file mode 100644 index 0000000000..5796596f7f --- /dev/null +++ b/dom/base/AutocompleteFieldList.h @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * This file contains the list of field names that are used in @autocomplete + * attribute for , +
+
+ +
+
+
+ + + + + + + + +
Table
+ + + diff --git a/dom/base/crashtests/343730-1.xhtml b/dom/base/crashtests/343730-1.xhtml new file mode 100644 index 0000000000..82b5a26a8a --- /dev/null +++ b/dom/base/crashtests/343730-1.xhtml @@ -0,0 +1,35 @@ + + + + + + + + + +
+ + + + diff --git a/dom/base/crashtests/343850-1.xhtml b/dom/base/crashtests/343850-1.xhtml new file mode 100644 index 0000000000..4bf313062d --- /dev/null +++ b/dom/base/crashtests/343850-1.xhtml @@ -0,0 +1,28 @@ + + + + + + + + + +
+ + + diff --git a/dom/base/crashtests/343889-1.html b/dom/base/crashtests/343889-1.html new file mode 100644 index 0000000000..8ea8bc28d3 --- /dev/null +++ b/dom/base/crashtests/343889-1.html @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/dom/base/crashtests/344434-1.xhtml b/dom/base/crashtests/344434-1.xhtml new file mode 100644 index 0000000000..28c5fc0e49 --- /dev/null +++ b/dom/base/crashtests/344434-1.xhtml @@ -0,0 +1,24 @@ + + + + + + + +
A
+ + + diff --git a/dom/base/crashtests/344882-1.html b/dom/base/crashtests/344882-1.html new file mode 100644 index 0000000000..6a8dd69d5b --- /dev/null +++ b/dom/base/crashtests/344882-1.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/dom/base/crashtests/345837-1.xhtml b/dom/base/crashtests/345837-1.xhtml new file mode 100644 index 0000000000..a1f010c5e2 --- /dev/null +++ b/dom/base/crashtests/345837-1.xhtml @@ -0,0 +1,35 @@ + + + + + + + + +
+ +
+ +
+ +
+ + + diff --git a/dom/base/crashtests/346381-1.html b/dom/base/crashtests/346381-1.html new file mode 100644 index 0000000000..4d0263d804 --- /dev/null +++ b/dom/base/crashtests/346381-1.html @@ -0,0 +1,16 @@ + + + + + + + +

Loading this page should not make Firefox leak DOMWindows or documents.

+ +
+ +
+ + + + diff --git a/dom/base/crashtests/349355-1.html b/dom/base/crashtests/349355-1.html new file mode 100644 index 0000000000..627bdc6d61 --- /dev/null +++ b/dom/base/crashtests/349355-1.html @@ -0,0 +1,41 @@ + + + + + + + + +
+ +
+
+
+
+
+ + + + +
+
+ +
+
+
+ +
+ + + + + diff --git a/dom/base/crashtests/359432-1.xhtml b/dom/base/crashtests/359432-1.xhtml new file mode 100644 index 0000000000..391a4d1622 --- /dev/null +++ b/dom/base/crashtests/359432-1.xhtml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/dom/base/crashtests/360599-1.html b/dom/base/crashtests/360599-1.html new file mode 100644 index 0000000000..c090088c0f --- /dev/null +++ b/dom/base/crashtests/360599-1.html @@ -0,0 +1,25 @@ + + + +Testcase bug 360599 - Crash [@ nsFrameList::DestroyFrames] with first-letter/first-line css and position: fixed + + +This page should not crash Mozilla +
+ +
+ + text +
+ y +
+
+
+ + + + + \ No newline at end of file diff --git a/dom/base/crashtests/366200-1.xhtml b/dom/base/crashtests/366200-1.xhtml new file mode 100644 index 0000000000..a604990cf6 --- /dev/null +++ b/dom/base/crashtests/366200-1.xhtml @@ -0,0 +1,34 @@ + + + + + + + +

This text will disappear. There should be no assertions.

+ + diff --git a/dom/base/crashtests/369219-1.xhtml b/dom/base/crashtests/369219-1.xhtml new file mode 100644 index 0000000000..b44242d262 --- /dev/null +++ b/dom/base/crashtests/369219-1.xhtml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/dom/base/crashtests/369413-1.html b/dom/base/crashtests/369413-1.html new file mode 100644 index 0000000000..4fc3b7dfcc --- /dev/null +++ b/dom/base/crashtests/369413-1.html @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dom/base/crashtests/371124-1-inner.html b/dom/base/crashtests/371124-1-inner.html new file mode 100644 index 0000000000..d8fb45519d --- /dev/null +++ b/dom/base/crashtests/371124-1-inner.html @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dom/base/crashtests/371124-1.html b/dom/base/crashtests/371124-1.html new file mode 100644 index 0000000000..ccefd3a324 --- /dev/null +++ b/dom/base/crashtests/371124-1.html @@ -0,0 +1,9 @@ + + + + + + + diff --git a/dom/base/crashtests/371124-2-inner.html b/dom/base/crashtests/371124-2-inner.html new file mode 100644 index 0000000000..7883093822 --- /dev/null +++ b/dom/base/crashtests/371124-2-inner.html @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/dom/base/crashtests/371124-2.html b/dom/base/crashtests/371124-2.html new file mode 100644 index 0000000000..93897635fa --- /dev/null +++ b/dom/base/crashtests/371124-2.html @@ -0,0 +1,9 @@ + + + + + + + diff --git a/dom/base/crashtests/371466-1.xhtml b/dom/base/crashtests/371466-1.xhtml new file mode 100644 index 0000000000..8da0b22b12 --- /dev/null +++ b/dom/base/crashtests/371466-1.xhtml @@ -0,0 +1,24 @@ + + + + + + + + + +
Foo
+ + + diff --git a/dom/base/crashtests/400763-1.html b/dom/base/crashtests/400763-1.html new file mode 100644 index 0000000000..2de6720908 --- /dev/null +++ b/dom/base/crashtests/400763-1.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/base/crashtests/407818.html b/dom/base/crashtests/407818.html new file mode 100644 index 0000000000..eea475be42 --- /dev/null +++ b/dom/base/crashtests/407818.html @@ -0,0 +1,5 @@ + + + +
+ diff --git a/dom/base/crashtests/410860-1.xml b/dom/base/crashtests/410860-1.xml new file mode 100644 index 0000000000..4a7414fc9b --- /dev/null +++ b/dom/base/crashtests/410860-1.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/dom/base/crashtests/411882-1.xhtml b/dom/base/crashtests/411882-1.xhtml new file mode 100644 index 0000000000..6cd121044f --- /dev/null +++ b/dom/base/crashtests/411882-1.xhtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dom/base/crashtests/416734-1.html b/dom/base/crashtests/416734-1.html new file mode 100644 index 0000000000..69350933c1 --- /dev/null +++ b/dom/base/crashtests/416734-1.html @@ -0,0 +1,13 @@ + + + + + + +X X } + + + + + + diff --git a/dom/base/crashtests/417852-1.html b/dom/base/crashtests/417852-1.html new file mode 100644 index 0000000000..bf8ba34863 --- /dev/null +++ b/dom/base/crashtests/417852-1.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/base/crashtests/418928-1.html b/dom/base/crashtests/418928-1.html new file mode 100644 index 0000000000..a3e42fe6f3 --- /dev/null +++ b/dom/base/crashtests/418928-1.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/dom/base/crashtests/420620-1.html b/dom/base/crashtests/420620-1.html new file mode 100644 index 0000000000..74ae6dcbe3 --- /dev/null +++ b/dom/base/crashtests/420620-1.html @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/dom/base/crashtests/424276-1.html b/dom/base/crashtests/424276-1.html new file mode 100644 index 0000000000..feb39bf33d --- /dev/null +++ b/dom/base/crashtests/424276-1.html @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/dom/base/crashtests/426987-1.html b/dom/base/crashtests/426987-1.html new file mode 100644 index 0000000000..7d277156e1 --- /dev/null +++ b/dom/base/crashtests/426987-1.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/base/crashtests/43040-1.html b/dom/base/crashtests/43040-1.html new file mode 100644 index 0000000000..00165763c4 --- /dev/null +++ b/dom/base/crashtests/43040-1.html @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/dom/base/crashtests/439206-1.html b/dom/base/crashtests/439206-1.html new file mode 100644 index 0000000000..688ebe44d5 --- /dev/null +++ b/dom/base/crashtests/439206-1.html @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/dom/base/crashtests/443538-1.svg b/dom/base/crashtests/443538-1.svg new file mode 100644 index 0000000000..cb7388a7cd --- /dev/null +++ b/dom/base/crashtests/443538-1.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/dom/base/crashtests/448615-1.html b/dom/base/crashtests/448615-1.html new file mode 100644 index 0000000000..bfb4f365a1 --- /dev/null +++ b/dom/base/crashtests/448615-1.html @@ -0,0 +1,13 @@ + + + + + + +
A
+ + diff --git a/dom/base/crashtests/450383-1.html b/dom/base/crashtests/450383-1.html new file mode 100644 index 0000000000..3c95b966ce --- /dev/null +++ b/dom/base/crashtests/450383-1.html @@ -0,0 +1,9 @@ + + + + diff --git a/dom/base/crashtests/450385-1.html b/dom/base/crashtests/450385-1.html new file mode 100644 index 0000000000..e75159c51d --- /dev/null +++ b/dom/base/crashtests/450385-1.html @@ -0,0 +1,11 @@ + + + + diff --git a/dom/base/crashtests/458637-1-inner.xhtml b/dom/base/crashtests/458637-1-inner.xhtml new file mode 100644 index 0000000000..f91d6e5b4c --- /dev/null +++ b/dom/base/crashtests/458637-1-inner.xhtml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dom/base/crashtests/458637-1.html b/dom/base/crashtests/458637-1.html new file mode 100644 index 0000000000..124846fcbe --- /dev/null +++ b/dom/base/crashtests/458637-1.html @@ -0,0 +1,29 @@ + + + + + + + diff --git a/dom/base/crashtests/462947.html b/dom/base/crashtests/462947.html new file mode 100644 index 0000000000..09581b3081 --- /dev/null +++ b/dom/base/crashtests/462947.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/base/crashtests/467392.html b/dom/base/crashtests/467392.html new file mode 100644 index 0000000000..a64044c6ea --- /dev/null +++ b/dom/base/crashtests/467392.html @@ -0,0 +1,4 @@ + diff --git a/dom/base/crashtests/472593-1.html b/dom/base/crashtests/472593-1.html new file mode 100644 index 0000000000..ad8fe34bfa --- /dev/null +++ b/dom/base/crashtests/472593-1.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/base/crashtests/474041-1.svg b/dom/base/crashtests/474041-1.svg new file mode 100644 index 0000000000..2b8351472c --- /dev/null +++ b/dom/base/crashtests/474041-1.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/dom/base/crashtests/476526.html b/dom/base/crashtests/476526.html new file mode 100644 index 0000000000..b3d8f8e1c8 --- /dev/null +++ b/dom/base/crashtests/476526.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/dom/base/crashtests/483818-1.html b/dom/base/crashtests/483818-1.html new file mode 100644 index 0000000000..11cc7c4aca --- /dev/null +++ b/dom/base/crashtests/483818-1.html @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/dom/base/crashtests/490760-1.xhtml b/dom/base/crashtests/490760-1.xhtml new file mode 100644 index 0000000000..988f7c12ba --- /dev/null +++ b/dom/base/crashtests/490760-1.xhtml @@ -0,0 +1,25 @@ + + + + + + diff --git a/dom/base/crashtests/493281-1.html b/dom/base/crashtests/493281-1.html new file mode 100644 index 0000000000..6dd3dd4a15 --- /dev/null +++ b/dom/base/crashtests/493281-1.html @@ -0,0 +1,7 @@ + + +
+ +
+ + diff --git a/dom/base/crashtests/493281-2.html b/dom/base/crashtests/493281-2.html new file mode 100644 index 0000000000..2369624694 --- /dev/null +++ b/dom/base/crashtests/493281-2.html @@ -0,0 +1,12 @@ + + +
+ +
+ + diff --git a/dom/base/crashtests/494810-1.html b/dom/base/crashtests/494810-1.html new file mode 100644 index 0000000000..e0036cd836 --- /dev/null +++ b/dom/base/crashtests/494810-1.html @@ -0,0 +1,15 @@ + + + + + + + diff --git a/dom/base/crashtests/499006-1.html b/dom/base/crashtests/499006-1.html new file mode 100644 index 0000000000..f02720b847 --- /dev/null +++ b/dom/base/crashtests/499006-1.html @@ -0,0 +1,26 @@ + + + + +Hello Kitty + diff --git a/dom/base/crashtests/499006-2.html b/dom/base/crashtests/499006-2.html new file mode 100644 index 0000000000..86907c5bb6 --- /dev/null +++ b/dom/base/crashtests/499006-2.html @@ -0,0 +1,35 @@ + + + + + + + + \ No newline at end of file diff --git a/dom/base/crashtests/502617.html b/dom/base/crashtests/502617.html new file mode 100644 index 0000000000..4d4487817f --- /dev/null +++ b/dom/base/crashtests/502617.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/base/crashtests/504224.html b/dom/base/crashtests/504224.html new file mode 100644 index 0000000000..713085166b --- /dev/null +++ b/dom/base/crashtests/504224.html @@ -0,0 +1,29 @@ + + +Crash [@ nsFocusManager::GetClosestCommonInclusiveAncestor], part 2 + + + + + + + diff --git a/dom/base/crashtests/509536-1.html b/dom/base/crashtests/509536-1.html new file mode 100644 index 0000000000..9881646013 --- /dev/null +++ b/dom/base/crashtests/509536-1.html @@ -0,0 +1,17 @@ + + + + + + + diff --git a/dom/base/crashtests/522516-1.html b/dom/base/crashtests/522516-1.html new file mode 100644 index 0000000000..87891ea198 --- /dev/null +++ b/dom/base/crashtests/522516-1.html @@ -0,0 +1,10 @@ + + + + +
+
+
+ + + diff --git a/dom/base/crashtests/529670.html b/dom/base/crashtests/529670.html new file mode 100644 index 0000000000..52e66ab8c2 --- /dev/null +++ b/dom/base/crashtests/529670.html @@ -0,0 +1,18 @@ + + + + Testcase for bug 529670 + + + + diff --git a/dom/base/crashtests/535926-1.html b/dom/base/crashtests/535926-1.html new file mode 100644 index 0000000000..b59c10cbdd --- /dev/null +++ b/dom/base/crashtests/535926-1.html @@ -0,0 +1,28 @@ + + + + + + + diff --git a/dom/base/crashtests/543645.html b/dom/base/crashtests/543645.html new file mode 100644 index 0000000000..c9b80f4cdf --- /dev/null +++ b/dom/base/crashtests/543645.html @@ -0,0 +1,14 @@ + + diff --git a/dom/base/crashtests/551631-1.html b/dom/base/crashtests/551631-1.html new file mode 100644 index 0000000000..90a84ce584 --- /dev/null +++ b/dom/base/crashtests/551631-1.html @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/dom/base/crashtests/552651.html b/dom/base/crashtests/552651.html new file mode 100644 index 0000000000..7db14f52a4 --- /dev/null +++ b/dom/base/crashtests/552651.html @@ -0,0 +1,25 @@ + + + + Testcase for bug 552651 + + + +This test should not leak... + + + diff --git a/dom/base/crashtests/552651.xml b/dom/base/crashtests/552651.xml new file mode 100644 index 0000000000..b04b966cfa --- /dev/null +++ b/dom/base/crashtests/552651.xml @@ -0,0 +1,2 @@ +test + diff --git a/dom/base/crashtests/554230-1.xhtml b/dom/base/crashtests/554230-1.xhtml new file mode 100644 index 0000000000..28801ccfa4 --- /dev/null +++ b/dom/base/crashtests/554230-1.xhtml @@ -0,0 +1,15 @@ + diff --git a/dom/base/crashtests/558973.html b/dom/base/crashtests/558973.html new file mode 100644 index 0000000000..878b8c9259 --- /dev/null +++ b/dom/base/crashtests/558973.html @@ -0,0 +1,17 @@ + + + + + + diff --git a/dom/base/crashtests/564079-1.html b/dom/base/crashtests/564079-1.html new file mode 100644 index 0000000000..1c97ff9677 --- /dev/null +++ b/dom/base/crashtests/564079-1.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/dom/base/crashtests/564114.html b/dom/base/crashtests/564114.html new file mode 100644 index 0000000000..93786e2221 --- /dev/null +++ b/dom/base/crashtests/564114.html @@ -0,0 +1,11 @@ + + + + + + + diff --git a/dom/base/crashtests/565125-1.html b/dom/base/crashtests/565125-1.html new file mode 100644 index 0000000000..ceeb923f4c --- /dev/null +++ b/dom/base/crashtests/565125-1.html @@ -0,0 +1,27 @@ + + + + + + + diff --git a/dom/base/crashtests/575462.svg b/dom/base/crashtests/575462.svg new file mode 100644 index 0000000000..8131d5f1fd --- /dev/null +++ b/dom/base/crashtests/575462.svg @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/dom/base/crashtests/582601.html b/dom/base/crashtests/582601.html new file mode 100644 index 0000000000..4fb854a42c --- /dev/null +++ b/dom/base/crashtests/582601.html @@ -0,0 +1,12 @@ + + + Crashtest + + + + + + diff --git a/dom/base/crashtests/590395-1.html b/dom/base/crashtests/590395-1.html new file mode 100644 index 0000000000..3b653c5e71 --- /dev/null +++ b/dom/base/crashtests/590395-1.html @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/base/crashtests/593302-2.html b/dom/base/crashtests/593302-2.html new file mode 100644 index 0000000000..60e77d4881 --- /dev/null +++ b/dom/base/crashtests/593302-2.html @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dom/base/crashtests/595606-1.html b/dom/base/crashtests/595606-1.html new file mode 100644 index 0000000000..82cae26363 --- /dev/null +++ b/dom/base/crashtests/595606-1.html @@ -0,0 +1,17 @@ + + + + +
+
+
+ + +
+
+ + + + diff --git a/dom/base/crashtests/595606-2.html b/dom/base/crashtests/595606-2.html new file mode 100644 index 0000000000..3cab264c0d --- /dev/null +++ b/dom/base/crashtests/595606-2.html @@ -0,0 +1,18 @@ + + + + +
+
+ + +
+ + +
+ + + + diff --git a/dom/base/crashtests/601247.html b/dom/base/crashtests/601247.html new file mode 100644 index 0000000000..6eb9f46574 --- /dev/null +++ b/dom/base/crashtests/601247.html @@ -0,0 +1,8 @@ + + diff --git a/dom/base/crashtests/603531.html b/dom/base/crashtests/603531.html new file mode 100644 index 0000000000..8243e462e1 --- /dev/null +++ b/dom/base/crashtests/603531.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/dom/base/crashtests/604262-1.html b/dom/base/crashtests/604262-1.html new file mode 100644 index 0000000000..4ece25e855 --- /dev/null +++ b/dom/base/crashtests/604262-1.html @@ -0,0 +1,8 @@ + + diff --git a/dom/base/crashtests/605672-1.svg b/dom/base/crashtests/605672-1.svg new file mode 100644 index 0000000000..b929b26691 --- /dev/null +++ b/dom/base/crashtests/605672-1.svg @@ -0,0 +1,17 @@ + + + + + diff --git a/dom/base/crashtests/606729-1.html b/dom/base/crashtests/606729-1.html new file mode 100644 index 0000000000..c81479c20b --- /dev/null +++ b/dom/base/crashtests/606729-1.html @@ -0,0 +1 @@ + diff --git a/dom/base/crashtests/607222.html b/dom/base/crashtests/607222.html new file mode 100644 index 0000000000..a9491b3429 --- /dev/null +++ b/dom/base/crashtests/607222.html @@ -0,0 +1,21 @@ + + + + + diff --git a/dom/base/crashtests/609560-1.xhtml b/dom/base/crashtests/609560-1.xhtml new file mode 100644 index 0000000000..7849c8db73 --- /dev/null +++ b/dom/base/crashtests/609560-1.xhtml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/dom/base/crashtests/610571-1.html b/dom/base/crashtests/610571-1.html new file mode 100644 index 0000000000..96dbc22719 --- /dev/null +++ b/dom/base/crashtests/610571-1.html @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/dom/base/crashtests/612018-1.html b/dom/base/crashtests/612018-1.html new file mode 100644 index 0000000000..7f81422a71 --- /dev/null +++ b/dom/base/crashtests/612018-1.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/dom/base/crashtests/628599-1.html b/dom/base/crashtests/628599-1.html new file mode 100644 index 0000000000..09be38f1e0 --- /dev/null +++ b/dom/base/crashtests/628599-1.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/dom/base/crashtests/637116.html b/dom/base/crashtests/637116.html new file mode 100644 index 0000000000..422cbe7360 --- /dev/null +++ b/dom/base/crashtests/637116.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/dom/base/crashtests/637214-1.svg b/dom/base/crashtests/637214-1.svg new file mode 100644 index 0000000000..106428a297 --- /dev/null +++ b/dom/base/crashtests/637214-1.svg @@ -0,0 +1,26 @@ + + + + + + + + Text + Text + + + + + diff --git a/dom/base/crashtests/637214-2.svg b/dom/base/crashtests/637214-2.svg new file mode 100644 index 0000000000..4f5c929277 --- /dev/null +++ b/dom/base/crashtests/637214-2.svg @@ -0,0 +1,26 @@ + + + + + + + + Text + Text + + + + + diff --git a/dom/base/crashtests/642022-1.html b/dom/base/crashtests/642022-1.html new file mode 100644 index 0000000000..b2bc59085f --- /dev/null +++ b/dom/base/crashtests/642022-1.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/646184.html b/dom/base/crashtests/646184.html new file mode 100644 index 0000000000..a4a6ac4907 --- /dev/null +++ b/dom/base/crashtests/646184.html @@ -0,0 +1,17 @@ + + + + + + + diff --git a/dom/base/crashtests/658845-1.svg b/dom/base/crashtests/658845-1.svg new file mode 100644 index 0000000000..40a6a3167c --- /dev/null +++ b/dom/base/crashtests/658845-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/dom/base/crashtests/666869.html b/dom/base/crashtests/666869.html new file mode 100644 index 0000000000..ac11f64e12 --- /dev/null +++ b/dom/base/crashtests/666869.html @@ -0,0 +1,17 @@ + + + + + + + diff --git a/dom/base/crashtests/667336-1.html b/dom/base/crashtests/667336-1.html new file mode 100644 index 0000000000..499f5a9ef0 --- /dev/null +++ b/dom/base/crashtests/667336-1.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/675516.xhtml b/dom/base/crashtests/675516.xhtml new file mode 100644 index 0000000000..0daadf136b --- /dev/null +++ b/dom/base/crashtests/675516.xhtml @@ -0,0 +1,31 @@ + + + + diff --git a/dom/base/crashtests/675621-1.html b/dom/base/crashtests/675621-1.html new file mode 100644 index 0000000000..8f42bfcb7e --- /dev/null +++ b/dom/base/crashtests/675621-1.html @@ -0,0 +1,7 @@ + + + diff --git a/dom/base/crashtests/677194.html b/dom/base/crashtests/677194.html new file mode 100644 index 0000000000..a320219a2f --- /dev/null +++ b/dom/base/crashtests/677194.html @@ -0,0 +1,6 @@ + diff --git a/dom/base/crashtests/679459.html b/dom/base/crashtests/679459.html new file mode 100644 index 0000000000..c3cbb0c7c6 --- /dev/null +++ b/dom/base/crashtests/679459.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/dom/base/crashtests/679689-1.html b/dom/base/crashtests/679689-1.html new file mode 100644 index 0000000000..aab88bbc36 --- /dev/null +++ b/dom/base/crashtests/679689-1.html @@ -0,0 +1,2 @@ + + diff --git a/dom/base/crashtests/682463.html b/dom/base/crashtests/682463.html new file mode 100644 index 0000000000..735979e9fb --- /dev/null +++ b/dom/base/crashtests/682463.html @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/dom/base/crashtests/693212.xhtml b/dom/base/crashtests/693212.xhtml new file mode 100644 index 0000000000..6cc600d3b4 --- /dev/null +++ b/dom/base/crashtests/693212.xhtml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/dom/base/crashtests/693811-1.html b/dom/base/crashtests/693811-1.html new file mode 100644 index 0000000000..e3629fbb24 --- /dev/null +++ b/dom/base/crashtests/693811-1.html @@ -0,0 +1,14 @@ + + diff --git a/dom/base/crashtests/693811-2.html b/dom/base/crashtests/693811-2.html new file mode 100644 index 0000000000..858e66f4f3 --- /dev/null +++ b/dom/base/crashtests/693811-2.html @@ -0,0 +1,16 @@ + + diff --git a/dom/base/crashtests/693811-3.html b/dom/base/crashtests/693811-3.html new file mode 100644 index 0000000000..6e5855e610 --- /dev/null +++ b/dom/base/crashtests/693811-3.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/693894.html b/dom/base/crashtests/693894.html new file mode 100644 index 0000000000..23bf4a9c8e --- /dev/null +++ b/dom/base/crashtests/693894.html @@ -0,0 +1,8 @@ + + diff --git a/dom/base/crashtests/695867.html b/dom/base/crashtests/695867.html new file mode 100644 index 0000000000..4cba753f7b --- /dev/null +++ b/dom/base/crashtests/695867.html @@ -0,0 +1,9 @@ + + diff --git a/dom/base/crashtests/697643.html b/dom/base/crashtests/697643.html new file mode 100644 index 0000000000..093e02ada7 --- /dev/null +++ b/dom/base/crashtests/697643.html @@ -0,0 +1,5 @@ + diff --git a/dom/base/crashtests/698974-1.html b/dom/base/crashtests/698974-1.html new file mode 100644 index 0000000000..b945c9a29f --- /dev/null +++ b/dom/base/crashtests/698974-1.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/700090-1.html b/dom/base/crashtests/700090-1.html new file mode 100644 index 0000000000..30479454f7 --- /dev/null +++ b/dom/base/crashtests/700090-1.html @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/dom/base/crashtests/700090-2.html b/dom/base/crashtests/700090-2.html new file mode 100644 index 0000000000..c6d5eb2114 --- /dev/null +++ b/dom/base/crashtests/700090-2.html @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/dom/base/crashtests/700512-worker.js b/dom/base/crashtests/700512-worker.js new file mode 100644 index 0000000000..fcb558fcf4 --- /dev/null +++ b/dom/base/crashtests/700512-worker.js @@ -0,0 +1,7 @@ +onmessage = function(event) { + var blob = event.data; + + blob.slice(1, 5); + + postMessage("done"); +} diff --git a/dom/base/crashtests/700512.html b/dom/base/crashtests/700512.html new file mode 100644 index 0000000000..49764e62b2 --- /dev/null +++ b/dom/base/crashtests/700512.html @@ -0,0 +1,11 @@ + + + diff --git a/dom/base/crashtests/706283-1.html b/dom/base/crashtests/706283-1.html new file mode 100644 index 0000000000..67b618e7fe --- /dev/null +++ b/dom/base/crashtests/706283-1.html @@ -0,0 +1,6 @@ + + diff --git a/dom/base/crashtests/709384.html b/dom/base/crashtests/709384.html new file mode 100644 index 0000000000..5e99e9c3c6 --- /dev/null +++ b/dom/base/crashtests/709384.html @@ -0,0 +1,5 @@ + + diff --git a/dom/base/crashtests/709954.html b/dom/base/crashtests/709954.html new file mode 100644 index 0000000000..a06b7715ec --- /dev/null +++ b/dom/base/crashtests/709954.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/dom/base/crashtests/713417-1.html b/dom/base/crashtests/713417-1.html new file mode 100644 index 0000000000..a5bfd0f809 --- /dev/null +++ b/dom/base/crashtests/713417-1.html @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/dom/base/crashtests/713417-2.html b/dom/base/crashtests/713417-2.html new file mode 100644 index 0000000000..8bf33b6b11 --- /dev/null +++ b/dom/base/crashtests/713417-2.html @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/dom/base/crashtests/715056.html b/dom/base/crashtests/715056.html new file mode 100644 index 0000000000..214569b02a --- /dev/null +++ b/dom/base/crashtests/715056.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/dom/base/crashtests/729431-1.xhtml b/dom/base/crashtests/729431-1.xhtml new file mode 100644 index 0000000000..9ff18fc65a --- /dev/null +++ b/dom/base/crashtests/729431-1.xhtml @@ -0,0 +1,36 @@ + + + + + + + diff --git a/dom/base/crashtests/741163-1.html b/dom/base/crashtests/741163-1.html new file mode 100644 index 0000000000..62262a9498 --- /dev/null +++ b/dom/base/crashtests/741163-1.html @@ -0,0 +1,7 @@ + + diff --git a/dom/base/crashtests/745495.html b/dom/base/crashtests/745495.html new file mode 100644 index 0000000000..f513a33a8b --- /dev/null +++ b/dom/base/crashtests/745495.html @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/dom/base/crashtests/752226-1.html b/dom/base/crashtests/752226-1.html new file mode 100644 index 0000000000..9c05388ff2 --- /dev/null +++ b/dom/base/crashtests/752226-1.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/752226-2.html b/dom/base/crashtests/752226-2.html new file mode 100644 index 0000000000..9d0aa1698e --- /dev/null +++ b/dom/base/crashtests/752226-2.html @@ -0,0 +1,4 @@ + + diff --git a/dom/base/crashtests/766426.html b/dom/base/crashtests/766426.html new file mode 100644 index 0000000000..105347b34f --- /dev/null +++ b/dom/base/crashtests/766426.html @@ -0,0 +1,32 @@ + + + + + + +
X
+ + diff --git a/dom/base/crashtests/771639.html b/dom/base/crashtests/771639.html new file mode 100644 index 0000000000..c6124cac51 --- /dev/null +++ b/dom/base/crashtests/771639.html @@ -0,0 +1,16 @@ + + diff --git a/dom/base/crashtests/786854.html b/dom/base/crashtests/786854.html new file mode 100644 index 0000000000..846741c08c --- /dev/null +++ b/dom/base/crashtests/786854.html @@ -0,0 +1,4 @@ + + +
+ diff --git a/dom/base/crashtests/815043.html b/dom/base/crashtests/815043.html new file mode 100644 index 0000000000..d5cdd93598 --- /dev/null +++ b/dom/base/crashtests/815043.html @@ -0,0 +1,8 @@ + + + + +
+ + + diff --git a/dom/base/crashtests/815276.html b/dom/base/crashtests/815276.html new file mode 100644 index 0000000000..8a691d6685 --- /dev/null +++ b/dom/base/crashtests/815276.html @@ -0,0 +1,6 @@ + + + +
x
+ + diff --git a/dom/base/crashtests/815477.html b/dom/base/crashtests/815477.html new file mode 100644 index 0000000000..d3cceb0f9c --- /dev/null +++ b/dom/base/crashtests/815477.html @@ -0,0 +1,15 @@ +
    +7. If no matching font face is within the "font-family" being processed by steps +
+ +

* XHB7R%[+z^NvLp5 n$C +

+> \ No newline at end of file diff --git a/dom/base/crashtests/815500.html b/dom/base/crashtests/815500.html new file mode 100644 index 0000000000..76d3157ee6 --- /dev/null +++ b/dom/base/crashtests/815500.html @@ -0,0 +1,14 @@ +>>

A,*/îˆ^㰞﷑ dq豑>> \ No newline at end of file diff --git a/dom/base/crashtests/816253.html b/dom/base/crashtests/816253.html new file mode 100644 index 0000000000..4381700916 --- /dev/null +++ b/dom/base/crashtests/816253.html @@ -0,0 +1,31 @@ + + + + + + +
+
+
+ Test test test +
+
+ + + + diff --git a/dom/base/crashtests/819014.html b/dom/base/crashtests/819014.html new file mode 100644 index 0000000000..0e7c22c502 --- /dev/null +++ b/dom/base/crashtests/819014.html @@ -0,0 +1,22 @@ + + + + + + +
+ + +
+ + + diff --git a/dom/base/crashtests/822723.html b/dom/base/crashtests/822723.html new file mode 100644 index 0000000000..e057d5b61f --- /dev/null +++ b/dom/base/crashtests/822723.html @@ -0,0 +1,20 @@ + + + + + + + diff --git a/dom/base/crashtests/824719.html b/dom/base/crashtests/824719.html new file mode 100644 index 0000000000..64507ef995 --- /dev/null +++ b/dom/base/crashtests/824719.html @@ -0,0 +1,26 @@ + + +
+
+
+a +
+
+
+
+ + + + + diff --git a/dom/base/crashtests/827190.html b/dom/base/crashtests/827190.html new file mode 100644 index 0000000000..e8bce20cb7 --- /dev/null +++ b/dom/base/crashtests/827190.html @@ -0,0 +1,13 @@ +K \ No newline at end of file diff --git a/dom/base/crashtests/828054.html b/dom/base/crashtests/828054.html new file mode 100644 index 0000000000..ae5b8d35a7 --- /dev/null +++ b/dom/base/crashtests/828054.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/dom/base/crashtests/828903-iframe.html b/dom/base/crashtests/828903-iframe.html new file mode 100644 index 0000000000..dc40c45d66 --- /dev/null +++ b/dom/base/crashtests/828903-iframe.html @@ -0,0 +1,46 @@ + + + + + diff --git a/dom/base/crashtests/828903.html b/dom/base/crashtests/828903.html new file mode 100644 index 0000000000..1a5a4d31fc --- /dev/null +++ b/dom/base/crashtests/828903.html @@ -0,0 +1,28 @@ + + + + Testcase for bug 828903 + + + + + + + + + + + + + + + diff --git a/dom/base/crashtests/829428.html b/dom/base/crashtests/829428.html new file mode 100644 index 0000000000..4cab24d87d --- /dev/null +++ b/dom/base/crashtests/829428.html @@ -0,0 +1,8 @@ + + + + + +
+ + diff --git a/dom/base/crashtests/830098.html b/dom/base/crashtests/830098.html new file mode 100644 index 0000000000..0b563ce956 --- /dev/null +++ b/dom/base/crashtests/830098.html @@ -0,0 +1,14 @@ +

+ + +nt/b|+K E:

+ + ~ N LRWue`N6g J`NfT Ai0 BG q QPX6 ~ #A?ORD + >>> \ No newline at end of file diff --git a/dom/base/crashtests/831287.html b/dom/base/crashtests/831287.html new file mode 100644 index 0000000000..3fc841cc9b --- /dev/null +++ b/dom/base/crashtests/831287.html @@ -0,0 +1,11 @@ +

FAIL (fallback content)

+ +>> \ No newline at end of file diff --git a/dom/base/crashtests/832644.html b/dom/base/crashtests/832644.html new file mode 100644 index 0000000000..41ce1b907c --- /dev/null +++ b/dom/base/crashtests/832644.html @@ -0,0 +1,8 @@ +>
>ohVG l0ci * |X5SEX :GdK5i2rC#sdnwJv0%O{QF Lh>>>
    > \ No newline at end of file diff --git a/dom/base/crashtests/836890.html b/dom/base/crashtests/836890.html new file mode 100644 index 0000000000..a75fa3c45f --- /dev/null +++ b/dom/base/crashtests/836890.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/dom/base/crashtests/838489-1.html b/dom/base/crashtests/838489-1.html new file mode 100644 index 0000000000..c7167c45a8 --- /dev/null +++ b/dom/base/crashtests/838489-1.html @@ -0,0 +1,11 @@ +> +>
    >>> \ No newline at end of file diff --git a/dom/base/crashtests/838489-2.html b/dom/base/crashtests/838489-2.html new file mode 100644 index 0000000000..0f5883436f --- /dev/null +++ b/dom/base/crashtests/838489-2.html @@ -0,0 +1,16 @@ +>> +> \ No newline at end of file diff --git a/dom/base/crashtests/841205.html b/dom/base/crashtests/841205.html new file mode 100644 index 0000000000..4de533a885 --- /dev/null +++ b/dom/base/crashtests/841205.html @@ -0,0 +1,25 @@ + + + + + + + diff --git a/dom/base/crashtests/844404.html b/dom/base/crashtests/844404.html new file mode 100644 index 0000000000..9022837bf2 --- /dev/null +++ b/dom/base/crashtests/844404.html @@ -0,0 +1,23 @@ + + + + + + + + +
    + + + diff --git a/dom/base/crashtests/845093-1.html b/dom/base/crashtests/845093-1.html new file mode 100644 index 0000000000..3ed8efca65 --- /dev/null +++ b/dom/base/crashtests/845093-1.html @@ -0,0 +1,10 @@ + u +> diff --git a/dom/base/crashtests/845093-2.html b/dom/base/crashtests/845093-2.html new file mode 100644 index 0000000000..59262ac4c7 --- /dev/null +++ b/dom/base/crashtests/845093-2.html @@ -0,0 +1,7 @@ +>嵐>>>

    diff --git a/dom/base/crashtests/847127.html b/dom/base/crashtests/847127.html new file mode 100644 index 0000000000..4d78893d87 --- /dev/null +++ b/dom/base/crashtests/847127.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/dom/base/crashtests/849601.html b/dom/base/crashtests/849601.html new file mode 100644 index 0000000000..bc6410d4fa --- /dev/null +++ b/dom/base/crashtests/849601.html @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/dom/base/crashtests/849727.html b/dom/base/crashtests/849727.html new file mode 100644 index 0000000000..8f26365356 --- /dev/null +++ b/dom/base/crashtests/849727.html @@ -0,0 +1,9 @@ +
    >>>>
    w.)+
    >.c34::-moz-page-sequence { outline-color: invert }> \ No newline at end of file diff --git a/dom/base/crashtests/849732.html b/dom/base/crashtests/849732.html new file mode 100644 index 0000000000..150db1ca12 --- /dev/null +++ b/dom/base/crashtests/849732.html @@ -0,0 +1,18 @@ +>+A[]@q +> \ No newline at end of file diff --git a/dom/base/crashtests/851353-1.html b/dom/base/crashtests/851353-1.html new file mode 100644 index 0000000000..2af7de97aa --- /dev/null +++ b/dom/base/crashtests/851353-1.html @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/dom/base/crashtests/852381.html b/dom/base/crashtests/852381.html new file mode 100644 index 0000000000..7e8dd47f81 --- /dev/null +++ b/dom/base/crashtests/852381.html @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/dom/base/crashtests/863950.html b/dom/base/crashtests/863950.html new file mode 100644 index 0000000000..42303a5094 --- /dev/null +++ b/dom/base/crashtests/863950.html @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/dom/base/crashtests/864448.html b/dom/base/crashtests/864448.html new file mode 100644 index 0000000000..fdb1a75ea1 --- /dev/null +++ b/dom/base/crashtests/864448.html @@ -0,0 +1,22 @@ + + + + + + + + +
    + + diff --git a/dom/base/crashtests/886213.html b/dom/base/crashtests/886213.html new file mode 100644 index 0000000000..9cba893f33 --- /dev/null +++ b/dom/base/crashtests/886213.html @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/dom/base/crashtests/898906.html b/dom/base/crashtests/898906.html new file mode 100644 index 0000000000..12f744109c --- /dev/null +++ b/dom/base/crashtests/898906.html @@ -0,0 +1,14 @@ + + + + + + + diff --git a/dom/base/crashtests/90613-1.html b/dom/base/crashtests/90613-1.html new file mode 100644 index 0000000000..de60573cc3 --- /dev/null +++ b/dom/base/crashtests/90613-1.html @@ -0,0 +1,7 @@ + + + + + + diff --git a/dom/base/crashtests/930250.html b/dom/base/crashtests/930250.html new file mode 100644 index 0000000000..cf2c15e9e5 --- /dev/null +++ b/dom/base/crashtests/930250.html @@ -0,0 +1,8 @@ + + + + +

    + + + diff --git a/dom/base/crashtests/942979.html b/dom/base/crashtests/942979.html new file mode 100644 index 0000000000..7faf0092ed --- /dev/null +++ b/dom/base/crashtests/942979.html @@ -0,0 +1,42 @@ + + + + + + diff --git a/dom/base/crashtests/973401.html b/dom/base/crashtests/973401.html new file mode 100644 index 0000000000..070548edd1 --- /dev/null +++ b/dom/base/crashtests/973401.html @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/dom/base/crashtests/978646.html b/dom/base/crashtests/978646.html new file mode 100644 index 0000000000..09274ed16c --- /dev/null +++ b/dom/base/crashtests/978646.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list new file mode 100644 index 0000000000..7260a18878 --- /dev/null +++ b/dom/base/crashtests/crashtests.list @@ -0,0 +1,273 @@ +load 43040-1.html +load 90613-1.html +load 116848-1.html +load 149320-1.html +load 205225-1.html +load 231475-1.html +load 244933-1.html +load 275912-1.html +load 293388-1.html +load 325730-1.html +load 326618-1.html +load 326646-1.html +load 326865-1.html +load 327571-1.html +load 327694.html +load 327695-1.html +load 329481-1.xhtml +load 336381-1.xhtml +load 336715-1.xhtml +load 338391-1.xhtml +load 338674-1.xhtml +load 340733-1.html +load 343730-1.xhtml +load 343850-1.xhtml +load 343889-1.html +load 344434-1.xhtml +load 344882-1.html +load 345837-1.xhtml +load 346381-1.html +load 349355-1.html +load 359432-1.xhtml +load 360599-1.html +load 366200-1.xhtml +load 369219-1.xhtml +load 369413-1.html +load 371124-1.html +load 371124-2.html +load 371466-1.xhtml +load 372554-1.html +load 375399-1.html +load 377360-1.xhtml +load 377960-1.html +load 377960-2.html +load 384663-1.html +load 386000-1.html +load 386794-1.html +load 387460-1.html +load 399712-1.html +load 400763-1.html +load 407818.html +load 410860-1.xml +load 411882-1.xhtml +load 416734-1.html +load 417852-1.html +load 418928-1.html +load 420620-1.html +load 424276-1.html +load 426987-1.html +load 439206-1.html +load 443538-1.svg +load 448615-1.html +load 450383-1.html +load 450385-1.html +load 458637-1.html +load 462947.html +load 467392.html +load 472593-1.html +load 474041-1.svg +load 476526.html +load 483818-1.html +load 490760-1.xhtml +load 493281-1.html +load 493281-2.html +load 494810-1.html +load 499006-1.html +load 499006-2.html +load 502617.html +load 504224.html +load 509536-1.html +load 522516-1.html +load 529670.html +load 535926-1.html +load 543645.html +load 551631-1.html +load 552651.html +load 554230-1.xhtml +load 558973.html +load 564079-1.html +load 564114.html +load 565125-1.html +load 575462.svg +load 582601.html +load 590395-1.html +load 593302-1.html +load 593302-2.html +load 595606-1.html +load 595606-2.html +load 601247.html +load 603531.html +load 604262-1.html +load 605672-1.svg +load 606729-1.html +load 607222.html +load 609560-1.xhtml +load 610571-1.html +load 612018-1.html +load 628599-1.html +load 637116.html +load 637214-1.svg +load 637214-2.svg +pref(extensions.InstallTrigger.enabled,true) pref(extensions.InstallTriggerImpl.enabled,true) load 642022-1.html +load 646184.html +pref(svg.use-element.data-url-href.allowed,true) load 658845-1.svg +load 666869.html +load 667336-1.html +load 675516.xhtml +load 675621-1.html +load 677194.html +load 679459.html +load 679689-1.html +load 682463.html +load 693212.xhtml +load 693811-1.html +load 693811-2.html +load 693811-3.html +load 693894.html +load 695867.html +load 697643.html +load 698974-1.html +load 700090-1.html +load 700090-2.html +load 700512.html +load 706283-1.html +load 709384.html +load 709954.html +load 713417-1.html +load 713417-2.html +load 715056.html +load 729431-1.xhtml +load 741163-1.html +load 745495.html +load 752226-1.html +load 752226-2.html +load 766426.html +load 771639.html +load 786854.html +load 815043.html +load 815276.html +load 815477.html +load 815500.html +load 816253.html +load 819014.html +load 822723.html +load 824719.html +load 827190.html +load 828054.html +load 828903.html +load 829428.html +load 830098.html +load 831287.html +load 832644.html +load 836890.html +load 838489-1.html +load 838489-2.html +load 841205.html +load 844404.html +load 845093-1.html +load 845093-2.html +load 847127.html +load 849601.html +load 849727.html +load 849732.html +load 851353-1.html +load 852381.html +load 863950.html +load 864448.html +load 886213.html +load 898906.html +load 930250.html +load 942979.html +load 973401.html +load 978646.html +load 1024428-1.html +load 1027461-1.html +load 1029710.html +load 1154598.xhtml +load 1157995.html +load 1158412.html +load 1181619.html +load 1228882.html +load 1230422.html +load 1251361.html +load 1281715.html +load 1304437.html +load 1324209.html +load 1324500.html +load 1326194-1.html +load 1326194-2.html +load 1332939.html +load 1341693.html +load 1352453.html +load chrome://reftest/content/crashtests/dom/base/crashtests/1353529.xhtml +load 1368327.html +load chrome://reftest/content/crashtests/dom/base/crashtests/1369363.xhtml +load 1370072.html +pref(clipboard.autocopy,true) load 1370737.html +load 1370968.html +load 1373750.html +load 1377826.html +load 1383478.html +load 1383780.html +pref(clipboard.autocopy,true) load 1385272-1.html +load 1393806.html +load 1396466.html +load 1397795.html +load 1400701.html +load 1403377.html +load 1405771.html +load 1406109-1.html +load 1411473.html +load 1413815.html +load 1419799.html +skip-if(!browserIsRemote) skip-if(geckoview) skip-if(geckoview&&isDebugBuild) skip-if(AddressSanitizer) skip-if(ThreadSanitizer) pref(dom.disable_open_during_load,false) load 1419902.html # skip on non e10s loads, Bug 1419902. Bug 1563013 for GV+WR. Bug 1524493 GV+debug. Bug 1573281 asan +load 1422883.html +load 1428053.html +load 1441029.html +load 1445670.html +load 1449601.html +load 1458016.html +load 1459688.html +load 1460794.html +load 1462548.html +load 1505811.html +load 1505875.html +load 1508845.html +load 1516289.html +load 1516560.html +pref(javascript.options.dynamicImport,true) load 1529203-1.html +skip-if(Android) pref(javascript.options.dynamicImport,true) pref(dom.disable_open_during_load,false) pref(browser.link.open_newwindow,2) load 1529203-2.html +skip-if(Android) pref(dom.disable_open_during_load,false) pref(browser.link.open_newwindow,2) load 1529203-3.html +load 1528675.html +load 1566310.html +skip-if(Android) skip-if(ThreadSanitizer) pref(dom.disable_open_during_load,false) pref(browser.link.open_newwindow,2) load 1588259.html +load structured_clone_container_throws.html +load xhr_empty_datauri.html +load xhr_html_nullresponse.html +asserts(0-1) load 1517025.html # see bug 1666910 for assert +load xhr-with-pagehide-1.html +load 1555786.html +load 1577191.html +load eventSource_invalid_scheme_worker_shutdown.html +load 1291535.html +skip-if(!isDebugBuild||xulRuntime.OS!="Linux") load 1611853.html +load 1619322.html +asserts(0-2) load 1623918.html # May hit an assertion if the element's anonymous tree hasn't been flushed when IMEContentObserver handles focus +load 1656925.html +skip-if(Android) load 1665792.html # Print preview on android doesn't fly +skip-if(ThreadSanitizer) load 1681729.html +skip-if(ThreadSanitizer) load 1693049.html +skip-if(winWidget||Android) pref(print.always_print_silent,true) pref(print.print_to_file,true) pref(print.print_to_filename,"/dev/null") load 1697256.html # Windows seemingly requires pref(print_printer,"Mozilla Save to PDF") but pref() doesn't allow space. Android doesn't support print. +skip-if(ThreadSanitizer||Android) load 1697525.html +skip-if(ThreadSanitizer||Android) load 1712198.html # Mysterious failure that should be investigated (bug 1712866). +skip-if(Android) HTTP load 1728670-1.html +load 1757923.html +load 1766472.html +pref(dom.enable_web_task_scheduling,true) load 1780790.html +load 1700237.html +load 1811939.html +load 1822717.html +load 1835886.html +load 1836824.html +skip-if(Android) load 1838484.html +load 1840191.html diff --git a/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown-worker.js b/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown-worker.js new file mode 100644 index 0000000000..d2e5e9e668 --- /dev/null +++ b/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown-worker.js @@ -0,0 +1,4 @@ +onmessage = function(event) { + close(); + let source = new EventSource(`d:`, {}); +} diff --git a/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown.html b/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown.html new file mode 100644 index 0000000000..731392d83d --- /dev/null +++ b/dom/base/crashtests/eventSource_invalid_scheme_worker_shutdown.html @@ -0,0 +1,36 @@ + + + + + + + diff --git a/dom/base/crashtests/file_504224.html b/dom/base/crashtests/file_504224.html new file mode 100644 index 0000000000..9031ccbfad --- /dev/null +++ b/dom/base/crashtests/file_504224.html @@ -0,0 +1,7 @@ + + + + + diff --git a/dom/base/crashtests/module-with-syntax-error.js b/dom/base/crashtests/module-with-syntax-error.js new file mode 100644 index 0000000000..7edb2fa5bc --- /dev/null +++ b/dom/base/crashtests/module-with-syntax-error.js @@ -0,0 +1 @@ +, diff --git a/dom/base/crashtests/structured_clone_container_throws.html b/dom/base/crashtests/structured_clone_container_throws.html new file mode 100644 index 0000000000..c92c6f4ae1 --- /dev/null +++ b/dom/base/crashtests/structured_clone_container_throws.html @@ -0,0 +1,9 @@ + + diff --git a/dom/base/crashtests/xhr-with-pagehide-1-helper.html b/dom/base/crashtests/xhr-with-pagehide-1-helper.html new file mode 100644 index 0000000000..efac291708 --- /dev/null +++ b/dom/base/crashtests/xhr-with-pagehide-1-helper.html @@ -0,0 +1,21 @@ + + + + + + +initial iframe content + + diff --git a/dom/base/crashtests/xhr-with-pagehide-1.html b/dom/base/crashtests/xhr-with-pagehide-1.html new file mode 100644 index 0000000000..86f074868f --- /dev/null +++ b/dom/base/crashtests/xhr-with-pagehide-1.html @@ -0,0 +1,21 @@ + + + + + Crashtest to make sure that a sync XHR during pageload doesn't prevent + pagehide event from firing. + + + + + + + diff --git a/dom/base/crashtests/xhr_empty_datauri.html b/dom/base/crashtests/xhr_empty_datauri.html new file mode 100644 index 0000000000..77988cfe24 --- /dev/null +++ b/dom/base/crashtests/xhr_empty_datauri.html @@ -0,0 +1,5 @@ + + + diff --git a/dom/base/crashtests/xhr_html_nullresponse.html b/dom/base/crashtests/xhr_html_nullresponse.html new file mode 100644 index 0000000000..47c85db9bf --- /dev/null +++ b/dom/base/crashtests/xhr_html_nullresponse.html @@ -0,0 +1,5 @@ + + + diff --git a/dom/base/domerr.msg b/dom/base/domerr.msg new file mode 100644 index 0000000000..d506fb5ce2 --- /dev/null +++ b/dom/base/domerr.msg @@ -0,0 +1,137 @@ +/* -*- 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/. */ + +/* Error Message definitions. */ + + +/* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */ + +DOM4_MSG_DEF(IndexSizeError, "Index or size is negative or greater than the allowed amount", NS_ERROR_DOM_INDEX_SIZE_ERR) +DOM4_MSG_DEF(HierarchyRequestError, "Node cannot be inserted at the specified point in the hierarchy", NS_ERROR_DOM_HIERARCHY_REQUEST_ERR) +DOM4_MSG_DEF(WrongDocumentError, "Node cannot be used in a document other than the one in which it was created", NS_ERROR_DOM_WRONG_DOCUMENT_ERR) +DOM4_MSG_DEF(InvalidCharacterError, "String contains an invalid character", NS_ERROR_DOM_INVALID_CHARACTER_ERR) +DOM4_MSG_DEF(NoModificationAllowedError, "Modifications are not allowed for this document", NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR) +DOM4_MSG_DEF(NotFoundError, "Node was not found", NS_ERROR_DOM_NOT_FOUND_ERR) +DOM4_MSG_DEF(NotSupportedError, "Operation is not supported", NS_ERROR_DOM_NOT_SUPPORTED_ERR) +DOM4_MSG_DEF(InUseAttributeError, "Attribute already in use", NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR) +DOM4_MSG_DEF(InvalidStateError, "An attempt was made to use an object that is not, or is no longer, usable", NS_ERROR_DOM_INVALID_STATE_ERR) +DOM4_MSG_DEF(SyntaxError, "An invalid or illegal string was specified", NS_ERROR_DOM_SYNTAX_ERR) +DOM4_MSG_DEF(InvalidModificationError, "An attempt was made to modify the type of the underlying objec", NS_ERROR_DOM_INVALID_MODIFICATION_ERR) +DOM4_MSG_DEF(NamespaceError, "An attempt was made to create or change an object in a way which is incorrect with regard to namespaces", NS_ERROR_DOM_NAMESPACE_ERR) +DOM4_MSG_DEF(InvalidAccessError, "A parameter or an operation is not supported by the underlying object", NS_ERROR_DOM_INVALID_ACCESS_ERR) +DOM4_MSG_DEF(TypeMismatchError, "The type of an object is incompatible with the expected type of the parameter associated to the object", NS_ERROR_DOM_TYPE_MISMATCH_ERR) +DOM4_MSG_DEF(SecurityError, "The operation is insecure.", NS_ERROR_DOM_SECURITY_ERR) +DOM4_MSG_DEF(NetworkError, "A network error occurred.", NS_ERROR_DOM_NETWORK_ERR) +DOM4_MSG_DEF(AbortError, "The operation was aborted. ", NS_ERROR_DOM_ABORT_ERR) +DOM4_MSG_DEF(URLMismatchError, "The given URL does not match another URL.", NS_ERROR_DOM_URL_MISMATCH_ERR) +DOM4_MSG_DEF(QuotaExceededError, "The quota has been exceeded.", NS_ERROR_DOM_QUOTA_EXCEEDED_ERR) +DOM4_MSG_DEF(TimeoutError, "The operation timed out.", NS_ERROR_DOM_TIMEOUT_ERR) +DOM4_MSG_DEF(InvalidNodeTypeError, "The supplied node is incorrect or has an incorrect ancestor for this operation.", NS_ERROR_DOM_INVALID_NODE_TYPE_ERR) +DOM4_MSG_DEF(DataCloneError, "The object could not be cloned.", NS_ERROR_DOM_DATA_CLONE_ERR) +DOM4_MSG_DEF(NotAllowedError, "The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_NOT_ALLOWED_ERR) + +/* StringEncoding API errors from http://wiki.whatwg.org/wiki/StringEncoding */ +DOM4_MSG_DEF(EncodingError, "The given encoding is not supported.", NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR) + +/* WebCrypto API errors from http://www.w3.org/TR/WebCryptoAPI/ */ +DOM4_MSG_DEF(UnknownError, "The operation failed for an unknown transient reason", NS_ERROR_DOM_UNKNOWN_ERR) +DOM4_MSG_DEF(DataError, "Data provided to an operation does not meet requirements", NS_ERROR_DOM_DATA_ERR) +DOM4_MSG_DEF(OperationError, "The operation failed for an operation-specific reason", NS_ERROR_DOM_OPERATION_ERR) + +/* Media API extra messages for QuotaExceededError */ +DOM4_MSG_DEF(QuotaExceededError, "MediaKeys object is already bound to another HTMLMediaElement.", NS_ERROR_DOM_MEDIA_KEY_QUOTA_EXCEEDED_ERR) +DOM4_MSG_DEF(QuotaExceededError, "Too many SourceBuffer objects created for a single MediaSource object.", NS_ERROR_DOM_MEDIA_SOURCE_MAX_BUFFER_QUOTA_EXCEEDED_ERR) +DOM4_MSG_DEF(QuotaExceededError, "MediaSource buffer not sufficient.", NS_ERROR_DOM_MEDIA_SOURCE_FULL_BUFFER_QUOTA_EXCEEDED_ERR) + +/* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */ + +DOM4_MSG_DEF(UnknownError, "The operation failed for reasons unrelated to the database itself and not covered by any other error code.", NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR) +DOM4_MSG_DEF(ConstraintError, "A mutation operation in the transaction failed because a constraint was not satisfied.", NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR) +DOM4_MSG_DEF(ConstraintError, "Object store renamed to an already existing object store.", NS_ERROR_DOM_INDEXEDDB_RENAME_OBJECT_STORE_ERR) +DOM4_MSG_DEF(ConstraintError, "Index already exists and a new one was being attempted to be created.", NS_ERROR_DOM_INDEXEDDB_RENAME_INDEX_ERR) +DOM4_MSG_DEF(DataError, "Data provided to an operation does not meet requirements.", NS_ERROR_DOM_INDEXEDDB_DATA_ERR) +DOM4_MSG_DEF(DataError, "No valid key or key range specified.", NS_ERROR_DOM_INDEXEDDB_KEY_ERR) +DOM4_MSG_DEF(TransactionInactiveError, "A request was placed against a transaction which is currently not active, or which is finished.", NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR) +DOM4_MSG_DEF(ReadOnlyError, "A mutation operation was attempted in a READ_ONLY transaction.", NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR) +DOM4_MSG_DEF(VersionError, "The operation failed because the stored database is a higher version than the version requested.", NS_ERROR_DOM_INDEXEDDB_VERSION_ERR) + +DOM4_MSG_DEF(NotFoundError, "The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.", NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR) +DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a database that did not allow mutations.", NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR) +DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to IDBTransaction.abort.", NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) +DOM4_MSG_DEF(QuotaExceededError, "The current transaction exceeded its quota limitations.", NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR) + +/* FileSystem DOM errors. */ +DOM4_MSG_DEF(InvalidAccessError, "Invalid file system path.", NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR) +DOM4_MSG_DEF(InvalidModificationError, "Failed to modify the file.", NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR) +DOM4_MSG_DEF(NoModificationAllowedError, "Modifications are not allowed for this file", NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR) +DOM4_MSG_DEF(AbortError, "File already exists.", NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR) +DOM4_MSG_DEF(TypeMismatchError, "The type of the file is incompatible with the expected type.", NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR) +DOM4_MSG_DEF(UnknownError, "The operation failed for reasons unrelated to the file system itself and not covered by any other error code.", NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR) + +/* DOM error codes defined by us */ + +DOM_MSG_DEF(NS_ERROR_DOM_WRONG_TYPE_ERR, "Object is of wrong type") +DOM_MSG_DEF(NS_ERROR_DOM_NOT_NUMBER_ERR, "Parameter is not a number") +DOM_MSG_DEF(NS_ERROR_DOM_PROP_ACCESS_DENIED, "Access to property denied") +DOM_MSG_DEF(NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED, "Access to XPConnect service denied") +DOM_MSG_DEF(NS_ERROR_DOM_BAD_URI, "Access to restricted URI denied") +DOM_MSG_DEF(NS_ERROR_DOM_RETVAL_UNDEFINED, "Return value is undefined") + +DOM4_MSG_DEF(NotFoundError, "File was not found", NS_ERROR_DOM_FILE_NOT_FOUND_ERR) +DOM4_MSG_DEF(NotReadableError, "File could not be read", NS_ERROR_DOM_FILE_NOT_READABLE_ERR) + +/* common global codes (from nsError.h) */ + +DOM_MSG_DEF(NS_OK , "Success") +DOM_MSG_DEF(NS_ERROR_NOT_INITIALIZED , "Component not initialized") +DOM_MSG_DEF(NS_ERROR_ALREADY_INITIALIZED , "Component already initialized") +DOM_MSG_DEF(NS_ERROR_NOT_IMPLEMENTED , "Method not implemented") +DOM_MSG_DEF(NS_NOINTERFACE , "Component does not have requested interface") +DOM_MSG_DEF(NS_ERROR_NO_INTERFACE , "Component does not have requested interface") +DOM_MSG_DEF(NS_ERROR_INVALID_POINTER , "Invalid pointer") +DOM_MSG_DEF(NS_ERROR_NULL_POINTER , "Null pointer") +DOM_MSG_DEF(NS_ERROR_ABORT , "Abort") +DOM_MSG_DEF(NS_ERROR_FAILURE , "Failure") +DOM_MSG_DEF(NS_ERROR_UNEXPECTED , "Unexpected error") +DOM_MSG_DEF(NS_ERROR_OUT_OF_MEMORY , "Out of Memory") +DOM_MSG_DEF(NS_ERROR_ILLEGAL_VALUE , "Illegal value") +DOM_MSG_DEF(NS_ERROR_INVALID_ARG , "Invalid argument") +DOM_MSG_DEF(NS_ERROR_NOT_AVAILABLE , "Component is not available") +DOM_MSG_DEF(NS_ERROR_FACTORY_NOT_REGISTERED , "Factory not registered") +DOM_MSG_DEF(NS_ERROR_FACTORY_NOT_LOADED , "Factory not loaded") +DOM_MSG_DEF(NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT , "Factory does not support signatures") +DOM_MSG_DEF(NS_ERROR_FACTORY_EXISTS , "Factory already exists") + +DOM4_MSG_DEF(UnknownError, "The operation failed for reasons unrelated to the file storage itself and not covered by any other error code.", NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR) +DOM4_MSG_DEF(FileHandleInactiveError, "A request was placed against a file handle which is currently not active, or which is finished.", NS_ERROR_DOM_FILEHANDLE_INACTIVE_ERR) +DOM4_MSG_DEF(ReadOnlyError, "A mutation operation was attempted in a READ_ONLY file handle.", NS_ERROR_DOM_FILEHANDLE_READ_ONLY_ERR) + +DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a file storage that did not allow mutations.", NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR) +DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to FileHandle.abort.", NS_ERROR_DOM_FILEHANDLE_ABORT_ERR) +DOM4_MSG_DEF(QuotaExceededError, "The current file handle exceeded its quota limitations.", NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR) + +/* Push API errors. */ +DOM4_MSG_DEF(NotAllowedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR) +DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR) +DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE) +DOM4_MSG_DEF(InvalidAccessError, "Invalid raw ECDSA P-256 public key.", NS_ERROR_DOM_PUSH_INVALID_KEY_ERR) +DOM4_MSG_DEF(InvalidStateError, "A subscription with a different application server key already exists.", NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR) + +/* Media errors */ +DOM4_MSG_DEF(AbortError, "The fetching process for the media resource was aborted by the user agent at the user's request.", NS_ERROR_DOM_MEDIA_ABORT_ERR) +DOM4_MSG_DEF(NotAllowedError, "The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR) +DOM4_MSG_DEF(NotSupportedError, "The media resource indicated by the src attribute or assigned media provider object was not suitable.", NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR) + +DOM4_MSG_DEF(SyntaxError, "The URI is malformed.", NS_ERROR_DOM_MALFORMED_URI) +DOM4_MSG_DEF(SyntaxError, "Invalid header name.", NS_ERROR_DOM_INVALID_HEADER_NAME) +DOM4_MSG_DEF(SyntaxError, "Invalid header value.", NS_ERROR_DOM_INVALID_HEADER_VALUE) + +/* XMLHttpRequest errors. */ +DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest has an invalid context.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT) + +/* Image decode errors. */ +DOM4_MSG_DEF(EncodingError, "Node bound to inactive document.", NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT) +DOM4_MSG_DEF(EncodingError, "Invalid image request.", NS_ERROR_DOM_IMAGE_INVALID_REQUEST) +DOM4_MSG_DEF(EncodingError, "Invalid encoded image data.", NS_ERROR_DOM_IMAGE_BROKEN) diff --git a/dom/base/fuzztest/FuzzStructuredClone.cpp b/dom/base/fuzztest/FuzzStructuredClone.cpp new file mode 100644 index 0000000000..5473df2c8e --- /dev/null +++ b/dom/base/fuzztest/FuzzStructuredClone.cpp @@ -0,0 +1,70 @@ +/* -*- 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 "FuzzingInterface.h" + +#include "jsapi.h" +#include "js/StructuredClone.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/StructuredCloneHolder.h" +#include "mozilla/dom/SimpleGlobalObject.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/ScopeExit.h" +#include "mozilla/UniquePtr.h" + +#include "nsCycleCollector.h" + +using namespace mozilla; +using namespace mozilla::dom; +using namespace mozilla::dom::ipc; + +JS::PersistentRooted global; + +static int FuzzingInitDomSC(int* argc, char*** argv) { + JSObject* simpleGlobal = + SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail); + global.init(mozilla::dom::RootingCx()); + global.set(simpleGlobal); + return 0; +} + +static int FuzzingRunDomSC(const uint8_t* data, size_t size) { + if (size < 8) { + return 0; + } + + AutoJSAPI jsapi; + MOZ_RELEASE_ASSERT(jsapi.Init(global)); + + JSContext* cx = jsapi.cx(); + auto gcGuard = mozilla::MakeScopeExit([&] { + JS::PrepareForFullGC(cx); + JS::NonIncrementalGC(cx, JS::GCOptions::Normal, JS::GCReason::API); + nsCycleCollector_collect(CCReason::API, nullptr); + }); + + // The internals of SCInput have a release assert about the padding + // of the data, so we fix it here to avoid performance problems + // during fuzzing. + size -= size % 8; + + StructuredCloneData scdata; + if (!scdata.CopyExternalData(reinterpret_cast(data), size)) { + return 0; + } + + JS::Rooted result(cx); + ErrorResult rv; + scdata.Read(cx, &result, rv); + + rv.SuppressException(); + + return 0; +} + +MOZ_FUZZING_INTERFACE_RAW(FuzzingInitDomSC, FuzzingRunDomSC, + StructuredCloneReaderDOM); diff --git a/dom/base/fuzztest/moz.build b/dom/base/fuzztest/moz.build new file mode 100644 index 0000000000..f2d65a3a8d --- /dev/null +++ b/dom/base/fuzztest/moz.build @@ -0,0 +1,23 @@ +# -*- 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/. + +Library("FuzzingDomBase") + +SOURCES += [ + "FuzzStructuredClone.cpp", +] + +LOCAL_INCLUDES += [ + "/dom/base", + "/dom/ipc", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +# Add libFuzzer configuration directives +include("/tools/fuzzing/libfuzzer-config.mozbuild") + +FINAL_LIBRARY = "xul-gtest" diff --git a/dom/base/gen-usecounters.py b/dom/base/gen-usecounters.py new file mode 100755 index 0000000000..bd0dba7b0b --- /dev/null +++ b/dom/base/gen-usecounters.py @@ -0,0 +1,74 @@ +#!/usr/bin/env 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/. + +import os +import sys + +sys.path.append(os.path.dirname(__file__)) + +import usecounters + +AUTOGENERATED_WARNING_COMMENT = ( + "/* THIS FILE IS AUTOGENERATED BY gen-usecounters.py - DO NOT EDIT */" +) + + +def generate_list(f, counters): + def print_optional_macro_declare(name): + print( + """ +#ifndef %(name)s +#define %(name)s(interface_, name_) // nothing +#define DEFINED_%(name)s +#endif +""" + % {"name": name}, + file=f, + ) + + def print_optional_macro_undeclare(name): + print( + """ +#ifdef DEFINED_%(name)s +#undef DEFINED_%(name)s +#undef %(name)s +#endif +""" + % {"name": name}, + file=f, + ) + + print(AUTOGENERATED_WARNING_COMMENT, file=f) + + print_optional_macro_declare("USE_COUNTER_DOM_METHOD") + print_optional_macro_declare("USE_COUNTER_DOM_ATTRIBUTE") + print_optional_macro_declare("USE_COUNTER_CUSTOM") + + for counter in counters: + if counter["type"] == "method": + print( + "USE_COUNTER_DOM_METHOD(%s, %s)" + % (counter["interface_name"], counter["method_name"]), + file=f, + ) + elif counter["type"] == "attribute": + print( + "USE_COUNTER_DOM_ATTRIBUTE(%s, %s)" + % (counter["interface_name"], counter["attribute_name"]), + file=f, + ) + elif counter["type"] == "custom": + desc = counter["desc"].replace("\\", r"\\").replace('"', r"\"") + print('USE_COUNTER_CUSTOM(%s, "%s")' % (counter["name"], desc), file=f) + + print_optional_macro_undeclare("USE_COUNTER_DOM_METHOD") + print_optional_macro_undeclare("USE_COUNTER_DOM_ATTRIBUTE") + print_optional_macro_undeclare("USE_COUNTER_CUSTOM") + + +def use_counter_list(output_header, conf_filename): + counters = usecounters.read_conf(conf_filename) + generate_list(output_header, counters) diff --git a/dom/base/mach_commands.py b/dom/base/mach_commands.py new file mode 100644 index 0000000000..333d187b51 --- /dev/null +++ b/dom/base/mach_commands.py @@ -0,0 +1,21 @@ +# 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/. + +from mach.decorators import Command + + +@Command( + "gen-use-counter-metrics", + category="misc", + description="Generate a Glean use_counter_metrics.yaml file, creating metrics definitions for every use counter.", +) +def gen_use_counter_metrics(command_context): + # Dispatch to usecounters.py + import sys + from os import path + + sys.path.append(path.dirname(__file__)) + from usecounters import gen_use_counter_metrics + + return gen_use_counter_metrics() diff --git a/dom/base/moz.build b/dom/base/moz.build new file mode 100644 index 0000000000..14c9f9dd96 --- /dev/null +++ b/dom/base/moz.build @@ -0,0 +1,634 @@ +# -*- 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/. + +with Files("*Selection*"): + BUG_COMPONENT = ("Core", "DOM: Selection") + +with Files("**"): + BUG_COMPONENT = ("Core", "DOM: Core & HTML") + +TEST_DIRS += ["test"] + +if CONFIG["FUZZING"]: + if CONFIG["FUZZING_INTERFACES"]: + TEST_DIRS += ["fuzztest"] + +# Add libFuzzer configuration directives +include("/tools/fuzzing/libfuzzer-config.mozbuild") + +XPIDL_SOURCES += [ + "mozIDOMWindow.idl", + "nsIContentPolicy.idl", + "nsIDOMRequestService.idl", + "nsIDroppedLinkHandler.idl", + "nsIEventSourceEventService.idl", + "nsIImageLoadingContent.idl", + "nsIMessageManager.idl", + "nsIObjectLoadingContent.idl", + "nsIScriptableContentIterator.idl", + "nsIScriptChannel.idl", + "nsISelectionController.idl", + "nsISelectionDisplay.idl", + "nsISelectionListener.idl", + "nsISlowScriptDebug.idl", +] + +XPIDL_MODULE = "dom" + +EXPORTS += [ + "AttrArray.h", + "AutocompleteFieldList.h", + "Crypto.h", + "HTMLSplitOnSpacesTokenizer.h", + "IframeSandboxKeywordList.h", + "mozAutoDocUpdate.h", + "NodeUbiReporting.h", + "nsAttrName.h", + "nsAttrValue.h", + "nsAttrValueInlines.h", + "nsCaseTreatment.h", + "nsChildContentList.h", + "nsContentCID.h", + "nsContentCreatorFunctions.h", + "nsContentList.h", + "nsContentListDeclarations.h", + "nsContentPermissionHelper.h", + "nsContentPolicyUtils.h", + "nsContentSink.h", + "nsContentTypeParser.h", + "nsContentUtils.h", + "nsCopySupport.h", + "nsDeprecatedOperationList.h", + "nsDocElementCreatedNotificationRunner.h", + "nsDocumentWarningList.h", + "nsDOMAttributeMap.h", + "nsDOMCID.h", + "nsDOMJSUtils.h", + "nsDOMMutationObserver.h", + "nsDOMNavigationTiming.h", + "nsDOMString.h", + "nsDOMTokenList.h", + "nsFocusManager.h", + "nsFrameLoader.h", # Because binding headers include it. + "nsFrameLoaderOwner.h", + "nsFrameMessageManager.h", + "nsGlobalWindowInner.h", # Because binding headers include it. + "nsGlobalWindowOuter.h", # Because binding headers include it. + "nsIAnimationObserver.h", + "nsIContent.h", + "nsIContentInlines.h", + "nsIDocumentObserver.h", + "nsIGlobalObject.h", + "nsImageLoadingContent.h", + "nsIMutationObserver.h", + "nsINode.h", + "nsINodeList.h", + "nsIScriptContext.h", + "nsIScriptGlobalObject.h", + "nsIScriptObjectPrincipal.h", + "nsJSEnvironment.h", + "nsJSUtils.h", + "nsLineBreaker.h", + "nsNameSpaceManager.h", + "nsNodeInfoManager.h", + "nsPIDOMWindow.h", + "nsPIDOMWindowInlines.h", + "nsPIWindowRoot.h", + "nsPropertyTable.h", + "nsRange.h", + "nsSandboxFlags.h", + "nsStructuredCloneContainer.h", + "nsStubAnimationObserver.h", + "nsStubDocumentObserver.h", + "nsStubMutationObserver.h", + "nsStyledElement.h", + "nsTextFragment.h", + "nsTextNode.h", + "nsTraversal.h", + "nsTreeSanitizer.h", + "nsViewportInfo.h", + "nsWindowMemoryReporter.h", + "nsWindowSizes.h", + "nsWrapperCache.h", + "nsWrapperCacheInlines.h", + "XPathGenerator.h", +] + +if CONFIG["MOZ_WEBRTC"]: + EXPORTS += [ + "nsDOMDataChannel.h", + "nsDOMDataChannelDeclarations.h", + ] + +EXPORTS.mozilla += [ + "CallState.h", + "ContentIterator.h", + "CORSMode.h", + "FlushType.h", + "FullscreenChange.h", + "GlobalTeardownObserver.h", + "IdentifierMapEntry.h", + "PointerLockManager.h", + "RangeBoundary.h", + "RangeUtils.h", + "ScriptableContentIterator.h", + "ScrollingMetrics.h", + "SelectionChangeEventDispatcher.h", + "TextInputProcessor.h", + "UseCounter.h", +] + +EXPORTS.mozilla.dom += [ + "!UseCounterList.h", + "!UseCounterWorkerList.h", + "AbstractRange.h", + "AncestorIterator.h", + "AnimationFrameProvider.h", + "AnonymousContent.h", + "Attr.h", + "AutoPrintEventDispatcher.h", + "AutoSuppressEventHandlingAndSuspend.h", + "BarProps.h", + "BindContext.h", + "BodyConsumer.h", + "BodyUtil.h", + "BorrowedAttrInfo.h", + "CCGCScheduler.h", + "CharacterData.h", + "ChildIterator.h", + "ChildProcessMessageManager.h", + "ChromeMessageBroadcaster.h", + "ChromeMessageSender.h", + "ChromeNodeList.h", + "ChromeUtils.h", + "Comment.h", + "CompressionStream.h", + "ContentFrameMessageManager.h", + "ContentProcessMessageManager.h", + "CustomElementRegistry.h", + "DecompressionStream.h", + "DirectionalityUtils.h", + "DocGroup.h", + "Document.h", + "DocumentFragment.h", + "DocumentInlines.h", + "DocumentOrShadowRoot.h", + "DocumentType.h", + "DOMArena.h", + "DOMException.h", + "DOMImplementation.h", + "DOMIntersectionObserver.h", + "DOMMatrix.h", + "DOMMozPromiseRequestHolder.h", + "DOMParser.h", + "DOMPoint.h", + "DOMQuad.h", + "DOMRect.h", + "DOMRequest.h", + "DOMStringList.h", + "DOMTokenListSupportedTokens.h", + "Element.h", + "ElementInlines.h", + "EventSource.h", + "EventSourceEventService.h", + "External.h", + "FilteredNodeIterator.h", + "FormData.h", + "FragmentOrElement.h", + "FromParser.h", + "GeneratedImageContent.h", + "Highlight.h", + "HighlightRegistry.h", + "IdleDeadline.h", + "IdleRequest.h", + "IDTracker.h", + "ImageEncoder.h", + "ImageTracker.h", + "IntlUtils.h", + "JSExecutionContext.h", + "Link.h", + "LinkStyle.h", + "Location.h", + "LocationBase.h", + "MaybeCrossOriginObject.h", + "MessageBroadcaster.h", + "MessageListenerManager.h", + "MessageManagerCallback.h", + "MessageManagerGlobal.h", + "MessageSender.h", + "MimeType.h", + "MozQueryInterface.h", + "MutationObservers.h", + "NameSpaceConstants.h", + "Navigator.h", + "NodeInfo.h", + "NodeInfoInlines.h", + "NodeIterator.h", + "ParentProcessMessageManager.h", + "PlacesBookmark.h", + "PlacesBookmarkAddition.h", + "PlacesBookmarkChanged.h", + "PlacesBookmarkGuid.h", + "PlacesBookmarkKeyword.h", + "PlacesBookmarkMoved.h", + "PlacesBookmarkRemoved.h", + "PlacesBookmarkTags.h", + "PlacesBookmarkTime.h", + "PlacesBookmarkTitle.h", + "PlacesBookmarkUrl.h", + "PlacesEvent.h", + "PlacesFavicon.h", + "PlacesHistoryCleared.h", + "PlacesObservers.h", + "PlacesPurgeCaches.h", + "PlacesRanking.h", + "PlacesVisit.h", + "PlacesVisitRemoved.h", + "PlacesVisitTitle.h", + "PlacesWeakCallbackWrapper.h", + "PopoverData.h", + "PopupBlocker.h", + "Pose.h", + "PostMessageEvent.h", + "ProcessMessageManager.h", + "RadioGroupContainer.h", + "ResizeObserver.h", + "ResponsiveImageSelector.h", + "SameProcessMessageQueue.h", + "ScreenLuminance.h", + "ScreenOrientation.h", + "Selection.h", + "SerializedStackHolder.h", + "ShadowIncludingTreeIterator.h", + "ShadowRoot.h", + "StaticRange.h", + "StructuredCloneBlob.h", + "StructuredCloneHolder.h", + "StructuredCloneTags.h", + "StructuredCloneTester.h", + "StyledRange.h", + "StyleSheetList.h", + "SubtleCrypto.h", + "SyncMessageSender.h", + "TestUtils.h", + "Text.h", + "Timeout.h", + "TimeoutHandler.h", + "TimeoutManager.h", + "TreeIterator.h", + "TreeOrderedArray.h", + "TreeOrderedArrayInlines.h", + "TreeWalker.h", + "UIDirectionManager.h", + "UseCounterMetrics.h", + "UserActivation.h", + "ViewportMetaData.h", + "VisualViewport.h", + "WindowFeatures.h", + "WindowProxyHolder.h", +] + +if CONFIG["FUZZING"]: + EXPORTS.mozilla.dom += [ + "FuzzingFunctions.h", + ] + +if CONFIG["COMPILE_ENVIRONMENT"]: + EXPORTS.mozilla.dom += [ + "!GeneratedElementDocumentState.h", + "RustTypes.h", + ] + + CbindgenHeader( + "GeneratedElementDocumentState.h", + inputs=["rust"], + ) + +UNIFIED_SOURCES += [ + "!UseCounterMetrics.cpp", + "AbstractRange.cpp", + "AnimationFrameProvider.cpp", + "AnonymousContent.cpp", + "Attr.cpp", + "AttrArray.cpp", + "BarProps.cpp", + "BindContext.cpp", + "BodyConsumer.cpp", + "BodyUtil.cpp", + "BorrowedAttrInfo.cpp", + "CCGCScheduler.cpp", + "CharacterData.cpp", + "ChildIterator.cpp", + "ChromeMessageBroadcaster.cpp", + "ChromeMessageSender.cpp", + "ChromeNodeList.cpp", + "ChromeUtils.cpp", + "Comment.cpp", + "ContentFrameMessageManager.cpp", + "ContentIterator.cpp", + "ContentProcessMessageManager.cpp", + "Crypto.cpp", + "CustomElementRegistry.cpp", + "DirectionalityUtils.cpp", + "DocGroup.cpp", + "Document.cpp", + "DocumentFragment.cpp", + "DocumentOrShadowRoot.cpp", + "DocumentType.cpp", + "DOMException.cpp", + "DOMImplementation.cpp", + "DOMMatrix.cpp", + "DOMParser.cpp", + "DOMPoint.cpp", + "DOMQuad.cpp", + "DOMRect.cpp", + "DOMRequest.cpp", + "DOMStringList.cpp", + "Element.cpp", + "EventSource.cpp", + "EventSourceEventService.cpp", + "External.cpp", + "FormData.cpp", + "FragmentOrElement.cpp", + "GeneratedImageContent.cpp", + "GlobalTeardownObserver.cpp", + "Highlight.cpp", + "HighlightRegistry.cpp", + "IdleDeadline.cpp", + "IdleRequest.cpp", + "IDTracker.cpp", + "ImageEncoder.cpp", + "ImageTracker.cpp", + "InProcessBrowserChildMessageManager.cpp", + "IntlUtils.cpp", + "JSExecutionContext.cpp", + "Link.cpp", + "LinkStyle.cpp", + "Location.cpp", + "LocationBase.cpp", + "MaybeCrossOriginObject.cpp", + "MessageBroadcaster.cpp", + "MessageListenerManager.cpp", + "MessageManagerGlobal.cpp", + "MessageSender.cpp", + "MimeType.cpp", + "MozQueryInterface.cpp", + "MutationObservers.cpp", + "Navigator.cpp", + "NodeInfo.cpp", + "NodeIterator.cpp", + "NodeUbiReporting.cpp", + "nsAttrValue.cpp", + "nsAttrValueOrString.cpp", + "nsCCUncollectableMarker.cpp", + "nsContentAreaDragDrop.cpp", + "nsContentList.cpp", + "nsContentPermissionHelper.cpp", + "nsContentPolicy.cpp", + "nsContentSink.cpp", + "nsContentTypeParser.cpp", + "nsCopySupport.cpp", + "nsDataDocumentContentPolicy.cpp", + "nsDOMAttributeMap.cpp", + "nsDOMCaretPosition.cpp", + "nsDOMMutationObserver.cpp", + "nsDOMNavigationTiming.cpp", + "nsDOMTokenList.cpp", + "nsFocusManager.cpp", + "nsFrameLoader.cpp", + "nsFrameLoaderOwner.cpp", + "nsGlobalWindowCommands.cpp", + "nsHistory.cpp", + "nsIGlobalObject.cpp", + "nsINode.cpp", + "nsJSEnvironment.cpp", + "nsJSUtils.cpp", + "nsLineBreaker.cpp", + "nsMimeTypeArray.cpp", + "nsNameSpaceManager.cpp", + "nsNoDataProtocolContentPolicy.cpp", + "nsNodeInfoManager.cpp", + "nsOpenURIInFrameParams.cpp", + "nsPropertyTable.cpp", + "nsQueryContentEventResult.cpp", + "nsRange.cpp", + "nsScreen.cpp", + "nsStructuredCloneContainer.cpp", + "nsStubAnimationObserver.cpp", + "nsStubDocumentObserver.cpp", + "nsStubMutationObserver.cpp", + "nsStyledElement.cpp", + "nsSyncLoadService.cpp", + "nsTextFragment.cpp", + "nsTextNode.cpp", + "nsTraversal.cpp", + "nsTreeSanitizer.cpp", + "nsViewportInfo.cpp", + "nsWindowMemoryReporter.cpp", + "nsWindowRoot.cpp", + "nsWrapperCache.cpp", + "ParentProcessMessageManager.cpp", + "PointerLockManager.cpp", + "PopoverData.cpp", + "PopupBlocker.cpp", + "Pose.cpp", + "PostMessageEvent.cpp", + "ProcessMessageManager.cpp", + "RadioGroupContainer.cpp", + "RangeUtils.cpp", + "RemoteOuterWindowProxy.cpp", + "ResizeObserver.cpp", + "ResponsiveImageSelector.cpp", + "SameProcessMessageQueue.cpp", + "ScreenLuminance.cpp", + "ScreenOrientation.cpp", + "ScriptableContentIterator.cpp", + "ScrollingMetrics.cpp", + "Selection.cpp", + "SelectionChangeEventDispatcher.cpp", + "SerializedStackHolder.cpp", + "ShadowRoot.cpp", + "StaticRange.cpp", + "StorageAccessPermissionRequest.cpp", + "StructuredCloneBlob.cpp", + "StructuredCloneHolder.cpp", + "StructuredCloneTester.cpp", + "StyledRange.cpp", + "StyleSheetList.cpp", + "SubtleCrypto.cpp", + "TestUtils.cpp", + "Text.cpp", + "TextInputProcessor.cpp", + "ThirdPartyUtil.cpp", + "Timeout.cpp", + "TimeoutBudgetManager.cpp", + "TimeoutExecutor.cpp", + "TimeoutHandler.cpp", + "TimeoutManager.cpp", + "TreeWalker.cpp", + "UIDirectionManager.cpp", + "UserActivation.cpp", + "ViewportMetaData.cpp", + "VisualViewport.cpp", + "WindowDestroyedEvent.cpp", + "WindowFeatures.cpp", + "WindowNamedPropertiesHandler.cpp", + "XPathGenerator.cpp", +] + +if CONFIG["MOZ_WEBRTC"]: + UNIFIED_SOURCES += [ + "nsDOMDataChannel.cpp", + ] + +if CONFIG["FUZZING"]: + UNIFIED_SOURCES += [ + "FuzzingFunctions.cpp", + ] + +if CONFIG["MOZ_PLACES"]: + UNIFIED_SOURCES += [ + "PlacesEvent.cpp", + "PlacesObservers.cpp", + "PlacesWeakCallbackWrapper.cpp", + ] + +# on win32 if we add these files to UNIFIED_SOURCES then the compiler generates +# larger stack frames for some recursive functions that cause us to hit stack +# overflows (see bug 1824565) +if CONFIG["OS_ARCH"] == "WINNT" and CONFIG["TARGET_CPU"] == "x86": + SOURCES += [ + "CompressionStream.cpp", + "DecompressionStream.cpp", + ] +else: + UNIFIED_SOURCES += [ + "CompressionStream.cpp", + "DecompressionStream.cpp", + ] + +# these files couldn't be in UNIFIED_SOURCES for now for reasons given below: +SOURCES += [ + # Several conflicts with other bindings. + "DOMIntersectionObserver.cpp", + # Because of OS X headers. + "nsContentUtils.cpp", + # this file doesn't like windows.h + "nsDOMWindowUtils.cpp", + # Conflicts with windows.h's definition of SendMessage. + "nsFrameMessageManager.cpp", + # These files have a #error "Never include unwrapped windows.h in this file!" + "nsGlobalWindowInner.cpp", + "nsGlobalWindowOuter.cpp", + # Conflicts with windows.h's definition of LoadImage. + "nsImageLoadingContent.cpp", + # Because of OS X headers. + "nsObjectLoadingContent.cpp", + # nsPluginArray.cpp includes npapi.h indirectly, and that includes a lot of system headers + "nsPluginArray.cpp", +] + +# Are we targeting x86-32 or x86-64? If so, we want to include SSE2 code for +# nsTextFragment.cpp +if CONFIG["INTEL_ARCHITECTURE"]: + SOURCES += ["nsTextFragmentSSE2.cpp"] + SOURCES["nsTextFragmentSSE2.cpp"].flags += CONFIG["SSE2_FLAGS"] + +# Are we targeting PowerPC? If so, we can enable a SIMD version for +# nsTextFragment.cpp as well. +if CONFIG["TARGET_CPU"].startswith("ppc"): + SOURCES += ["nsTextFragmentVMX.cpp"] + SOURCES["nsTextFragmentVMX.cpp"].flags += CONFIG["PPC_VMX_FLAGS"] + +EXTRA_JS_MODULES += [ + "ContentAreaDropListener.sys.mjs", + "DOMRequestHelper.sys.mjs", + "IndexedDBHelper.sys.mjs", + "LocationHelper.sys.mjs", + "ProcessSelector.sys.mjs", + "SlowScriptDebug.sys.mjs", +] + +XPCOM_MANIFESTS += [ + "components.conf", +] + +LOCAL_INCLUDES += [ + "../battery", + "../events", + "../media", + "../network", + "/caps", + "/docshell/base", + "/dom/base", + "/dom/file", + "/dom/geolocation", + "/dom/html", + "/dom/ipc", + "/dom/storage", + "/dom/svg", + "/dom/xml", + "/dom/xslt/xpath", + "/dom/xul", + "/extensions/spellcheck/src", + "/gfx/2d", + "/image", + "/js/xpconnect/loader", + "/js/xpconnect/src", + "/js/xpconnect/wrappers", + "/layout/base", + "/layout/forms", + "/layout/generic", + "/layout/style", + "/layout/xul", + "/netwerk/base", + "/netwerk/protocol/http", + "/netwerk/url-classifier", + "/parser/htmlparser", + "/security/manager/ssl", + "/third_party/xsimd/include", + "/widget", + "/xpcom/ds", +] + +if CONFIG["MOZ_WEBRTC"]: + LOCAL_INCLUDES += [ + "/netwerk/sctp/datachannel", + ] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul" + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] + +GeneratedFile( + "UseCounterList.h", + script="gen-usecounters.py", + entry_point="use_counter_list", + inputs=["UseCounters.conf"], +) + +GeneratedFile( + "UseCounterWorkerList.h", + script="gen-usecounters.py", + entry_point="use_counter_list", + inputs=["UseCountersWorker.conf"], +) + +GeneratedFile( + "UseCounterMetrics.cpp", + script="usecounters.py", + entry_point="metric_map", + inputs=[ + "UseCounters.conf", + "UseCountersWorker.conf", + "nsDeprecatedOperationList.h", + "!/layout/style/ServoCSSPropList.py", + "/servo/components/style/properties/counted_unknown_properties.py", + ], +) diff --git a/dom/base/mozAutoDocUpdate.h b/dom/base/mozAutoDocUpdate.h new file mode 100644 index 0000000000..0b210c3dda --- /dev/null +++ b/dom/base/mozAutoDocUpdate.h @@ -0,0 +1,51 @@ +/* -*- 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 mozAutoDocUpdate_h_ +#define mozAutoDocUpdate_h_ + +#include "nsContentUtils.h" // For AddScriptBlocker() and RemoveScriptBlocker(). +#include "mozilla/dom/Document.h" +#include "nsIDocumentObserver.h" + +/** + * Helper class to automatically handle batching of document updates. This + * class will call BeginUpdate on construction and EndUpdate on destruction on + * the given document with the given update type. The document could be null, + * in which case no updates will be called. The constructor also takes a + * boolean that can be set to false to prevent notifications. + */ +class MOZ_STACK_CLASS mozAutoDocUpdate { + public: + mozAutoDocUpdate(mozilla::dom::Document* aDocument, bool aNotify) + : mDocument(aNotify ? aDocument : nullptr) { + if (mDocument) { + mDocument->BeginUpdate(); + } else { + nsContentUtils::AddScriptBlocker(); + } + } + + ~mozAutoDocUpdate() { + if (mDocument) { + mDocument->EndUpdate(); + } else { + nsContentUtils::RemoveScriptBlocker(); + } + } + + private: + RefPtr mDocument; +}; + +#define MOZ_AUTO_DOC_UPDATE_PASTE2(tok, line) tok##line +#define MOZ_AUTO_DOC_UPDATE_PASTE(tok, line) \ + MOZ_AUTO_DOC_UPDATE_PASTE2(tok, line) +#define MOZ_AUTO_DOC_UPDATE(doc, notify) \ + mozAutoDocUpdate MOZ_AUTO_DOC_UPDATE_PASTE(_autoDocUpdater_, __LINE__)( \ + doc, notify) + +#endif diff --git a/dom/base/mozIDOMWindow.idl b/dom/base/mozIDOMWindow.idl new file mode 100644 index 0000000000..4b15d54b60 --- /dev/null +++ b/dom/base/mozIDOMWindow.idl @@ -0,0 +1,16 @@ +/* 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 "nsISupports.idl" + +/* + * Placeholder interfaces to allow passing inner/outer windows through XPIDL. + */ +[scriptable, builtinclass, uuid(75fbabd6-7a2e-4787-aa33-449a33512135)] +interface mozIDOMWindow : nsISupports +{}; + +[scriptable, builtinclass, uuid(53ca090c-e739-48b9-8911-208c72f9191e)] +interface mozIDOMWindowProxy : nsISupports +{}; diff --git a/dom/base/nsAttrName.h b/dom/base/nsAttrName.h new file mode 100644 index 0000000000..5af01b028b --- /dev/null +++ b/dom/base/nsAttrName.h @@ -0,0 +1,179 @@ +/* -*- 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/. */ + +/* + * Class that represents the name (nodeinfo or atom) of an attribute; + * using nodeinfos all the time is too slow, so we use atoms when we + * can. + */ + +#ifndef nsAttrName_h___ +#define nsAttrName_h___ + +#include "mozilla/dom/NodeInfo.h" +#include "nsAtom.h" +#include "nsDOMString.h" + +#define NS_ATTRNAME_NODEINFO_BIT 1 +class nsAttrName { + public: + nsAttrName(const nsAttrName& aOther) : mBits(aOther.mBits) { + AddRefInternalName(); + } + + explicit nsAttrName(nsAtom* aAtom) + : mBits(reinterpret_cast(aAtom)) { + NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); + NS_ADDREF(aAtom); + } + + explicit nsAttrName(mozilla::dom::NodeInfo* aNodeInfo) { + NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); + if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { + mBits = reinterpret_cast(aNodeInfo->NameAtom()); + NS_ADDREF(aNodeInfo->NameAtom()); + } else { + mBits = reinterpret_cast(aNodeInfo) | NS_ATTRNAME_NODEINFO_BIT; + NS_ADDREF(aNodeInfo); + } + } + + ~nsAttrName() { ReleaseInternalName(); } + + void SetTo(mozilla::dom::NodeInfo* aNodeInfo) { + NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); + + ReleaseInternalName(); + if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { + mBits = reinterpret_cast(aNodeInfo->NameAtom()); + NS_ADDREF(aNodeInfo->NameAtom()); + } else { + mBits = reinterpret_cast(aNodeInfo) | NS_ATTRNAME_NODEINFO_BIT; + NS_ADDREF(aNodeInfo); + } + } + + void SetTo(nsAtom* aAtom) { + NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); + + ReleaseInternalName(); + mBits = reinterpret_cast(aAtom); + NS_ADDREF(aAtom); + } + + bool IsAtom() const { return !(mBits & NS_ATTRNAME_NODEINFO_BIT); } + + mozilla::dom::NodeInfo* NodeInfo() const { + NS_ASSERTION(!IsAtom(), "getting nodeinfo-value of atom-name"); + return reinterpret_cast(mBits & + ~NS_ATTRNAME_NODEINFO_BIT); + } + + nsAtom* Atom() const { + NS_ASSERTION(IsAtom(), "getting atom-value of nodeinfo-name"); + return reinterpret_cast(mBits); + } + + bool Equals(const nsAttrName& aOther) const { return mBits == aOther.mBits; } + + // Faster comparison in the case we know the namespace is null + // Note that some callers such as AttrArray::IndexOfAttr() will + // call this function on nsAttrName structs with 0 mBits, so no attempt + // must be made to do anything with mBits besides comparing it with the + // incoming aAtom argument. + bool Equals(const nsAtom* aAtom) const { + return reinterpret_cast(aAtom) == mBits; + } + + // And the same but without forcing callers to atomize + bool Equals(const nsAString& aLocalName) const { + return IsAtom() && Atom()->Equals(aLocalName); + } + + bool Equals(const nsAtom* aLocalName, int32_t aNamespaceID) const { + if (aNamespaceID == kNameSpaceID_None) { + return Equals(aLocalName); + } + return !IsAtom() && NodeInfo()->Equals(aLocalName, aNamespaceID); + } + + bool Equals(mozilla::dom::NodeInfo* aNodeInfo) const { + return Equals(aNodeInfo->NameAtom(), aNodeInfo->NamespaceID()); + } + + int32_t NamespaceID() const { + return IsAtom() ? kNameSpaceID_None : NodeInfo()->NamespaceID(); + } + + int32_t NamespaceEquals(int32_t aNamespaceID) const { + return aNamespaceID == kNameSpaceID_None + ? IsAtom() + : (!IsAtom() && NodeInfo()->NamespaceEquals(aNamespaceID)); + } + + nsAtom* LocalName() const { + return IsAtom() ? Atom() : NodeInfo()->NameAtom(); + } + + nsAtom* GetPrefix() const { + return IsAtom() ? nullptr : NodeInfo()->GetPrefixAtom(); + } + + bool QualifiedNameEquals(const nsAString& aName) const { + return IsAtom() ? Atom()->Equals(aName) + : NodeInfo()->QualifiedNameEquals(aName); + } + + void GetQualifiedName(nsAString& aStr) const { + if (IsAtom()) { + Atom()->ToString(aStr); + } else { + aStr = NodeInfo()->QualifiedName(); + } + } + +#ifdef MOZILLA_INTERNAL_API + void GetPrefix(nsAString& aStr) const { + if (IsAtom()) { + SetDOMStringToNull(aStr); + } else { + NodeInfo()->GetPrefix(aStr); + } + } +#endif + + uint32_t HashValue() const { + // mBits and uint32_t might have different size. This should silence + // any warnings or compile-errors. This is what the implementation of + // NS_PTR_TO_INT32 does to take care of the same problem. + return mBits - 0; + } + + bool IsSmaller(const nsAtom* aOther) const { + return mBits < reinterpret_cast(aOther); + } + + private: + void AddRefInternalName() { + if (IsAtom()) { + NS_ADDREF(Atom()); + } else { + NS_ADDREF(NodeInfo()); + } + } + + void ReleaseInternalName() { + if (IsAtom()) { + Atom()->Release(); + } else { + NodeInfo()->Release(); + } + } + + uintptr_t mBits; +}; + +#endif diff --git a/dom/base/nsAttrValue.cpp b/dom/base/nsAttrValue.cpp new file mode 100644 index 0000000000..ea7923fa0f --- /dev/null +++ b/dom/base/nsAttrValue.cpp @@ -0,0 +1,2170 @@ +/* -*- 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/. */ + +/* + * A struct that represents the value (type and actual data) of an + * attribute. + */ + +#include "mozilla/ArrayUtils.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/HashFunctions.h" + +#include "nsAttrValue.h" +#include "nsAttrValueInlines.h" +#include "nsAtomHashKeys.h" +#include "nsUnicharUtils.h" +#include "mozilla/AttributeStyles.h" +#include "mozilla/BloomFilter.h" +#include "mozilla/CORSMode.h" +#include "mozilla/DeclarationBlock.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/ServoBindingTypes.h" +#include "mozilla/ServoUtils.h" +#include "mozilla/ShadowParts.h" +#include "mozilla/SVGAttrValueWrapper.h" +#include "mozilla/URLExtraData.h" +#include "mozilla/dom/CSSRuleBinding.h" +#include "mozilla/dom/Document.h" +#include "nsContentUtils.h" +#include "nsReadableUtils.h" +#include "nsStyledElement.h" +#include "nsIURI.h" +#include "ReferrerInfo.h" +#include + +using namespace mozilla; + +constexpr uint32_t kMiscContainerCacheSize = 128; +static void* gMiscContainerCache[kMiscContainerCacheSize]; +static uint32_t gMiscContainerCount = 0; + +/** + * Global cache for eAtomArray MiscContainer objects, to speed up the parsing + * of class attributes with multiple class names. + * This cache doesn't keep anything alive - a MiscContainer removes itself from + * the cache once its last reference is dropped. + */ +struct AtomArrayCache { + // We don't keep any strong references, neither to the atom nor to the + // MiscContainer. The MiscContainer removes itself from the cache when + // the last reference to it is dropped, and the atom is kept alive by + // the MiscContainer. + using MapType = nsTHashMap; + + static MiscContainer* Lookup(nsAtom* aValue) { + if (auto* instance = GetInstance()) { + return instance->LookupImpl(aValue); + } + return nullptr; + } + + static void Insert(nsAtom* aValue, MiscContainer* aCont) { + if (auto* instance = GetInstance()) { + instance->InsertImpl(aValue, aCont); + } + } + + static void Remove(nsAtom* aValue) { + if (auto* instance = GetInstance()) { + instance->RemoveImpl(aValue); + } + } + + static AtomArrayCache* GetInstance() { + static StaticAutoPtr sInstance; + if (!sInstance && !PastShutdownPhase(ShutdownPhase::XPCOMShutdownFinal)) { + sInstance = new AtomArrayCache(); + ClearOnShutdown(&sInstance, ShutdownPhase::XPCOMShutdownFinal); + } + return sInstance; + } + + private: + MiscContainer* LookupImpl(nsAtom* aValue) { + auto lookupResult = mMap.Lookup(aValue); + return lookupResult ? *lookupResult : nullptr; + } + + void InsertImpl(nsAtom* aValue, MiscContainer* aCont) { + MOZ_ASSERT(aCont); + mMap.InsertOrUpdate(aValue, aCont); + } + + void RemoveImpl(nsAtom* aValue) { mMap.Remove(aValue); } + + MapType mMap; +}; + +/* static */ +MiscContainer* nsAttrValue::AllocMiscContainer() { + MOZ_ASSERT(NS_IsMainThread()); + + static_assert(sizeof(gMiscContainerCache) <= 1024); + static_assert(sizeof(MiscContainer) <= 32); + + // Allocate MiscContainer objects in batches to improve performance. + if (gMiscContainerCount == 0) { + for (; gMiscContainerCount < kMiscContainerCacheSize; + ++gMiscContainerCount) { + gMiscContainerCache[gMiscContainerCount] = + moz_xmalloc(sizeof(MiscContainer)); + } + } + + return new (gMiscContainerCache[--gMiscContainerCount]) MiscContainer(); +} + +/* static */ +void nsAttrValue::DeallocMiscContainer(MiscContainer* aCont) { + MOZ_ASSERT(NS_IsMainThread()); + if (!aCont) { + return; + } + + aCont->~MiscContainer(); + + if (gMiscContainerCount < kMiscContainerCacheSize) { + gMiscContainerCache[gMiscContainerCount++] = aCont; + return; + } + + free(aCont); +} + +bool MiscContainer::GetString(nsAString& aString) const { + bool isString; + void* ptr = GetStringOrAtomPtr(isString); + if (!ptr) { + return false; + } + if (isString) { + auto* buffer = static_cast(ptr); + buffer->ToString(buffer->StorageSize() / sizeof(char16_t) - 1, aString); + } else { + static_cast(ptr)->ToString(aString); + } + return true; +} + +void MiscContainer::Cache() { + switch (mType) { + case nsAttrValue::eCSSDeclaration: { + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount > 0); + MOZ_ASSERT(!mValue.mCached); + + AttributeStyles* attrStyles = + mValue.mCSSDeclaration->GetAttributeStyles(); + if (!attrStyles) { + return; + } + + nsString str; + bool gotString = GetString(str); + if (!gotString) { + return; + } + + attrStyles->CacheStyleAttr(str, this); + mValue.mCached = 1; + + // This has to be immutable once it goes into the cache. + mValue.mCSSDeclaration->SetImmutable(); + break; + } + case nsAttrValue::eAtomArray: { + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount > 0); + MOZ_ASSERT(!mValue.mCached); + + nsAtom* atom = GetStoredAtom(); + if (!atom) { + return; + } + + AtomArrayCache::Insert(atom, this); + mValue.mCached = 1; + break; + } + default: + MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type"); + break; + } +} + +void MiscContainer::Evict() { + switch (mType) { + case nsAttrValue::eCSSDeclaration: { + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount == 0); + + if (!mValue.mCached) { + return; + } + + AttributeStyles* attrStyles = + mValue.mCSSDeclaration->GetAttributeStyles(); + MOZ_ASSERT(attrStyles); + + nsString str; + DebugOnly gotString = GetString(str); + MOZ_ASSERT(gotString); + + attrStyles->EvictStyleAttr(str, this); + mValue.mCached = 0; + break; + } + case nsAttrValue::eAtomArray: { + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount == 0); + + if (!mValue.mCached) { + return; + } + + nsAtom* atom = GetStoredAtom(); + MOZ_ASSERT(atom); + + AtomArrayCache::Remove(atom); + + mValue.mCached = 0; + break; + } + default: + + MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type"); + break; + } +} + +nsTArray* nsAttrValue::sEnumTableArray = nullptr; + +nsAttrValue::nsAttrValue() : mBits(0) {} + +nsAttrValue::nsAttrValue(const nsAttrValue& aOther) : mBits(0) { + SetTo(aOther); +} + +nsAttrValue::nsAttrValue(const nsAString& aValue) : mBits(0) { SetTo(aValue); } + +nsAttrValue::nsAttrValue(nsAtom* aValue) : mBits(0) { SetTo(aValue); } + +nsAttrValue::nsAttrValue(already_AddRefed aValue, + const nsAString* aSerialized) + : mBits(0) { + SetTo(std::move(aValue), aSerialized); +} + +nsAttrValue::~nsAttrValue() { ResetIfSet(); } + +/* static */ +void nsAttrValue::Init() { + MOZ_ASSERT(!sEnumTableArray, "nsAttrValue already initialized"); + sEnumTableArray = new nsTArray; +} + +/* static */ +void nsAttrValue::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + delete sEnumTableArray; + sEnumTableArray = nullptr; + + for (uint32_t i = 0; i < gMiscContainerCount; ++i) { + free(gMiscContainerCache[i]); + } + gMiscContainerCount = 0; +} + +void nsAttrValue::Reset() { + switch (BaseType()) { + case eStringBase: { + nsStringBuffer* str = static_cast(GetPtr()); + if (str) { + str->Release(); + } + + break; + } + case eOtherBase: { + MiscContainer* cont = GetMiscContainer(); + if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { + NS_RELEASE(cont); + break; + } + + DeallocMiscContainer(ClearMiscContainer()); + + break; + } + case eAtomBase: { + nsAtom* atom = GetAtomValue(); + NS_RELEASE(atom); + + break; + } + case eIntegerBase: { + break; + } + } + + mBits = 0; +} + +void nsAttrValue::SetTo(const nsAttrValue& aOther) { + if (this == &aOther) { + return; + } + + switch (aOther.BaseType()) { + case eStringBase: { + ResetIfSet(); + nsStringBuffer* str = static_cast(aOther.GetPtr()); + if (str) { + str->AddRef(); + SetPtrValueAndType(str, eStringBase); + } + return; + } + case eOtherBase: { + break; + } + case eAtomBase: { + ResetIfSet(); + nsAtom* atom = aOther.GetAtomValue(); + NS_ADDREF(atom); + SetPtrValueAndType(atom, eAtomBase); + return; + } + case eIntegerBase: { + ResetIfSet(); + mBits = aOther.mBits; + return; + } + } + + MiscContainer* otherCont = aOther.GetMiscContainer(); + if (otherCont->IsRefCounted()) { + DeallocMiscContainer(ClearMiscContainer()); + NS_ADDREF(otherCont); + SetPtrValueAndType(otherCont, eOtherBase); + return; + } + + MiscContainer* cont = EnsureEmptyMiscContainer(); + switch (otherCont->mType) { + case eInteger: { + cont->mValue.mInteger = otherCont->mValue.mInteger; + break; + } + case eEnum: { + cont->mValue.mEnumValue = otherCont->mValue.mEnumValue; + break; + } + case ePercent: { + cont->mDoubleValue = otherCont->mDoubleValue; + break; + } + case eColor: { + cont->mValue.mColor = otherCont->mValue.mColor; + break; + } + case eAtomArray: + case eShadowParts: + case eCSSDeclaration: { + MOZ_CRASH("These should be refcounted!"); + } + case eURL: { + NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL); + break; + } + case eDoubleValue: { + cont->mDoubleValue = otherCont->mDoubleValue; + break; + } + default: { + if (IsSVGType(otherCont->mType)) { + // All SVG types are just pointers to classes and will therefore have + // the same size so it doesn't really matter which one we assign + cont->mValue.mSVGLength = otherCont->mValue.mSVGLength; + } else { + MOZ_ASSERT_UNREACHABLE("unknown type stored in MiscContainer"); + } + break; + } + } + + bool isString; + if (void* otherPtr = otherCont->GetStringOrAtomPtr(isString)) { + if (isString) { + static_cast(otherPtr)->AddRef(); + } else { + static_cast(otherPtr)->AddRef(); + } + cont->SetStringBitsMainThread(otherCont->mStringBits); + } + // Note, set mType after switch-case, otherwise EnsureEmptyAtomArray doesn't + // work correctly. + cont->mType = otherCont->mType; +} + +void nsAttrValue::SetTo(const nsAString& aValue) { + ResetIfSet(); + nsStringBuffer* buf = GetStringBuffer(aValue).take(); + if (buf) { + SetPtrValueAndType(buf, eStringBase); + } +} + +void nsAttrValue::SetTo(nsAtom* aValue) { + ResetIfSet(); + if (aValue) { + NS_ADDREF(aValue); + SetPtrValueAndType(aValue, eAtomBase); + } +} + +void nsAttrValue::SetTo(int16_t aInt) { + ResetIfSet(); + SetIntValueAndType(aInt, eInteger, nullptr); +} + +void nsAttrValue::SetTo(int32_t aInt, const nsAString* aSerialized) { + ResetIfSet(); + SetIntValueAndType(aInt, eInteger, aSerialized); +} + +void nsAttrValue::SetTo(double aValue, const nsAString* aSerialized) { + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mDoubleValue = aValue; + cont->mType = eDoubleValue; + SetMiscAtomOrString(aSerialized); +} + +void nsAttrValue::SetTo(already_AddRefed aValue, + const nsAString* aSerialized) { + MiscContainer* cont = EnsureEmptyMiscContainer(); + MOZ_ASSERT(cont->mValue.mRefCount == 0); + cont->mValue.mCSSDeclaration = aValue.take(); + cont->mType = eCSSDeclaration; + NS_ADDREF(cont); + SetMiscAtomOrString(aSerialized); + MOZ_ASSERT(cont->mValue.mRefCount == 1); +} + +void nsAttrValue::SetTo(nsIURI* aValue, const nsAString* aSerialized) { + MiscContainer* cont = EnsureEmptyMiscContainer(); + NS_ADDREF(cont->mValue.mURL = aValue); + cont->mType = eURL; + SetMiscAtomOrString(aSerialized); +} + +void nsAttrValue::SetToSerialized(const nsAttrValue& aOther) { + if (aOther.Type() != nsAttrValue::eString && + aOther.Type() != nsAttrValue::eAtom) { + nsAutoString val; + aOther.ToString(val); + SetTo(val); + } else { + SetTo(aOther); + } +} + +void nsAttrValue::SetTo(const SVGAnimatedOrient& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGOrient, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGAnimatedIntegerPair& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGIntegerPair, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGAnimatedLength& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGLength, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGLengthList& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as a length list, there's no need to store + // it (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGLengthList, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGNumberList& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as a number list, there's no need to store + // it (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGNumberList, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGAnimatedNumberPair& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGNumberPair, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGPathData& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as path data, there's no need to store it + // (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGPathData, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGPointList& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as a point list, there's no need to store + // it (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGPointList, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGAnimatedPreserveAspectRatio& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGPreserveAspectRatio, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGStringList& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as a string list, there's no need to store + // it (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGStringList, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGTransformList& aValue, + const nsAString* aSerialized) { + // While an empty string will parse as a transform list, there's no need to + // store it (and SetMiscAtomOrString will assert if we try) + if (aSerialized && aSerialized->IsEmpty()) { + aSerialized = nullptr; + } + SetSVGType(eSVGTransformList, &aValue, aSerialized); +} + +void nsAttrValue::SetTo(const SVGAnimatedViewBox& aValue, + const nsAString* aSerialized) { + SetSVGType(eSVGViewBox, &aValue, aSerialized); +} + +void nsAttrValue::SwapValueWith(nsAttrValue& aOther) { + uintptr_t tmp = aOther.mBits; + aOther.mBits = mBits; + mBits = tmp; +} + +void nsAttrValue::RemoveDuplicatesFromAtomArray() { + if (Type() != eAtomArray) { + return; + } + + const AttrAtomArray* currentAtomArray = GetMiscContainer()->mValue.mAtomArray; + UniquePtr deduplicatedAtomArray = + currentAtomArray->CreateDeduplicatedCopyIfDifferent(); + + if (!deduplicatedAtomArray) { + // No duplicates found. Leave this value unchanged. + return; + } + + // We found duplicates. Wrap the new atom array into a fresh MiscContainer, + // and copy over the existing container's string or atom. + + MiscContainer* oldCont = GetMiscContainer(); + MOZ_ASSERT(oldCont->IsRefCounted()); + + uintptr_t stringBits = 0; + bool isString = false; + if (void* otherPtr = oldCont->GetStringOrAtomPtr(isString)) { + stringBits = oldCont->mStringBits; + if (isString) { + static_cast(otherPtr)->AddRef(); + } else { + static_cast(otherPtr)->AddRef(); + } + } + + MiscContainer* cont = EnsureEmptyMiscContainer(); + MOZ_ASSERT(cont->mValue.mRefCount == 0); + cont->mValue.mAtomArray = deduplicatedAtomArray.release(); + cont->mType = eAtomArray; + NS_ADDREF(cont); + MOZ_ASSERT(cont->mValue.mRefCount == 1); + cont->SetStringBitsMainThread(stringBits); + + // Don't cache the new container. It would stomp over the undeduplicated + // value in the cache. But we could have a separate cache for deduplicated + // atom arrays, if repeated deduplication shows up in profiles. +} + +void nsAttrValue::ToString(nsAString& aResult) const { + MiscContainer* cont = nullptr; + if (BaseType() == eOtherBase) { + cont = GetMiscContainer(); + + if (cont->GetString(aResult)) { + return; + } + } + + switch (Type()) { + case eString: { + nsStringBuffer* str = static_cast(GetPtr()); + if (str) { + str->ToString(str->StorageSize() / sizeof(char16_t) - 1, aResult); + } else { + aResult.Truncate(); + } + break; + } + case eAtom: { + nsAtom* atom = static_cast(GetPtr()); + atom->ToString(aResult); + + break; + } + case eInteger: { + nsAutoString intStr; + intStr.AppendInt(GetIntegerValue()); + aResult = intStr; + + break; + } +#ifdef DEBUG + case eColor: { + MOZ_ASSERT_UNREACHABLE("color attribute without string data"); + aResult.Truncate(); + break; + } +#endif + case eEnum: { + GetEnumString(aResult, false); + break; + } + case ePercent: { + nsAutoString str; + if (cont) { + str.AppendFloat(cont->mDoubleValue); + } else { + str.AppendInt(GetIntInternal()); + } + aResult = str + u"%"_ns; + + break; + } + case eCSSDeclaration: { + aResult.Truncate(); + MiscContainer* container = GetMiscContainer(); + if (DeclarationBlock* decl = container->mValue.mCSSDeclaration) { + nsAutoCString result; + decl->ToString(result); + CopyUTF8toUTF16(result, aResult); + } + + // This can be reached during parallel selector matching with attribute + // selectors on the style attribute. SetMiscAtomOrString handles this + // case, and as of this writing this is the only consumer that needs it. + const_cast(this)->SetMiscAtomOrString(&aResult); + + break; + } + case eDoubleValue: { + aResult.Truncate(); + aResult.AppendFloat(GetDoubleValue()); + break; + } + case eSVGIntegerPair: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGAnimatedIntegerPair, aResult); + break; + } + case eSVGOrient: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGAnimatedOrient, aResult); + break; + } + case eSVGLength: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGLength, + aResult); + break; + } + case eSVGLengthList: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGLengthList, + aResult); + break; + } + case eSVGNumberList: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGNumberList, + aResult); + break; + } + case eSVGNumberPair: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGAnimatedNumberPair, aResult); + break; + } + case eSVGPathData: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGPathData, + aResult); + break; + } + case eSVGPointList: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGPointList, + aResult); + break; + } + case eSVGPreserveAspectRatio: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGAnimatedPreserveAspectRatio, aResult); + break; + } + case eSVGStringList: { + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGStringList, + aResult); + break; + } + case eSVGTransformList: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGTransformList, aResult); + break; + } + case eSVGViewBox: { + SVGAttrValueWrapper::ToString( + GetMiscContainer()->mValue.mSVGAnimatedViewBox, aResult); + break; + } + default: { + aResult.Truncate(); + break; + } + } +} + +already_AddRefed nsAttrValue::GetAsAtom() const { + switch (Type()) { + case eString: + return NS_AtomizeMainThread(GetStringValue()); + + case eAtom: { + RefPtr atom = GetAtomValue(); + return atom.forget(); + } + + default: { + nsAutoString val; + ToString(val); + return NS_AtomizeMainThread(val); + } + } +} + +const nsCheapString nsAttrValue::GetStringValue() const { + MOZ_ASSERT(Type() == eString, "wrong type"); + + return nsCheapString(static_cast(GetPtr())); +} + +bool nsAttrValue::GetColorValue(nscolor& aColor) const { + if (Type() != eColor) { + // Unparseable value, treat as unset. + NS_ASSERTION(Type() == eString, "unexpected type for color-valued attr"); + return false; + } + + aColor = GetMiscContainer()->mValue.mColor; + return true; +} + +void nsAttrValue::GetEnumString(nsAString& aResult, bool aRealTag) const { + MOZ_ASSERT(Type() == eEnum, "wrong type"); + + uint32_t allEnumBits = (BaseType() == eIntegerBase) + ? static_cast(GetIntInternal()) + : GetMiscContainer()->mValue.mEnumValue; + int16_t val = allEnumBits >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS; + const EnumTable* table = sEnumTableArray->ElementAt( + allEnumBits & NS_ATTRVALUE_ENUMTABLEINDEX_MASK); + + while (table->tag) { + if (table->value == val) { + aResult.AssignASCII(table->tag); + if (!aRealTag && + allEnumBits & NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER) { + nsContentUtils::ASCIIToUpper(aResult); + } + return; + } + table++; + } + + MOZ_ASSERT_UNREACHABLE("couldn't find value in EnumTable"); +} + +UniquePtr AttrAtomArray::CreateDeduplicatedCopyIfDifferentImpl() + const { + MOZ_ASSERT(mMayContainDuplicates); + + bool usingHashTable = false; + BitBloomFilter<8, nsAtom> filter; + nsTHashSet hash; + + auto CheckDuplicate = [&](size_t i) { + nsAtom* atom = mArray[i]; + if (!usingHashTable) { + if (!filter.mightContain(atom)) { + filter.add(atom); + return false; + } + for (size_t j = 0; j < i; ++j) { + hash.Insert(mArray[j]); + } + usingHashTable = true; + } + return !hash.EnsureInserted(atom); + }; + + size_t len = mArray.Length(); + UniquePtr deduplicatedArray; + for (size_t i = 0; i < len; ++i) { + if (!CheckDuplicate(i)) { + if (deduplicatedArray) { + deduplicatedArray->mArray.AppendElement(mArray[i]); + } + continue; + } + // We've found a duplicate! + if (!deduplicatedArray) { + // Allocate the deduplicated copy and copy the preceding elements into it. + deduplicatedArray = MakeUnique(); + deduplicatedArray->mMayContainDuplicates = false; + deduplicatedArray->mArray.SetCapacity(len - 1); + for (size_t indexToCopy = 0; indexToCopy < i; indexToCopy++) { + deduplicatedArray->mArray.AppendElement(mArray[indexToCopy]); + } + } + } + + if (!deduplicatedArray) { + // This AttrAtomArray doesn't contain any duplicates, cache this information + // for future invocations. + mMayContainDuplicates = false; + } + return deduplicatedArray; +} + +uint32_t nsAttrValue::GetAtomCount() const { + ValueType type = Type(); + + if (type == eAtom) { + return 1; + } + + if (type == eAtomArray) { + return GetAtomArrayValue()->mArray.Length(); + } + + return 0; +} + +nsAtom* nsAttrValue::AtomAt(int32_t aIndex) const { + MOZ_ASSERT(aIndex >= 0, "Index must not be negative"); + MOZ_ASSERT(GetAtomCount() > uint32_t(aIndex), "aIndex out of range"); + + if (BaseType() == eAtomBase) { + return GetAtomValue(); + } + + NS_ASSERTION(Type() == eAtomArray, "GetAtomCount must be confused"); + return GetAtomArrayValue()->mArray.ElementAt(aIndex); +} + +uint32_t nsAttrValue::HashValue() const { + switch (BaseType()) { + case eStringBase: { + nsStringBuffer* str = static_cast(GetPtr()); + if (str) { + uint32_t len = str->StorageSize() / sizeof(char16_t) - 1; + return HashString(static_cast(str->Data()), len); + } + + return 0; + } + case eOtherBase: { + break; + } + case eAtomBase: + case eIntegerBase: { + // mBits and uint32_t might have different size. This should silence + // any warnings or compile-errors. This is what the implementation of + // NS_PTR_TO_INT32 does to take care of the same problem. + return mBits - 0; + } + } + + MiscContainer* cont = GetMiscContainer(); + if (static_cast(cont->mStringBits & + NS_ATTRVALUE_BASETYPE_MASK) == eAtomBase) { + return cont->mStringBits - 0; + } + + switch (cont->mType) { + case eInteger: { + return cont->mValue.mInteger; + } + case eEnum: { + return cont->mValue.mEnumValue; + } + case ePercent: { + return cont->mDoubleValue; + } + case eColor: { + return cont->mValue.mColor; + } + case eCSSDeclaration: { + return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration); + } + case eURL: { + nsString str; + ToString(str); + return HashString(str); + } + case eAtomArray: { + uint32_t hash = 0; + for (const auto& atom : cont->mValue.mAtomArray->mArray) { + hash = AddToHash(hash, atom.get()); + } + return hash; + } + case eDoubleValue: { + // XXX this is crappy, but oh well + return cont->mDoubleValue; + } + default: { + if (IsSVGType(cont->mType)) { + // All SVG types are just pointers to classes so we can treat them alike + return NS_PTR_TO_INT32(cont->mValue.mSVGLength); + } + MOZ_ASSERT_UNREACHABLE("unknown type stored in MiscContainer"); + return 0; + } + } +} + +bool nsAttrValue::Equals(const nsAttrValue& aOther) const { + if (BaseType() != aOther.BaseType()) { + return false; + } + + switch (BaseType()) { + case eStringBase: { + return GetStringValue().Equals(aOther.GetStringValue()); + } + case eOtherBase: { + break; + } + case eAtomBase: + case eIntegerBase: { + return mBits == aOther.mBits; + } + } + + MiscContainer* thisCont = GetMiscContainer(); + MiscContainer* otherCont = aOther.GetMiscContainer(); + if (thisCont == otherCont) { + return true; + } + + if (thisCont->mType != otherCont->mType) { + return false; + } + + bool needsStringComparison = false; + + switch (thisCont->mType) { + case eInteger: { + if (thisCont->mValue.mInteger == otherCont->mValue.mInteger) { + needsStringComparison = true; + } + break; + } + case eEnum: { + if (thisCont->mValue.mEnumValue == otherCont->mValue.mEnumValue) { + needsStringComparison = true; + } + break; + } + case ePercent: { + if (thisCont->mDoubleValue == otherCont->mDoubleValue) { + needsStringComparison = true; + } + break; + } + case eColor: { + if (thisCont->mValue.mColor == otherCont->mValue.mColor) { + needsStringComparison = true; + } + break; + } + case eCSSDeclaration: { + return thisCont->mValue.mCSSDeclaration == + otherCont->mValue.mCSSDeclaration; + } + case eURL: { + return thisCont->mValue.mURL == otherCont->mValue.mURL; + } + case eAtomArray: { + // For classlists we could be insensitive to order, however + // classlists are never mapped attributes so they are never compared. + + if (!(*thisCont->mValue.mAtomArray == *otherCont->mValue.mAtomArray)) { + return false; + } + + needsStringComparison = true; + break; + } + case eDoubleValue: { + return thisCont->mDoubleValue == otherCont->mDoubleValue; + } + default: { + if (IsSVGType(thisCont->mType)) { + // Currently this method is never called for nsAttrValue objects that + // point to SVG data types. + // If that changes then we probably want to add methods to the + // corresponding SVG types to compare their base values. + // As a shortcut, however, we can begin by comparing the pointers. + MOZ_ASSERT(false, "Comparing nsAttrValues that point to SVG data"); + return false; + } + MOZ_ASSERT_UNREACHABLE("unknown type stored in MiscContainer"); + return false; + } + } + if (needsStringComparison) { + if (thisCont->mStringBits == otherCont->mStringBits) { + return true; + } + if ((static_cast(thisCont->mStringBits & + NS_ATTRVALUE_BASETYPE_MASK) == + eStringBase) && + (static_cast(otherCont->mStringBits & + NS_ATTRVALUE_BASETYPE_MASK) == + eStringBase)) { + return nsCheapString(reinterpret_cast( + static_cast(thisCont->mStringBits))) + .Equals(nsCheapString(reinterpret_cast( + static_cast(otherCont->mStringBits)))); + } + } + return false; +} + +bool nsAttrValue::Equals(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + switch (BaseType()) { + case eStringBase: { + if (auto* str = static_cast(GetPtr())) { + nsDependentString dep(static_cast(str->Data()), + str->StorageSize() / sizeof(char16_t) - 1); + return aCaseSensitive == eCaseMatters + ? aValue.Equals(dep) + : nsContentUtils::EqualsIgnoreASCIICase(aValue, dep); + } + return aValue.IsEmpty(); + } + case eAtomBase: { + auto* atom = static_cast(GetPtr()); + if (aCaseSensitive == eCaseMatters) { + return atom->Equals(aValue); + } + return nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(atom), + aValue); + } + default: + break; + } + + nsAutoString val; + ToString(val); + return aCaseSensitive == eCaseMatters + ? val.Equals(aValue) + : nsContentUtils::EqualsIgnoreASCIICase(val, aValue); +} + +bool nsAttrValue::Equals(const nsAtom* aValue, + nsCaseTreatment aCaseSensitive) const { + switch (BaseType()) { + case eAtomBase: { + auto* atom = static_cast(GetPtr()); + if (atom == aValue) { + return true; + } + if (aCaseSensitive == eCaseMatters) { + return false; + } + if (atom->IsAsciiLowercase() && aValue->IsAsciiLowercase()) { + return false; + } + return nsContentUtils::EqualsIgnoreASCIICase( + nsDependentAtomString(atom), nsDependentAtomString(aValue)); + } + case eStringBase: { + if (auto* str = static_cast(GetPtr())) { + size_t strLen = str->StorageSize() / sizeof(char16_t) - 1; + if (aValue->GetLength() != strLen) { + return false; + } + const char16_t* strData = static_cast(str->Data()); + const char16_t* valData = aValue->GetUTF16String(); + if (aCaseSensitive == eCaseMatters) { + // Avoid string construction / destruction for the easy case. + return ArrayEqual(strData, valData, strLen); + } + nsDependentSubstring depStr(strData, strLen); + nsDependentSubstring depVal(valData, strLen); + return nsContentUtils::EqualsIgnoreASCIICase(depStr, depVal); + } + return aValue->IsEmpty(); + } + default: + break; + } + + nsAutoString val; + ToString(val); + nsDependentAtomString dep(aValue); + return aCaseSensitive == eCaseMatters + ? val.Equals(dep) + : nsContentUtils::EqualsIgnoreASCIICase(val, dep); +} + +struct HasPrefixFn { + static bool Check(const char16_t* aAttrValue, size_t aAttrLen, + const nsAString& aSearchValue, + nsCaseTreatment aCaseSensitive) { + if (aCaseSensitive == eCaseMatters) { + if (aSearchValue.Length() > aAttrLen) { + return false; + } + return !memcmp(aAttrValue, aSearchValue.BeginReading(), + aSearchValue.Length() * sizeof(char16_t)); + } + return StringBeginsWith(nsDependentString(aAttrValue, aAttrLen), + aSearchValue, + nsASCIICaseInsensitiveStringComparator); + } +}; + +struct HasSuffixFn { + static bool Check(const char16_t* aAttrValue, size_t aAttrLen, + const nsAString& aSearchValue, + nsCaseTreatment aCaseSensitive) { + if (aCaseSensitive == eCaseMatters) { + if (aSearchValue.Length() > aAttrLen) { + return false; + } + return !memcmp(aAttrValue + aAttrLen - aSearchValue.Length(), + aSearchValue.BeginReading(), + aSearchValue.Length() * sizeof(char16_t)); + } + return StringEndsWith(nsDependentString(aAttrValue, aAttrLen), aSearchValue, + nsASCIICaseInsensitiveStringComparator); + } +}; + +struct HasSubstringFn { + static bool Check(const char16_t* aAttrValue, size_t aAttrLen, + const nsAString& aSearchValue, + nsCaseTreatment aCaseSensitive) { + if (aCaseSensitive == eCaseMatters) { + if (aSearchValue.IsEmpty()) { + return true; + } + const char16_t* end = aAttrValue + aAttrLen; + return std::search(aAttrValue, end, aSearchValue.BeginReading(), + aSearchValue.EndReading()) != end; + } + return FindInReadable(aSearchValue, nsDependentString(aAttrValue, aAttrLen), + nsASCIICaseInsensitiveStringComparator); + } +}; + +template +bool nsAttrValue::SubstringCheck(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + switch (BaseType()) { + case eStringBase: { + auto str = static_cast(GetPtr()); + if (str) { + return F::Check(static_cast(str->Data()), + str->StorageSize() / sizeof(char16_t) - 1, aValue, + aCaseSensitive); + } + return aValue.IsEmpty(); + } + case eAtomBase: { + auto atom = static_cast(GetPtr()); + return F::Check(atom->GetUTF16String(), atom->GetLength(), aValue, + aCaseSensitive); + } + default: + break; + } + + nsAutoString val; + ToString(val); + return F::Check(val.BeginReading(), val.Length(), aValue, aCaseSensitive); +} + +bool nsAttrValue::HasPrefix(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + return SubstringCheck(aValue, aCaseSensitive); +} + +bool nsAttrValue::HasSuffix(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + return SubstringCheck(aValue, aCaseSensitive); +} + +bool nsAttrValue::HasSubstring(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const { + return SubstringCheck(aValue, aCaseSensitive); +} + +bool nsAttrValue::EqualsAsStrings(const nsAttrValue& aOther) const { + if (Type() == aOther.Type()) { + return Equals(aOther); + } + + // We need to serialize at least one nsAttrValue before passing to + // Equals(const nsAString&), but we can avoid unnecessarily serializing both + // by checking if one is already of a string type. + bool thisIsString = (BaseType() == eStringBase || BaseType() == eAtomBase); + const nsAttrValue& lhs = thisIsString ? *this : aOther; + const nsAttrValue& rhs = thisIsString ? aOther : *this; + + switch (rhs.BaseType()) { + case eAtomBase: + return lhs.Equals(rhs.GetAtomValue(), eCaseMatters); + + case eStringBase: + return lhs.Equals(rhs.GetStringValue(), eCaseMatters); + + default: { + nsAutoString val; + rhs.ToString(val); + return lhs.Equals(val, eCaseMatters); + } + } +} + +bool nsAttrValue::Contains(nsAtom* aValue, + nsCaseTreatment aCaseSensitive) const { + switch (BaseType()) { + case eAtomBase: { + nsAtom* atom = GetAtomValue(); + if (aCaseSensitive == eCaseMatters) { + return aValue == atom; + } + + // For performance reasons, don't do a full on unicode case insensitive + // string comparison. This is only used for quirks mode anyway. + return nsContentUtils::EqualsIgnoreASCIICase(aValue, atom); + } + default: { + if (Type() == eAtomArray) { + const AttrAtomArray* array = GetAtomArrayValue(); + if (aCaseSensitive == eCaseMatters) { + return array->mArray.Contains(aValue); + } + + for (const RefPtr& cur : array->mArray) { + // For performance reasons, don't do a full on unicode case + // insensitive string comparison. This is only used for quirks mode + // anyway. + if (nsContentUtils::EqualsIgnoreASCIICase(aValue, cur)) { + return true; + } + } + } + } + } + + return false; +} + +struct AtomArrayStringComparator { + bool Equals(nsAtom* atom, const nsAString& string) const { + return atom->Equals(string); + } +}; + +bool nsAttrValue::Contains(const nsAString& aValue) const { + switch (BaseType()) { + case eAtomBase: { + nsAtom* atom = GetAtomValue(); + return atom->Equals(aValue); + } + default: { + if (Type() == eAtomArray) { + const AttrAtomArray* array = GetAtomArrayValue(); + return array->mArray.Contains(aValue, AtomArrayStringComparator()); + } + } + } + + return false; +} + +void nsAttrValue::ParseAtom(const nsAString& aValue) { + ResetIfSet(); + + RefPtr atom = NS_Atomize(aValue); + if (atom) { + SetPtrValueAndType(atom.forget().take(), eAtomBase); + } +} + +void nsAttrValue::ParseAtomArray(nsAtom* aValue) { + if (MiscContainer* cont = AtomArrayCache::Lookup(aValue)) { + // Set our MiscContainer to the cached one. + NS_ADDREF(cont); + SetPtrValueAndType(cont, eOtherBase); + return; + } + + const char16_t* iter = aValue->GetUTF16String(); + const char16_t* end = iter + aValue->GetLength(); + bool hasSpace = false; + + // skip initial whitespace + while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { + hasSpace = true; + ++iter; + } + + if (iter == end) { + // The value is empty or only contains whitespace. + // Set this attribute to the string value. + // We don't call the SetTo(nsAtom*) overload because doing so would + // leave us with a classList of length 1. + SetTo(nsDependentAtomString(aValue)); + return; + } + + const char16_t* start = iter; + + // get first - and often only - atom + do { + ++iter; + } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter)); + + RefPtr classAtom = iter == end && !hasSpace + ? RefPtr(aValue).forget() + : NS_AtomizeMainThread(Substring(start, iter)); + if (!classAtom) { + ResetIfSet(); + return; + } + + // skip whitespace + while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { + hasSpace = true; + ++iter; + } + + if (iter == end && !hasSpace) { + // we only found one classname and there was no whitespace so + // don't bother storing a list + ResetIfSet(); + nsAtom* atom = nullptr; + classAtom.swap(atom); + SetPtrValueAndType(atom, eAtomBase); + return; + } + + // We have at least one class atom. Create a new AttrAtomArray. + AttrAtomArray* array = new AttrAtomArray; + + // XXX(Bug 1631371) Check if this should use a fallible operation as it + // pretended earlier. + array->mArray.AppendElement(std::move(classAtom)); + + // parse the rest of the classnames + while (iter != end) { + start = iter; + + do { + ++iter; + } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter)); + + classAtom = NS_AtomizeMainThread(Substring(start, iter)); + + // XXX(Bug 1631371) Check if this should use a fallible operation as it + // pretended earlier. + array->mArray.AppendElement(std::move(classAtom)); + array->mMayContainDuplicates = true; + + // skip whitespace + while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { + ++iter; + } + } + + // Wrap the AtomArray into a fresh MiscContainer. + MiscContainer* cont = EnsureEmptyMiscContainer(); + MOZ_ASSERT(cont->mValue.mRefCount == 0); + cont->mValue.mAtomArray = array; + cont->mType = eAtomArray; + NS_ADDREF(cont); + MOZ_ASSERT(cont->mValue.mRefCount == 1); + + // Assign the atom to the container's string bits (like SetMiscAtomOrString + // would do). + MOZ_ASSERT(!IsInServoTraversal()); + aValue->AddRef(); + uintptr_t bits = reinterpret_cast(aValue) | eAtomBase; + cont->SetStringBitsMainThread(bits); + + // Put the container in the cache. + cont->Cache(); +} + +void nsAttrValue::ParseAtomArray(const nsAString& aValue) { + if (aValue.IsVoid()) { + ResetIfSet(); + } else { + RefPtr atom = NS_AtomizeMainThread(aValue); + ParseAtomArray(atom); + } +} + +void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) { + uint32_t len = aValue.Length(); + // Don't bother with atoms if it's an empty string since + // we can store those efficiently anyway. + if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) { + ParseAtom(aValue); + } else { + SetTo(aValue); + } +} + +void nsAttrValue::ParsePartMapping(const nsAString& aValue) { + ResetIfSet(); + MiscContainer* cont = EnsureEmptyMiscContainer(); + + cont->mType = eShadowParts; + cont->mValue.mShadowParts = new ShadowParts(ShadowParts::Parse(aValue)); + NS_ADDREF(cont); + SetMiscAtomOrString(&aValue); + MOZ_ASSERT(cont->mValue.mRefCount == 1); +} + +void nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType, + const nsAString* aStringValue) { + if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE || + aValue < NS_ATTRVALUE_INTEGERTYPE_MINVALUE) { + MiscContainer* cont = EnsureEmptyMiscContainer(); + switch (aType) { + case eInteger: { + cont->mValue.mInteger = aValue; + break; + } + case ePercent: { + cont->mDoubleValue = aValue; + break; + } + case eEnum: { + cont->mValue.mEnumValue = aValue; + break; + } + default: { + MOZ_ASSERT_UNREACHABLE("unknown integer type"); + break; + } + } + cont->mType = aType; + SetMiscAtomOrString(aStringValue); + } else { + NS_ASSERTION(!mBits, "Reset before calling SetIntValueAndType!"); + mBits = (aValue * NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER) | aType; + } +} + +void nsAttrValue::SetDoubleValueAndType(double aValue, ValueType aType, + const nsAString* aStringValue) { + MOZ_ASSERT(aType == eDoubleValue || aType == ePercent, "Unexpected type"); + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mDoubleValue = aValue; + cont->mType = aType; + SetMiscAtomOrString(aStringValue); +} + +nsAtom* nsAttrValue::GetStoredAtom() const { + if (BaseType() == eAtomBase) { + return static_cast(GetPtr()); + } + if (BaseType() == eOtherBase) { + return GetMiscContainer()->GetStoredAtom(); + } + return nullptr; +} + +nsStringBuffer* nsAttrValue::GetStoredStringBuffer() const { + if (BaseType() == eStringBase) { + return static_cast(GetPtr()); + } + if (BaseType() == eOtherBase) { + return GetMiscContainer()->GetStoredStringBuffer(); + } + return nullptr; +} + +int16_t nsAttrValue::GetEnumTableIndex(const EnumTable* aTable) { + int16_t index = sEnumTableArray->IndexOf(aTable); + if (index < 0) { + index = sEnumTableArray->Length(); + NS_ASSERTION(index <= NS_ATTRVALUE_ENUMTABLEINDEX_MAXVALUE, + "too many enum tables"); + sEnumTableArray->AppendElement(aTable); + } + + return index; +} + +int32_t nsAttrValue::EnumTableEntryToValue(const EnumTable* aEnumTable, + const EnumTable* aTableEntry) { + int16_t index = GetEnumTableIndex(aEnumTable); + int32_t value = + (aTableEntry->value << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) + index; + return value; +} + +bool nsAttrValue::ParseEnumValue(const nsAString& aValue, + const EnumTable* aTable, bool aCaseSensitive, + const EnumTable* aDefaultValue) { + ResetIfSet(); + const EnumTable* tableEntry = aTable; + + while (tableEntry->tag) { + if (aCaseSensitive ? aValue.EqualsASCII(tableEntry->tag) + : aValue.LowerCaseEqualsASCII(tableEntry->tag)) { + int32_t value = EnumTableEntryToValue(aTable, tableEntry); + + bool equals = aCaseSensitive || aValue.EqualsASCII(tableEntry->tag); + if (!equals) { + nsAutoString tag; + tag.AssignASCII(tableEntry->tag); + nsContentUtils::ASCIIToUpper(tag); + if ((equals = tag.Equals(aValue))) { + value |= NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER; + } + } + SetIntValueAndType(value, eEnum, equals ? nullptr : &aValue); + NS_ASSERTION(GetEnumValue() == tableEntry->value, + "failed to store enum properly"); + + return true; + } + tableEntry++; + } + + if (aDefaultValue) { + MOZ_ASSERT(aTable <= aDefaultValue && aDefaultValue < tableEntry, + "aDefaultValue not inside aTable?"); + SetIntValueAndType(EnumTableEntryToValue(aTable, aDefaultValue), eEnum, + &aValue); + return true; + } + + return false; +} + +bool nsAttrValue::DoParseHTMLDimension(const nsAString& aInput, + bool aEnsureNonzero) { + ResetIfSet(); + + // We don't use nsContentUtils::ParseHTMLInteger here because we + // need a bunch of behavioral differences from it. We _could_ try to + // use it, but it would not be a great fit. + + // https://html.spec.whatwg.org/multipage/#rules-for-parsing-dimension-values + + // Steps 1 and 2. + const char16_t* position = aInput.BeginReading(); + const char16_t* end = aInput.EndReading(); + + // We will need to keep track of whether this was a canonical representation + // or not. It's non-canonical if it has leading whitespace, leading '+', + // leading '0' characters, or trailing garbage. + bool canonical = true; + + // Step 3. + while (position != end && nsContentUtils::IsHTMLWhitespace(*position)) { + canonical = false; // Leading whitespace + ++position; + } + + // Step 4. + if (position == end || *position < char16_t('0') || + *position > char16_t('9')) { + return false; + } + + // Step 5. + CheckedInt32 value = 0; + + // Collect up leading '0' first to avoid extra branching in the main + // loop to set 'canonical' properly. + while (position != end && *position == char16_t('0')) { + canonical = false; // Leading '0' + ++position; + } + + // Now collect up other digits. + while (position != end && *position >= char16_t('0') && + *position <= char16_t('9')) { + value = value * 10 + (*position - char16_t('0')); + if (!value.isValid()) { + // The spec assumes we can deal with arbitrary-size integers here, but we + // really can't. If someone sets something too big, just bail out and + // ignore it. + return false; + } + ++position; + } + + // Step 6 is implemented implicitly via the various "position != end" guards + // from this point on. + + Maybe doubleValue; + // Step 7. The return in step 7.2 is handled by just falling through to the + // code below this block when we reach end of input or a non-digit, because + // the while loop will terminate at that point. + if (position != end && *position == char16_t('.')) { + canonical = false; // Let's not rely on double serialization reproducing + // the string we started with. + // Step 7.1. + ++position; + // If we have a '.' _not_ followed by digits, this is not as efficient as it + // could be, because we will store as a double while we could have stored as + // an int. But that seems like a pretty rare case. + doubleValue.emplace(value.value()); + // Step 7.3. + double divisor = 1.0f; + // Step 7.4. + while (position != end && *position >= char16_t('0') && + *position <= char16_t('9')) { + // Step 7.4.1. + divisor = divisor * 10.0f; + // Step 7.4.2. + doubleValue.ref() += (*position - char16_t('0')) / divisor; + // Step 7.4.3. + ++position; + // Step 7.4.4 and 7.4.5 are captured in the while loop condition and the + // "position != end" checks below. + } + } + + if (aEnsureNonzero && value.value() == 0 && + (!doubleValue || *doubleValue == 0.0f)) { + // Not valid. Just drop it. + return false; + } + + // Step 8 and the spec's early return from step 7.2. + ValueType type; + if (position != end && *position == char16_t('%')) { + type = ePercent; + ++position; + } else if (doubleValue) { + type = eDoubleValue; + } else { + type = eInteger; + } + + if (position != end) { + canonical = false; + } + + if (doubleValue) { + MOZ_ASSERT(!canonical, "We set it false above!"); + SetDoubleValueAndType(*doubleValue, type, &aInput); + } else { + SetIntValueAndType(value.value(), type, canonical ? nullptr : &aInput); + } + +#ifdef DEBUG + nsAutoString str; + ToString(str); + MOZ_ASSERT(str == aInput, "We messed up our 'canonical' boolean!"); +#endif + + return true; +} + +bool nsAttrValue::ParseIntWithBounds(const nsAString& aString, int32_t aMin, + int32_t aMax) { + MOZ_ASSERT(aMin < aMax, "bad boundaries"); + + ResetIfSet(); + + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result); + if (result & nsContentUtils::eParseHTMLInteger_Error) { + return false; + } + + int32_t val = std::max(originalVal, aMin); + val = std::min(val, aMax); + bool nonStrict = + (val != originalVal) || + (result & nsContentUtils::eParseHTMLInteger_NonStandard) || + (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput); + + SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr); + + return true; +} + +void nsAttrValue::ParseIntWithFallback(const nsAString& aString, + int32_t aDefault, int32_t aMax) { + ResetIfSet(); + + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t val = nsContentUtils::ParseHTMLInteger(aString, &result); + bool nonStrict = false; + if ((result & nsContentUtils::eParseHTMLInteger_Error) || val < 1) { + val = aDefault; + nonStrict = true; + } + + if (val > aMax) { + val = aMax; + nonStrict = true; + } + + if ((result & nsContentUtils::eParseHTMLInteger_NonStandard) || + (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)) { + nonStrict = true; + } + + SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr); +} + +void nsAttrValue::ParseClampedNonNegativeInt(const nsAString& aString, + int32_t aDefault, int32_t aMin, + int32_t aMax) { + ResetIfSet(); + + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t val = nsContentUtils::ParseHTMLInteger(aString, &result); + bool nonStrict = + (result & nsContentUtils::eParseHTMLInteger_NonStandard) || + (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput); + + if (result & nsContentUtils::eParseHTMLInteger_ErrorOverflow) { + if (result & nsContentUtils::eParseHTMLInteger_Negative) { + val = aDefault; + } else { + val = aMax; + } + nonStrict = true; + } else if ((result & nsContentUtils::eParseHTMLInteger_Error) || val < 0) { + val = aDefault; + nonStrict = true; + } else if (val < aMin) { + val = aMin; + nonStrict = true; + } else if (val > aMax) { + val = aMax; + nonStrict = true; + } + + SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr); +} + +bool nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString) { + ResetIfSet(); + + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result); + if ((result & nsContentUtils::eParseHTMLInteger_Error) || originalVal < 0) { + return false; + } + + bool nonStrict = + (result & nsContentUtils::eParseHTMLInteger_NonStandard) || + (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput); + + SetIntValueAndType(originalVal, eInteger, nonStrict ? &aString : nullptr); + + return true; +} + +bool nsAttrValue::ParsePositiveIntValue(const nsAString& aString) { + ResetIfSet(); + + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result); + if ((result & nsContentUtils::eParseHTMLInteger_Error) || originalVal <= 0) { + return false; + } + + bool nonStrict = + (result & nsContentUtils::eParseHTMLInteger_NonStandard) || + (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput); + + SetIntValueAndType(originalVal, eInteger, nonStrict ? &aString : nullptr); + + return true; +} + +void nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString) { + nsStringBuffer* buf = GetStringBuffer(aString).take(); + if (!buf) { + return; + } + + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mValue.mColor = aColor; + cont->mType = eColor; + + // Save the literal string we were passed for round-tripping. + cont->SetStringBitsMainThread(reinterpret_cast(buf) | eStringBase); +} + +bool nsAttrValue::ParseColor(const nsAString& aString) { + ResetIfSet(); + + // FIXME (partially, at least): HTML5's algorithm says we shouldn't do + // the whitespace compression, trimming, or the test for emptiness. + // (I'm a little skeptical that we shouldn't do the whitespace + // trimming; WebKit also does it.) + nsAutoString colorStr(aString); + colorStr.CompressWhitespace(true, true); + if (colorStr.IsEmpty()) { + return false; + } + + nscolor color; + // No color names begin with a '#'; in standards mode, all acceptable + // numeric colors do. + if (colorStr.First() == '#') { + nsDependentString withoutHash(colorStr.get() + 1, colorStr.Length() - 1); + if (NS_HexToRGBA(withoutHash, nsHexColorType::NoAlpha, &color)) { + SetColorValue(color, aString); + return true; + } + } else if (colorStr.LowerCaseEqualsLiteral("transparent")) { + SetColorValue(NS_RGBA(0, 0, 0, 0), aString); + return true; + } else { + const NS_ConvertUTF16toUTF8 colorNameU8(colorStr); + if (Servo_ColorNameToRgb(&colorNameU8, &color)) { + SetColorValue(color, aString); + return true; + } + } + + // FIXME (maybe): HTML5 says we should handle system colors. This + // means we probably need another storage type, since we'd need to + // handle dynamic changes. However, I think this is a bad idea: + // http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-May/026449.html + + // Use NS_LooseHexToRGB as a fallback if nothing above worked. + if (NS_LooseHexToRGB(colorStr, &color)) { + SetColorValue(color, aString); + return true; + } + + return false; +} + +bool nsAttrValue::ParseDoubleValue(const nsAString& aString) { + ResetIfSet(); + + nsresult ec; + double val = PromiseFlatString(aString).ToDouble(&ec); + if (NS_FAILED(ec)) { + return false; + } + + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mDoubleValue = val; + cont->mType = eDoubleValue; + nsAutoString serializedFloat; + serializedFloat.AppendFloat(val); + SetMiscAtomOrString(serializedFloat.Equals(aString) ? nullptr : &aString); + return true; +} + +bool nsAttrValue::ParseStyleAttribute(const nsAString& aString, + nsIPrincipal* aMaybeScriptedPrincipal, + nsStyledElement* aElement) { + dom::Document* doc = aElement->OwnerDoc(); + AttributeStyles* attrStyles = doc->GetAttributeStyles(); + NS_ASSERTION(aElement->NodePrincipal() == doc->NodePrincipal(), + "This is unexpected"); + + nsIPrincipal* principal = aMaybeScriptedPrincipal ? aMaybeScriptedPrincipal + : aElement->NodePrincipal(); + RefPtr data = aElement->GetURLDataForStyleAttr(principal); + + // If the (immutable) document URI does not match the element's base URI + // (the common case is that they do match) do not cache the rule. This is + // because the results of the CSS parser are dependent on these URIs, and we + // do not want to have to account for the URIs in the hash lookup. + // Similarly, if the triggering principal does not match the node principal, + // do not cache the rule, since the principal will be encoded in any parsed + // URLs in the rule. + const bool cachingAllowed = attrStyles && + doc->GetDocumentURI() == data->BaseURI() && + principal == aElement->NodePrincipal(); + if (cachingAllowed) { + if (MiscContainer* cont = attrStyles->LookupStyleAttr(aString)) { + // Set our MiscContainer to the cached one. + NS_ADDREF(cont); + SetPtrValueAndType(cont, eOtherBase); + return true; + } + } + + RefPtr decl = + DeclarationBlock::FromCssText(aString, data, doc->GetCompatibilityMode(), + doc->CSSLoader(), StyleCssRuleType::Style); + if (!decl) { + return false; + } + decl->SetAttributeStyles(attrStyles); + SetTo(decl.forget(), &aString); + + if (cachingAllowed) { + MiscContainer* cont = GetMiscContainer(); + cont->Cache(); + } + + return true; +} + +void nsAttrValue::SetMiscAtomOrString(const nsAString* aValue) { + NS_ASSERTION(GetMiscContainer(), "Must have MiscContainer!"); + NS_ASSERTION(!GetMiscContainer()->mStringBits || IsInServoTraversal(), + "Trying to re-set atom or string!"); + if (aValue) { + uint32_t len = aValue->Length(); + // * We're allowing eCSSDeclaration attributes to store empty + // strings as it can be beneficial to store an empty style + // attribute as a parsed rule. + // * We're allowing enumerated values because sometimes the empty + // string corresponds to a particular enumerated value, especially + // for enumerated values that are not limited enumerated. + // Add other types as needed. + NS_ASSERTION(len || Type() == eCSSDeclaration || Type() == eEnum, + "Empty string?"); + MiscContainer* cont = GetMiscContainer(); + + if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) { + nsAtom* atom = MOZ_LIKELY(!IsInServoTraversal()) + ? NS_AtomizeMainThread(*aValue).take() + : NS_Atomize(*aValue).take(); + NS_ENSURE_TRUE_VOID(atom); + uintptr_t bits = reinterpret_cast(atom) | eAtomBase; + + // In the common case we're not in the servo traversal, and we can just + // set the bits normally. The parallel case requires more care. + if (MOZ_LIKELY(!IsInServoTraversal())) { + cont->SetStringBitsMainThread(bits); + } else if (!cont->mStringBits.compareExchange(0, bits)) { + // We raced with somebody else setting the bits. Release our copy. + atom->Release(); + } + } else { + nsStringBuffer* buffer = GetStringBuffer(*aValue).take(); + NS_ENSURE_TRUE_VOID(buffer); + uintptr_t bits = reinterpret_cast(buffer) | eStringBase; + + // In the common case we're not in the servo traversal, and we can just + // set the bits normally. The parallel case requires more care. + if (MOZ_LIKELY(!IsInServoTraversal())) { + cont->SetStringBitsMainThread(bits); + } else if (!cont->mStringBits.compareExchange(0, bits)) { + // We raced with somebody else setting the bits. Release our copy. + buffer->Release(); + } + } + } +} + +void nsAttrValue::ResetMiscAtomOrString() { + MiscContainer* cont = GetMiscContainer(); + bool isString; + if (void* ptr = cont->GetStringOrAtomPtr(isString)) { + if (isString) { + static_cast(ptr)->Release(); + } else { + static_cast(ptr)->Release(); + } + cont->SetStringBitsMainThread(0); + } +} + +void nsAttrValue::SetSVGType(ValueType aType, const void* aValue, + const nsAString* aSerialized) { + MOZ_ASSERT(IsSVGType(aType), "Not an SVG type"); + + MiscContainer* cont = EnsureEmptyMiscContainer(); + // All SVG types are just pointers to classes so just setting any of them + // will do. We'll lose type-safety but the signature of the calling + // function should ensure we don't get anything unexpected, and once we + // stick aValue in a union we lose type information anyway. + cont->mValue.mSVGLength = static_cast(aValue); + cont->mType = aType; + SetMiscAtomOrString(aSerialized); +} + +MiscContainer* nsAttrValue::ClearMiscContainer() { + MiscContainer* cont = nullptr; + if (BaseType() == eOtherBase) { + cont = GetMiscContainer(); + if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { + // This MiscContainer is shared, we need a new one. + NS_RELEASE(cont); + + cont = AllocMiscContainer(); + SetPtrValueAndType(cont, eOtherBase); + } else { + switch (cont->mType) { + case eCSSDeclaration: { + MOZ_ASSERT(cont->mValue.mRefCount == 1); + cont->Release(); + cont->Evict(); + NS_RELEASE(cont->mValue.mCSSDeclaration); + break; + } + case eShadowParts: { + MOZ_ASSERT(cont->mValue.mRefCount == 1); + cont->Release(); + delete cont->mValue.mShadowParts; + break; + } + case eURL: { + NS_RELEASE(cont->mValue.mURL); + break; + } + case eAtomArray: { + MOZ_ASSERT(cont->mValue.mRefCount == 1); + cont->Release(); + cont->Evict(); + delete cont->mValue.mAtomArray; + break; + } + default: { + break; + } + } + } + ResetMiscAtomOrString(); + } else { + ResetIfSet(); + } + + return cont; +} + +MiscContainer* nsAttrValue::EnsureEmptyMiscContainer() { + MiscContainer* cont = ClearMiscContainer(); + if (cont) { + MOZ_ASSERT(BaseType() == eOtherBase); + ResetMiscAtomOrString(); + cont = GetMiscContainer(); + } else { + cont = AllocMiscContainer(); + SetPtrValueAndType(cont, eOtherBase); + } + + return cont; +} + +already_AddRefed nsAttrValue::GetStringBuffer( + const nsAString& aValue) const { + uint32_t len = aValue.Length(); + if (!len) { + return nullptr; + } + + RefPtr buf = nsStringBuffer::FromString(aValue); + if (buf && (buf->StorageSize() / sizeof(char16_t) - 1) == len) { + // We can only reuse the buffer if it's exactly sized, since we rely on + // StorageSize() to get the string length in ToString(). + return buf.forget(); + } + return nsStringBuffer::Create(aValue.Data(), aValue.Length()); +} + +size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + size_t n = 0; + + switch (BaseType()) { + case eStringBase: { + nsStringBuffer* str = static_cast(GetPtr()); + n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0; + break; + } + case eOtherBase: { + MiscContainer* container = GetMiscContainer(); + if (!container) { + break; + } + if (container->IsRefCounted() && container->mValue.mRefCount > 1) { + // We don't report this MiscContainer at all in order to avoid + // twice-reporting it. + // TODO DMD, bug 1027551 - figure out how to report this ref-counted + // object just once. + break; + } + n += aMallocSizeOf(container); + + // We only count the size of the object pointed by otherPtr if it's a + // string. When it's an atom, it's counted separatly. + if (nsStringBuffer* buf = container->GetStoredStringBuffer()) { + n += buf->SizeOfIncludingThisIfUnshared(aMallocSizeOf); + } + + if (Type() == eCSSDeclaration && container->mValue.mCSSDeclaration) { + // TODO: mCSSDeclaration might be owned by another object which + // would make us count them twice, bug 677493. + // Bug 1281964: For DeclarationBlock if we do measure we'll + // need a way to call the Servo heap_size_of function. + // n += container->mCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf); + } else if (Type() == eAtomArray && container->mValue.mAtomArray) { + // Don't measure each nsAtom, they are measured separatly. + n += container->mValue.mAtomArray->mArray.ShallowSizeOfIncludingThis( + aMallocSizeOf); + } + break; + } + case eAtomBase: // Atoms are counted separately. + case eIntegerBase: // The value is in mBits, nothing to do. + break; + } + + return n; +} diff --git a/dom/base/nsAttrValue.h b/dom/base/nsAttrValue.h new file mode 100644 index 0000000000..4ef63c287f --- /dev/null +++ b/dom/base/nsAttrValue.h @@ -0,0 +1,577 @@ +/* -*- 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/. */ + +/* + * A struct that represents the value (type and actual data) of an + * attribute. + */ + +#ifndef nsAttrValue_h___ +#define nsAttrValue_h___ + +#include + +#include "nscore.h" +#include "nsString.h" +#include "nsStringBuffer.h" +#include "nsColor.h" +#include "nsCaseTreatment.h" +#include "nsMargin.h" +#include "nsStringFwd.h" +#include "nsTArrayForwardDeclare.h" +#include "nsAtom.h" +#include "mozilla/AtomArray.h" +#include "mozilla/EnumTypeTraits.h" +#include "mozilla/MemoryReporting.h" + +class nsIPrincipal; +class nsIURI; +class nsStyledElement; +struct MiscContainer; + +namespace mozilla { +class DeclarationBlock; +class ShadowParts; +class SVGAnimatedIntegerPair; +class SVGAnimatedLength; +class SVGAnimatedNumberPair; +class SVGAnimatedOrient; +class SVGAnimatedPreserveAspectRatio; +class SVGAnimatedViewBox; +class SVGLengthList; +class SVGNumberList; +class SVGPathData; +class SVGPointList; +class SVGStringList; +class SVGTransformList; + +struct AttrAtomArray { + AtomArray mArray; + mutable bool mMayContainDuplicates = false; + UniquePtr CreateDeduplicatedCopyIfDifferent() const { + if (!mMayContainDuplicates) { + return nullptr; + } + return CreateDeduplicatedCopyIfDifferentImpl(); + } + bool operator==(const AttrAtomArray& aOther) const { + return mArray == aOther.mArray; + } + + private: + UniquePtr CreateDeduplicatedCopyIfDifferentImpl() const; +}; + +namespace dom { +class DOMString; +} +} // namespace mozilla + +#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12 + +const uintptr_t NS_ATTRVALUE_BASETYPE_MASK = 3; +#define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK) + +#define NS_ATTRVALUE_INTEGERTYPE_BITS 4 +#define NS_ATTRVALUE_INTEGERTYPE_MASK \ + (uintptr_t((1 << NS_ATTRVALUE_INTEGERTYPE_BITS) - 1)) +#define NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER (1 << NS_ATTRVALUE_INTEGERTYPE_BITS) +#define NS_ATTRVALUE_INTEGERTYPE_MAXVALUE \ + ((1 << (31 - NS_ATTRVALUE_INTEGERTYPE_BITS)) - 1) +#define NS_ATTRVALUE_INTEGERTYPE_MINVALUE \ + (-NS_ATTRVALUE_INTEGERTYPE_MAXVALUE - 1) + +#define NS_ATTRVALUE_ENUMTABLEINDEX_BITS \ + (32 - 16 - NS_ATTRVALUE_INTEGERTYPE_BITS) +#define NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER \ + (1 << (NS_ATTRVALUE_ENUMTABLEINDEX_BITS - 1)) +#define NS_ATTRVALUE_ENUMTABLEINDEX_MAXVALUE \ + (NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER - 1) +#define NS_ATTRVALUE_ENUMTABLEINDEX_MASK \ + (uintptr_t((((1 << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) - 1) & \ + ~NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER))) + +/** + * A class used to construct a nsString from a nsStringBuffer (we might + * want to move this to nsString at some point). + * + * WARNING: Note that nsCheapString doesn't take an explicit length -- it + * assumes the string is maximally large, given the nsStringBuffer's storage + * size. This means the given string buffer *must* be sized exactly correctly + * for the string it contains (including one byte for a null terminator). If + * it has any unused storage space, then that will result in bogus characters + * at the end of our nsCheapString. + */ +class nsCheapString : public nsString { + public: + explicit nsCheapString(nsStringBuffer* aBuf) { + if (aBuf) aBuf->ToString(aBuf->StorageSize() / sizeof(char16_t) - 1, *this); + } +}; + +class nsAttrValue { + friend struct MiscContainer; + + public: + // This has to be the same as in ValueBaseType + enum ValueType { + eString = 0x00, // 00 + // 01 this value indicates a 'misc' struct + eAtom = 0x02, // 10 + eInteger = 0x03, // 0011 + eColor = 0x07, // 0111 + eEnum = 0x0B, // 1011 This should eventually die + ePercent = 0x0F, // 1111 + // Values below here won't matter, they'll be always stored in the 'misc' + // struct. + eCSSDeclaration = 0x10, + eURL, + eImage, + eAtomArray, + eDoubleValue, + // eShadowParts is refcounted in the misc container, as we do copy attribute + // values quite a bit (for example to process style invalidation), and the + // underlying value could get expensive to copy. + eShadowParts, + eSVGIntegerPair, + eSVGTypesBegin = eSVGIntegerPair, + eSVGOrient, + eSVGLength, + eSVGLengthList, + eSVGNumberList, + eSVGNumberPair, + eSVGPathData, + eSVGPointList, + eSVGPreserveAspectRatio, + eSVGStringList, + eSVGTransformList, + eSVGViewBox, + eSVGTypesEnd = eSVGViewBox, + }; + + nsAttrValue(); + nsAttrValue(const nsAttrValue& aOther); + explicit nsAttrValue(const nsAString& aValue); + explicit nsAttrValue(nsAtom* aValue); + nsAttrValue(already_AddRefed aValue, + const nsAString* aSerialized); + ~nsAttrValue(); + + inline const nsAttrValue& operator=(const nsAttrValue& aOther); + + static void Init(); + static void Shutdown(); + + inline ValueType Type() const; + // Returns true when this value is self-contained and does not depend on + // the state of its associated element. + // Returns false when this value depends on the state of its associated + // element and may be invalid if that state has been changed by changes to + // that element state outside of attribute setting. + inline bool StoresOwnData() const; + + void Reset(); + + void SetTo(const nsAttrValue& aOther); + void SetTo(const nsAString& aValue); + void SetTo(nsAtom* aValue); + void SetTo(int16_t aInt); + void SetTo(int32_t aInt, const nsAString* aSerialized); + void SetTo(double aValue, const nsAString* aSerialized); + void SetTo(already_AddRefed aValue, + const nsAString* aSerialized); + void SetTo(nsIURI* aValue, const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedIntegerPair& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedLength& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedNumberPair& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedOrient& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGAnimatedViewBox& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGLengthList& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGNumberList& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGPathData& aValue, const nsAString* aSerialized); + void SetTo(const mozilla::SVGPointList& aValue, const nsAString* aSerialized); + void SetTo(const mozilla::SVGStringList& aValue, + const nsAString* aSerialized); + void SetTo(const mozilla::SVGTransformList& aValue, + const nsAString* aSerialized); + + /** + * Sets this object with the string or atom representation of aValue. + * + * After calling this method, this object will have type eString unless the + * type of aValue is eAtom, in which case this object will also have type + * eAtom. + */ + void SetToSerialized(const nsAttrValue& aValue); + + void SwapValueWith(nsAttrValue& aOther); + + void RemoveDuplicatesFromAtomArray(); + + void ToString(nsAString& aResult) const; + inline void ToString(mozilla::dom::DOMString& aResult) const; + + /** + * Returns the value of this object as an atom. If necessary, the value will + * first be serialised using ToString before converting to an atom. + */ + already_AddRefed GetAsAtom() const; + + // Methods to get value. These methods do not convert so only use them + // to retrieve the datatype that this nsAttrValue has. + inline bool IsEmptyString() const; + const nsCheapString GetStringValue() const; + inline nsAtom* GetAtomValue() const; + inline int32_t GetIntegerValue() const; + bool GetColorValue(nscolor& aColor) const; + inline int16_t GetEnumValue() const; + inline double GetPercentValue() const; + inline const mozilla::AttrAtomArray* GetAtomArrayValue() const; + inline mozilla::DeclarationBlock* GetCSSDeclarationValue() const; + inline nsIURI* GetURLValue() const; + inline double GetDoubleValue() const; + inline const mozilla::ShadowParts& GetShadowPartsValue() const; + + /** + * Returns the string corresponding to the stored enum value. + * + * @param aResult the string representing the enum tag + * @param aRealTag wheter we want to have the real tag or the saved one + */ + void GetEnumString(nsAString& aResult, bool aRealTag) const; + + // Methods to get access to atoms we may have + // Returns the number of atoms we have; 0 if we have none. It's OK + // to call this without checking the type first; it handles that. + uint32_t GetAtomCount() const; + // Returns the atom at aIndex (0-based). Do not call this with + // aIndex >= GetAtomCount(). + nsAtom* AtomAt(int32_t aIndex) const; + + uint32_t HashValue() const; + bool Equals(const nsAttrValue& aOther) const; + // aCaseSensitive == eIgnoreCase means ASCII case-insenstive matching + bool Equals(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const; + bool Equals(const nsAtom* aValue, nsCaseTreatment aCaseSensitive) const; + bool HasPrefix(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const; + bool HasSuffix(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const; + bool HasSubstring(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const; + + /** + * Compares this object with aOther according to their string representation. + * + * For example, when called on an object with type eInteger and value 4, and + * given aOther of type eString and value "4", EqualsAsStrings will return + * true (while Equals will return false). + */ + bool EqualsAsStrings(const nsAttrValue& aOther) const; + + /** + * Returns true if this AttrValue is equal to the given atom, or is an + * array which contains the given atom. + */ + bool Contains(nsAtom* aValue, nsCaseTreatment aCaseSensitive) const; + /** + * Returns true if this AttrValue is an atom equal to the given + * string, or is an array of atoms which contains the given string. + * This always does a case-sensitive comparison. + */ + bool Contains(const nsAString& aValue) const; + + void ParseAtom(const nsAString& aValue); + void ParseAtomArray(const nsAString& aValue); + void ParseAtomArray(nsAtom* aValue); + void ParseStringOrAtom(const nsAString& aValue); + + /** + * Parses an exportparts attribute. + * + * https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list + */ + void ParsePartMapping(const nsAString&); + + /** + * Structure for a mapping from int (enum) values to strings. When you use + * it you generally create an array of them. + * Instantiate like this: + * EnumTable myTable[] = { + * { "string1", 1 }, + * { "string2", 2 }, + * { nullptr, 0 } + * } + */ + struct EnumTable { + // EnumTable can be initialized either with an int16_t value + // or a value of an enumeration type that can fit within an int16_t. + + constexpr EnumTable(const char* aTag, int16_t aValue) + : tag(aTag), value(aValue) {} + + template ::value>::type> + constexpr EnumTable(const char* aTag, T aValue) + : tag(aTag), value(static_cast(aValue)) { + static_assert(mozilla::EnumTypeFitsWithin::value, + "aValue must be an enum that fits within int16_t"); + // TODO: statically assert there are no duplicate values, otherwise + // `GetEnumString()` above will return wrong values. + } + + /** The string the value maps to */ + const char* tag; + /** The enum value that maps to this string */ + int16_t value; + }; + + /** + * Parse into an enum value. + * + * @param aValue the string to find the value for + * @param aTable the enumeration to map with + * @param aCaseSensitive specify if the parsing has to be case sensitive + * @param aDefaultValue if non-null, this function will always return true. + * Failure to parse aValue as one of the values in aTable will just + * cause aDefaultValue->value to be stored as the enumeration value. + * @return whether the enum value was found or not + */ + bool ParseEnumValue(const nsAString& aValue, const EnumTable* aTable, + bool aCaseSensitive, + const EnumTable* aDefaultValue = nullptr); + + /** + * Parse a string into a dimension value. This is similar to + * https://html.spec.whatwg.org/multipage/#rules-for-parsing-dimension-values + * but drops the fractional part of the value for now, until we figure out how + * to store that in our nsAttrValue. + * + * The resulting value (if the parse succeeds) is one of eInteger, + * eDoubleValue, or ePercent, depending on whether we found a fractional part + * and whether we found '%' at the end of the value. + * + * @param aInput the string to parse + * @return whether the value could be parsed + */ + bool ParseHTMLDimension(const nsAString& aInput) { + return DoParseHTMLDimension(aInput, false); + } + + /** + * Parse a string into a nonzero dimension value. This implements + * https://html.spec.whatwg.org/multipage/#rules-for-parsing-non-zero-dimension-values + * subject to the same constraints as ParseHTMLDimension above. + * + * @param aInput the string to parse + * @return whether the value could be parsed + */ + bool ParseNonzeroHTMLDimension(const nsAString& aInput) { + return DoParseHTMLDimension(aInput, true); + } + + /** + * Parse a string value into an integer. + * + * @param aString the string to parse + * @return whether the value could be parsed + */ + bool ParseIntValue(const nsAString& aString) { + return ParseIntWithBounds(aString, INT32_MIN, INT32_MAX); + } + + /** + * Parse a string value into an integer with minimum value and maximum value. + * + * @param aString the string to parse + * @param aMin the minimum value (if value is less it will be bumped up) + * @param aMax the maximum value (if value is greater it will be chopped down) + * @return whether the value could be parsed + */ + bool ParseIntWithBounds(const nsAString& aString, int32_t aMin, + int32_t aMax = INT32_MAX); + + /** + * Parse a string value into an integer with a fallback for invalid values. + * Also allows clamping to a maximum value to support col/colgroup.span (this + * is not per spec right now). + * + * @param aString the string to parse + * @param aDefault the default value + * @param aMax the maximum value (if value is greater it will be clamped) + */ + void ParseIntWithFallback(const nsAString& aString, int32_t aDefault, + int32_t aMax = INT32_MAX); + + /** + * Parse a string value into a non-negative integer. + * This method follows the rules for parsing non-negative integer from: + * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers + * + * @param aString the string to parse + * @return whether the value is valid + */ + bool ParseNonNegativeIntValue(const nsAString& aString); + + /** + * Parse a string value into a clamped non-negative integer. + * This method follows the rules for parsing non-negative integer from: + * https://html.spec.whatwg.org/multipage/infrastructure.html#clamped-to-the-range + * + * @param aString the string to parse + * @param aDefault value to return for negative or invalid values + * @param aMin minimum value + * @param aMax maximum value + */ + void ParseClampedNonNegativeInt(const nsAString& aString, int32_t aDefault, + int32_t aMin, int32_t aMax); + + /** + * Parse a string value into a positive integer. + * This method follows the rules for parsing non-negative integer from: + * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers + * In addition of these rules, the value has to be greater than zero. + * + * This is generally used for parsing content attributes which reflecting IDL + * attributes are limited to only non-negative numbers greater than zero, see: + * http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero + * + * @param aString the string to parse + * @return whether the value was valid + */ + bool ParsePositiveIntValue(const nsAString& aString); + + /** + * Parse a string into a color. This implements what HTML5 calls the + * "rules for parsing a legacy color value". + * + * @param aString the string to parse + * @return whether the value could be parsed + */ + bool ParseColor(const nsAString& aString); + + /** + * Parse a string value into a double-precision floating point value. + * + * @param aString the string to parse + * @return whether the value could be parsed + */ + bool ParseDoubleValue(const nsAString& aString); + + /** + * Parse a string into a CSS style rule. + * + * @param aString the style attribute value to be parsed. + * @param aElement the element the attribute is set on. + * @param aMaybeScriptedPrincipal if available, the scripted principal + * responsible for this attribute value, as passed to + * Element::ParseAttribute. + */ + bool ParseStyleAttribute(const nsAString& aString, + nsIPrincipal* aMaybeScriptedPrincipal, + nsStyledElement* aElement); + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + nsAtom* GetStoredAtom() const; + nsStringBuffer* GetStoredStringBuffer() const; + + private: + // These have to be the same as in ValueType + enum ValueBaseType { + eStringBase = eString, // 00 + eOtherBase = 0x01, // 01 + eAtomBase = eAtom, // 10 + eIntegerBase = 0x03 // 11 + }; + + inline ValueBaseType BaseType() const; + inline bool IsSVGType(ValueType aType) const; + + /** + * Get the index of an EnumTable in the sEnumTableArray. + * If the EnumTable is not in the sEnumTableArray, it is added. + * + * @param aTable the EnumTable to get the index of. + * @return the index of the EnumTable. + */ + int16_t GetEnumTableIndex(const EnumTable* aTable); + + inline void SetPtrValueAndType(void* aValue, ValueBaseType aType); + void SetIntValueAndType(int32_t aValue, ValueType aType, + const nsAString* aStringValue); + // aType can be ePercent or eDoubleValue. + void SetDoubleValueAndType(double aValue, ValueType aType, + const nsAString* aStringValue); + void SetColorValue(nscolor aColor, const nsAString& aString); + void SetMiscAtomOrString(const nsAString* aValue); + void ResetMiscAtomOrString(); + void SetSVGType(ValueType aType, const void* aValue, + const nsAString* aSerialized); + inline void ResetIfSet(); + + inline void* GetPtr() const; + inline MiscContainer* GetMiscContainer() const; + inline int32_t GetIntInternal() const; + + // Clears the current MiscContainer. This will return null if there is no + // existing container. + MiscContainer* ClearMiscContainer(); + // Like ClearMiscContainer, except allocates a new container if one does not + // exist already. + MiscContainer* EnsureEmptyMiscContainer(); + already_AddRefed GetStringBuffer( + const nsAString& aValue) const; + // Given an enum table and a particular entry in that table, return + // the actual integer value we should store. + int32_t EnumTableEntryToValue(const EnumTable* aEnumTable, + const EnumTable* aTableEntry); + + template + bool SubstringCheck(const nsAString& aValue, + nsCaseTreatment aCaseSensitive) const; + + static MiscContainer* AllocMiscContainer(); + static void DeallocMiscContainer(MiscContainer* aCont); + + static nsTArray* sEnumTableArray; + + /** + * Helper for ParseHTMLDimension and ParseNonzeroHTMLDimension. + * + * @param aInput the string to parse + * @param aEnsureNonzero whether to fail the parse if the value is 0 + * @return whether the value could be parsed + */ + bool DoParseHTMLDimension(const nsAString& aInput, bool aEnsureNonzero); + + uintptr_t mBits; +}; + +inline const nsAttrValue& nsAttrValue::operator=(const nsAttrValue& aOther) { + SetTo(aOther); + return *this; +} + +inline nsAttrValue::ValueBaseType nsAttrValue::BaseType() const { + return static_cast(mBits & NS_ATTRVALUE_BASETYPE_MASK); +} + +inline void* nsAttrValue::GetPtr() const { + NS_ASSERTION(BaseType() != eIntegerBase, "getting pointer from non-pointer"); + return reinterpret_cast(mBits & NS_ATTRVALUE_POINTERVALUE_MASK); +} + +inline bool nsAttrValue::IsEmptyString() const { return !mBits; } + +#endif diff --git a/dom/base/nsAttrValueInlines.h b/dom/base/nsAttrValueInlines.h new file mode 100644 index 0000000000..b15451237c --- /dev/null +++ b/dom/base/nsAttrValueInlines.h @@ -0,0 +1,274 @@ +/* -*- 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 nsAttrValueInlines_h__ +#define nsAttrValueInlines_h__ + +#include + +#include "nsAttrValue.h" +#include "mozilla/Atomics.h" +#include "mozilla/Attributes.h" +#include "mozilla/ServoUtils.h" +#include "mozilla/dom/DOMString.h" + +namespace mozilla { +class ShadowParts; +} + +struct MiscContainer final { + using ValueType = nsAttrValue::ValueType; + + ValueType mType; + // mStringBits points to either nsAtom* or nsStringBuffer* and is used when + // mType isn't eCSSDeclaration. + // Note eStringBase and eAtomBase is used also to handle the type of + // mStringBits. + // + // Note that we use an atomic here so that we can use Compare-And-Swap + // to cache the serialization during the parallel servo traversal. This case + // (which happens when the main thread is blocked) is the only case where + // mStringBits is mutated off-main-thread. The Atomic needs to be + // ReleaseAcquire so that the pointer to the serialization does not become + // observable to other threads before the initialization of the pointed-to + // memory is also observable. + mozilla::Atomic mStringBits; + union { + struct { + union { + int32_t mInteger; + nscolor mColor; + uint32_t mEnumValue; + mozilla::DeclarationBlock* mCSSDeclaration; + nsIURI* mURL; + const mozilla::AttrAtomArray* mAtomArray; + const mozilla::ShadowParts* mShadowParts; + const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair; + const mozilla::SVGAnimatedLength* mSVGLength; + const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair; + const mozilla::SVGAnimatedOrient* mSVGAnimatedOrient; + const mozilla::SVGAnimatedPreserveAspectRatio* + mSVGAnimatedPreserveAspectRatio; + const mozilla::SVGAnimatedViewBox* mSVGAnimatedViewBox; + const mozilla::SVGLengthList* mSVGLengthList; + const mozilla::SVGNumberList* mSVGNumberList; + const mozilla::SVGPathData* mSVGPathData; + const mozilla::SVGPointList* mSVGPointList; + const mozilla::SVGStringList* mSVGStringList; + const mozilla::SVGTransformList* mSVGTransformList; + }; + uint32_t mRefCount : 31; + uint32_t mCached : 1; + } mValue; + double mDoubleValue; + }; + + MiscContainer() : mType(nsAttrValue::eColor), mStringBits(0) { + MOZ_COUNT_CTOR(MiscContainer); + mValue.mColor = 0; + mValue.mRefCount = 0; + mValue.mCached = 0; + } + + protected: + // Only nsAttrValue should be able to delete us. + friend class nsAttrValue; + + ~MiscContainer() { + if (IsRefCounted()) { + MOZ_ASSERT(mValue.mRefCount == 0); + MOZ_ASSERT(!mValue.mCached); + } + MOZ_COUNT_DTOR(MiscContainer); + } + + public: + bool GetString(nsAString& aString) const; + + void* GetStringOrAtomPtr(bool& aIsString) const { + uintptr_t bits = mStringBits; + aIsString = + nsAttrValue::ValueBaseType(mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == + nsAttrValue::eStringBase; + return reinterpret_cast(bits & NS_ATTRVALUE_POINTERVALUE_MASK); + } + + nsAtom* GetStoredAtom() const { + bool isString = false; + void* ptr = GetStringOrAtomPtr(isString); + return isString ? nullptr : static_cast(ptr); + } + + nsStringBuffer* GetStoredStringBuffer() const { + bool isString = false; + void* ptr = GetStringOrAtomPtr(isString); + return isString ? static_cast(ptr) : nullptr; + } + + void SetStringBitsMainThread(uintptr_t aBits) { + // mStringBits is atomic, but the callers of this function are + // single-threaded so they don't have to worry about it. + MOZ_ASSERT(!mozilla::IsInServoTraversal()); + MOZ_ASSERT(NS_IsMainThread()); + mStringBits = aBits; + } + + inline bool IsRefCounted() const { + // Nothing stops us from refcounting (and sharing) other types of + // MiscContainer (except eDoubleValue types) but there's no compelling + // reason to. + return mType == nsAttrValue::eAtomArray || + mType == nsAttrValue::eCSSDeclaration || + mType == nsAttrValue::eShadowParts; + } + + inline int32_t AddRef() { + MOZ_ASSERT(IsRefCounted()); + return ++mValue.mRefCount; + } + + inline int32_t Release() { + MOZ_ASSERT(IsRefCounted()); + return --mValue.mRefCount; + } + + void Cache(); + void Evict(); +}; + +/** + * Implementation of inline methods + */ + +inline int32_t nsAttrValue::GetIntegerValue() const { + MOZ_ASSERT(Type() == eInteger, "wrong type"); + return (BaseType() == eIntegerBase) ? GetIntInternal() + : GetMiscContainer()->mValue.mInteger; +} + +inline int16_t nsAttrValue::GetEnumValue() const { + MOZ_ASSERT(Type() == eEnum, "wrong type"); + // We don't need to worry about sign extension here since we're + // returning an int16_t which will cut away the top bits. + return static_cast(((BaseType() == eIntegerBase) + ? static_cast(GetIntInternal()) + : GetMiscContainer()->mValue.mEnumValue) >> + NS_ATTRVALUE_ENUMTABLEINDEX_BITS); +} + +inline double nsAttrValue::GetPercentValue() const { + MOZ_ASSERT(Type() == ePercent, "wrong type"); + if (BaseType() == eIntegerBase) { + return GetIntInternal() / 100.0f; + } + return GetMiscContainer()->mDoubleValue / 100.0f; +} + +inline const mozilla::AttrAtomArray* nsAttrValue::GetAtomArrayValue() const { + MOZ_ASSERT(Type() == eAtomArray, "wrong type"); + return GetMiscContainer()->mValue.mAtomArray; +} + +inline mozilla::DeclarationBlock* nsAttrValue::GetCSSDeclarationValue() const { + MOZ_ASSERT(Type() == eCSSDeclaration, "wrong type"); + return GetMiscContainer()->mValue.mCSSDeclaration; +} + +inline nsIURI* nsAttrValue::GetURLValue() const { + MOZ_ASSERT(Type() == eURL, "wrong type"); + return GetMiscContainer()->mValue.mURL; +} + +inline double nsAttrValue::GetDoubleValue() const { + MOZ_ASSERT(Type() == eDoubleValue, "wrong type"); + return GetMiscContainer()->mDoubleValue; +} + +inline bool nsAttrValue::IsSVGType(ValueType aType) const { + return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd; +} + +inline bool nsAttrValue::StoresOwnData() const { + if (BaseType() != eOtherBase) { + return true; + } + ValueType t = Type(); + return t != eCSSDeclaration && !IsSVGType(t); +} + +inline void nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType) { + NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK), + "pointer not properly aligned, this will crash"); + mBits = reinterpret_cast(aValue) | aType; +} + +inline void nsAttrValue::ResetIfSet() { + if (mBits) { + Reset(); + } +} + +inline MiscContainer* nsAttrValue::GetMiscContainer() const { + NS_ASSERTION(BaseType() == eOtherBase, "wrong type"); + return static_cast(GetPtr()); +} + +inline int32_t nsAttrValue::GetIntInternal() const { + NS_ASSERTION(BaseType() == eIntegerBase, "getting integer from non-integer"); + // Make sure we get a signed value. + // Lets hope the optimizer optimizes this into a shift. Unfortunatly signed + // bitshift right is implementaion dependant. + return static_cast(mBits & ~NS_ATTRVALUE_INTEGERTYPE_MASK) / + NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER; +} + +inline nsAttrValue::ValueType nsAttrValue::Type() const { + switch (BaseType()) { + case eIntegerBase: { + return static_cast(mBits & NS_ATTRVALUE_INTEGERTYPE_MASK); + } + case eOtherBase: { + return GetMiscContainer()->mType; + } + default: { + return static_cast(static_cast(BaseType())); + } + } +} + +inline nsAtom* nsAttrValue::GetAtomValue() const { + MOZ_ASSERT(Type() == eAtom, "wrong type"); + return reinterpret_cast(GetPtr()); +} + +inline void nsAttrValue::ToString(mozilla::dom::DOMString& aResult) const { + switch (Type()) { + case eString: { + nsStringBuffer* str = static_cast(GetPtr()); + if (str) { + aResult.SetKnownLiveStringBuffer( + str, str->StorageSize() / sizeof(char16_t) - 1); + } + // else aResult is already empty + return; + } + case eAtom: { + nsAtom* atom = static_cast(GetPtr()); + aResult.SetKnownLiveAtom(atom, mozilla::dom::DOMString::eNullNotExpected); + break; + } + default: { + ToString(aResult.AsAString()); + } + } +} + +inline const mozilla::ShadowParts& nsAttrValue::GetShadowPartsValue() const { + MOZ_ASSERT(Type() == eShadowParts); + return *GetMiscContainer()->mValue.mShadowParts; +} + +#endif diff --git a/dom/base/nsAttrValueOrString.cpp b/dom/base/nsAttrValueOrString.cpp new file mode 100644 index 0000000000..cedf4fad43 --- /dev/null +++ b/dom/base/nsAttrValueOrString.cpp @@ -0,0 +1,29 @@ +/* -*- 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 "nsAttrValueOrString.h" +#include "nsAttrValueInlines.h" + +const nsAString& nsAttrValueOrString::String() const { + if (mStringPtr) { + return *mStringPtr; + } + + if (!mAttrValue) { + mStringPtr = &mCheapString; + return *mStringPtr; + } + + if (mAttrValue->Type() == nsAttrValue::eString) { + mCheapString = mAttrValue->GetStringValue(); + mStringPtr = &mCheapString; + return *mStringPtr; + } + + mAttrValue->ToString(mCheapString); + mStringPtr = &mCheapString; + return *mStringPtr; +} diff --git a/dom/base/nsAttrValueOrString.h b/dom/base/nsAttrValueOrString.h new file mode 100644 index 0000000000..9cb3db33c5 --- /dev/null +++ b/dom/base/nsAttrValueOrString.h @@ -0,0 +1,85 @@ +/* -*- 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/. */ + +/* + * A wrapper to contain either an nsAttrValue or an nsAString. This is useful + * because constructing an nsAttrValue from an nsAString can be expensive when + * the buffer of the string is not shared. + * + * This treats nsAttrValueOrString(nullptr) as the empty string, + * to help with contexts where a null pointer denotes an empty value. + * + * Since a raw pointer to the passed-in string is kept, this class should only + * be used on the stack. + */ + +#ifndef nsAttrValueOrString_h___ +#define nsAttrValueOrString_h___ + +#include "nsString.h" +#include "nsAttrValue.h" + +class MOZ_STACK_CLASS nsAttrValueOrString { + public: + explicit nsAttrValueOrString(const nsAString& aValue) + : mAttrValue(nullptr), mStringPtr(&aValue), mCheapString(nullptr) {} + + explicit nsAttrValueOrString(const nsAString* aValue) + : mAttrValue(nullptr), mStringPtr(aValue), mCheapString(nullptr) {} + + explicit nsAttrValueOrString(const nsAttrValue& aValue) + : mAttrValue(&aValue), mStringPtr(nullptr), mCheapString(nullptr) {} + + explicit nsAttrValueOrString(const nsAttrValue* aValue) + : mAttrValue(aValue), mStringPtr(nullptr), mCheapString(nullptr) {} + + void ResetToAttrValue(const nsAttrValue& aValue) { + mAttrValue = &aValue; + mStringPtr = nullptr; + // No need to touch mCheapString here. If we need to use it, we will reset + // it to the rigthe value anyway. + } + + /** + * Returns a reference to the string value of the contents of this object. + * + * When this object points to a string or an nsAttrValue of string or atom + * type this should be fairly cheap. Other nsAttrValue types will be + * serialized the first time this is called and cached from thereon. + */ + const nsAString& String() const; + + /** + * Compares the string representation of this object with the string + * representation of an nsAttrValue. + */ + bool EqualsAsStrings(const nsAttrValue& aOther) const { + if (mStringPtr) { + return aOther.Equals(*mStringPtr, eCaseMatters); + } + return aOther.EqualsAsStrings(*mAttrValue); + } + + /* + * Returns true if the value stored is empty + */ + bool IsEmpty() const { + if (mStringPtr) { + return mStringPtr->IsEmpty(); + } + if (mAttrValue) { + return mAttrValue->IsEmptyString(); + } + return true; + } + + protected: + const nsAttrValue* mAttrValue; + mutable const nsAString* mStringPtr; + mutable nsCheapString mCheapString; +}; + +#endif // nsAttrValueOrString_h___ diff --git a/dom/base/nsCCUncollectableMarker.cpp b/dom/base/nsCCUncollectableMarker.cpp new file mode 100644 index 0000000000..c906a20021 --- /dev/null +++ b/dom/base/nsCCUncollectableMarker.cpp @@ -0,0 +1,494 @@ +/* -*- 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 "nsCCUncollectableMarker.h" +#include "nsIObserverService.h" +#include "nsIDocShell.h" +#include "nsServiceManagerUtils.h" +#include "nsIDocumentViewer.h" +#include "mozilla/dom/Document.h" +#include "InProcessBrowserChildMessageManager.h" +#include "nsIWindowMediator.h" +#include "nsPIDOMWindow.h" +#include "nsIWebNavigation.h" +#include "nsISHistory.h" +#include "nsISHEntry.h" +#include "nsIWindowWatcher.h" +#include "mozilla/Services.h" +#include "nsIAppWindow.h" +#include "nsIAppShellService.h" +#include "nsAppShellCID.h" +#include "nsContentUtils.h" +#include "nsGlobalWindowInner.h" +#include "nsGlobalWindowOuter.h" +#include "nsJSEnvironment.h" +#include "nsFrameLoader.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/CycleCollectedJSRuntime.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/dom/ChromeMessageBroadcaster.h" +#include "mozilla/dom/ContentFrameMessageManager.h" +#include "mozilla/dom/ContentProcessMessageManager.h" +#include "mozilla/dom/CustomElementRegistry.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ParentProcessMessageManager.h" +#include "mozilla/dom/BrowserChild.h" +#include "mozilla/dom/TimeoutManager.h" +#include "xpcpublic.h" +#include "nsObserverService.h" +#include "nsFocusManager.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIXULRuntime.h" + +using namespace mozilla; +using namespace mozilla::dom; + +static bool sInited = 0; +// The initial value of sGeneration should not be the same as the +// value it is given at xpcom-shutdown, because this will make any GCs +// before we first CC benignly violate the black-gray invariant, due +// to dom::TraceBlackJS(). +uint32_t nsCCUncollectableMarker::sGeneration = 1; +#include "nsXULPrototypeCache.h" + +NS_IMPL_ISUPPORTS(nsCCUncollectableMarker, nsIObserver) + +/* static */ +nsresult nsCCUncollectableMarker::Init() { + if (sInited) { + return NS_OK; + } + + nsCOMPtr marker = new nsCCUncollectableMarker; + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (!obs) return NS_ERROR_FAILURE; + + nsresult rv; + + // This makes the observer service hold an owning reference to the marker + rv = obs->AddObserver(marker, "xpcom-shutdown", false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = obs->AddObserver(marker, "cycle-collector-begin", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = obs->AddObserver(marker, "cycle-collector-forget-skippable", false); + NS_ENSURE_SUCCESS(rv, rv); + + sInited = true; + + return NS_OK; +} + +static void MarkChildMessageManagers(MessageBroadcaster* aMM) { + aMM->MarkForCC(); + + uint32_t browserChildCount = aMM->ChildCount(); + for (uint32_t j = 0; j < browserChildCount; ++j) { + RefPtr childMM = aMM->GetChildAt(j); + if (!childMM) { + continue; + } + + RefPtr strongNonLeafMM = + MessageBroadcaster::From(childMM); + MessageBroadcaster* nonLeafMM = strongNonLeafMM; + + MessageListenerManager* tabMM = childMM; + + strongNonLeafMM = nullptr; + childMM = nullptr; + + if (nonLeafMM) { + MarkChildMessageManagers(nonLeafMM); + continue; + } + + tabMM->MarkForCC(); + + // XXX hack warning, but works, since we know that + // callback is frameloader. + mozilla::dom::ipc::MessageManagerCallback* cb = tabMM->GetCallback(); + if (cb) { + nsFrameLoader* fl = static_cast(cb); + InProcessBrowserChildMessageManager* et = + fl->GetBrowserChildMessageManager(); + if (!et) { + continue; + } + et->MarkForCC(); + EventListenerManager* elm = et->GetExistingListenerManager(); + if (elm) { + elm->MarkForCC(); + } + } + } +} + +static void MarkMessageManagers() { + if (nsFrameMessageManager::GetChildProcessManager()) { + // ContentProcessMessageManager's MarkForCC also marks ChildProcessManager. + ContentProcessMessageManager* pg = ContentProcessMessageManager::Get(); + if (pg) { + pg->MarkForCC(); + } + } + + // The global message manager only exists in the root process. + if (!XRE_IsParentProcess()) { + return; + } + RefPtr strongGlobalMM = + nsFrameMessageManager::GetGlobalMessageManager(); + if (!strongGlobalMM) { + return; + } + ChromeMessageBroadcaster* globalMM = strongGlobalMM; + strongGlobalMM = nullptr; + MarkChildMessageManagers(globalMM); + + if (nsFrameMessageManager::sParentProcessManager) { + nsFrameMessageManager::sParentProcessManager->MarkForCC(); + uint32_t childCount = + nsFrameMessageManager::sParentProcessManager->ChildCount(); + for (uint32_t i = 0; i < childCount; ++i) { + RefPtr childMM = + nsFrameMessageManager::sParentProcessManager->GetChildAt(i); + if (!childMM) { + continue; + } + MessageListenerManager* child = childMM; + childMM = nullptr; + child->MarkForCC(); + } + } + if (nsFrameMessageManager::sSameProcessParentManager) { + nsFrameMessageManager::sSameProcessParentManager->MarkForCC(); + } +} + +void MarkDocumentViewer(nsIDocumentViewer* aViewer, bool aCleanupJS) { + if (!aViewer) { + return; + } + + Document* doc = aViewer->GetDocument(); + if (doc && + doc->GetMarkedCCGeneration() != nsCCUncollectableMarker::sGeneration) { + doc->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration); + if (aCleanupJS) { + EventListenerManager* elm = doc->GetExistingListenerManager(); + if (elm) { + elm->MarkForCC(); + } + RefPtr win = + nsGlobalWindowInner::Cast(doc->GetInnerWindow()); + if (win) { + elm = win->GetExistingListenerManager(); + if (elm) { + elm->MarkForCC(); + } + win->TimeoutManager().UnmarkGrayTimers(); + } + } + } + if (doc) { + if (nsPIDOMWindowInner* inner = doc->GetInnerWindow()) { + inner->MarkUncollectableForCCGeneration( + nsCCUncollectableMarker::sGeneration); + } + if (nsPIDOMWindowOuter* outer = doc->GetWindow()) { + outer->MarkUncollectableForCCGeneration( + nsCCUncollectableMarker::sGeneration); + } + } +} + +void MarkDocShell(nsIDocShellTreeItem* aNode, bool aCleanupJS); + +void MarkSHEntry(nsISHEntry* aSHEntry, bool aCleanupJS) { + if (!aSHEntry) { + return; + } + + nsCOMPtr viewer; + aSHEntry->GetDocumentViewer(getter_AddRefs(viewer)); + MarkDocumentViewer(viewer, aCleanupJS); + + nsCOMPtr child; + int32_t i = 0; + while (NS_SUCCEEDED(aSHEntry->ChildShellAt(i++, getter_AddRefs(child))) && + child) { + MarkDocShell(child, aCleanupJS); + } + + int32_t count; + aSHEntry->GetChildCount(&count); + for (i = 0; i < count; ++i) { + nsCOMPtr childEntry; + aSHEntry->GetChildAt(i, getter_AddRefs(childEntry)); + MarkSHEntry(childEntry, aCleanupJS); + } +} + +void MarkDocShell(nsIDocShellTreeItem* aNode, bool aCleanupJS) { + nsCOMPtr shell = do_QueryInterface(aNode); + if (!shell) { + return; + } + + nsCOMPtr viewer; + shell->GetDocViewer(getter_AddRefs(viewer)); + MarkDocumentViewer(viewer, aCleanupJS); + + nsCOMPtr webNav = do_QueryInterface(shell); + RefPtr history = webNav->GetSessionHistory(); + IgnoredErrorResult ignore; + nsISHistory* legacyHistory = + history ? history->GetLegacySHistory(ignore) : nullptr; + if (legacyHistory) { + MOZ_DIAGNOSTIC_ASSERT(!mozilla::SessionHistoryInParent()); + int32_t historyCount = history->Count(); + for (int32_t i = 0; i < historyCount; ++i) { + nsCOMPtr shEntry; + legacyHistory->GetEntryAtIndex(i, getter_AddRefs(shEntry)); + + MarkSHEntry(shEntry, aCleanupJS); + } + } + + int32_t i, childCount; + aNode->GetInProcessChildCount(&childCount); + for (i = 0; i < childCount; ++i) { + nsCOMPtr child; + aNode->GetInProcessChildAt(i, getter_AddRefs(child)); + MarkDocShell(child, aCleanupJS); + } +} + +void MarkWindowList(nsISimpleEnumerator* aWindowList, bool aCleanupJS) { + nsCOMPtr iter; + while (NS_SUCCEEDED(aWindowList->GetNext(getter_AddRefs(iter))) && iter) { + if (nsCOMPtr window = do_QueryInterface(iter)) { + nsCOMPtr rootDocShell = window->GetDocShell(); + + MarkDocShell(rootDocShell, aCleanupJS); + + RefPtr browserChild = BrowserChild::GetFrom(rootDocShell); + if (browserChild) { + RefPtr mm = + browserChild->GetMessageManager(); + if (mm) { + // MarkForCC ends up calling UnmarkGray on message listeners, which + // TraceBlackJS can't do yet. + mm->MarkForCC(); + } + } + } + } +} + +nsresult nsCCUncollectableMarker::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) { + if (!strcmp(aTopic, "xpcom-shutdown")) { + Element::ClearContentUnbinder(); + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (!obs) return NS_ERROR_FAILURE; + + // No need for kungFuDeathGrip here, yay observerservice! + obs->RemoveObserver(this, "xpcom-shutdown"); + obs->RemoveObserver(this, "cycle-collector-begin"); + obs->RemoveObserver(this, "cycle-collector-forget-skippable"); + + sGeneration = 0; + + return NS_OK; + } + + NS_ASSERTION(!strcmp(aTopic, "cycle-collector-begin") || + !strcmp(aTopic, "cycle-collector-forget-skippable"), + "wrong topic"); + + // JS cleanup can be slow. Do it only if this is the first forget-skippable + // after a GC. + const bool cleanupJS = nsJSContext::HasHadCleanupSinceLastGC() && + !strcmp(aTopic, "cycle-collector-forget-skippable"); + + const bool prepareForCC = !strcmp(aTopic, "cycle-collector-begin"); + if (prepareForCC) { + Element::ClearContentUnbinder(); + } + + // Increase generation to effectively unmark all current objects + if (!++sGeneration) { + ++sGeneration; + } + + nsFocusManager::MarkUncollectableForCCGeneration(sGeneration); + + nsresult rv; + + // Iterate all toplevel windows + nsCOMPtr windowList; + nsCOMPtr med = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID); + if (med) { + rv = med->GetEnumerator(nullptr, getter_AddRefs(windowList)); + NS_ENSURE_SUCCESS(rv, rv); + + MarkWindowList(windowList, cleanupJS); + } + + nsCOMPtr ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); + if (ww) { + rv = ww->GetWindowEnumerator(getter_AddRefs(windowList)); + NS_ENSURE_SUCCESS(rv, rv); + + MarkWindowList(windowList, cleanupJS); + } + + nsCOMPtr appShell = + do_GetService(NS_APPSHELLSERVICE_CONTRACTID); + if (appShell) { + bool hasHiddenWindow = false; + appShell->GetHasHiddenWindow(&hasHiddenWindow); + if (hasHiddenWindow) { + nsCOMPtr hw; + appShell->GetHiddenWindow(getter_AddRefs(hw)); + nsCOMPtr shell; + hw->GetDocShell(getter_AddRefs(shell)); + MarkDocShell(shell, cleanupJS); + } + } + + nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance(); + if (xulCache) { + xulCache->MarkInCCGeneration(sGeneration); + } + + enum ForgetSkippableCleanupState { + eInitial = 0, + eUnmarkJSEventListeners = 1, + eUnmarkMessageManagers = 2, + eUnmarkStrongObservers = 3, + eUnmarkJSHolders = 4, + eDone = 5 + }; + + static_assert(eDone == kMajorForgetSkippableCalls, + "There must be one forgetSkippable call per cleanup state."); + + static uint32_t sFSState = eDone; + if (prepareForCC) { + sFSState = eDone; + return NS_OK; + } + + if (cleanupJS) { + // After a GC we start clean up phases from the beginning, + // but we don't want to do the additional clean up phases here + // since we have done already plenty of gray unmarking while going through + // frame message managers and docshells. + sFSState = eInitial; + return NS_OK; + } else { + ++sFSState; + } + + switch (sFSState) { + case eUnmarkJSEventListeners: { + nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(); + break; + } + case eUnmarkMessageManagers: { + MarkMessageManagers(); + break; + } + case eUnmarkStrongObservers: { + nsCOMPtr obs = + mozilla::services::GetObserverService(); + static_cast(obs.get())->UnmarkGrayStrongObservers(); + break; + } + case eUnmarkJSHolders: { + xpc_UnmarkSkippableJSHolders(); + break; + } + default: { + break; + } + } + + return NS_OK; +} + +void mozilla::dom::TraceBlackJS(JSTracer* aTrc) { + if (!nsCCUncollectableMarker::sGeneration) { + return; + } + + if (ContentProcessMessageManager::WasCreated() && + nsFrameMessageManager::GetChildProcessManager()) { + auto* pg = ContentProcessMessageManager::Get(); + if (pg) { + mozilla::TraceScriptHolder(ToSupports(pg), aTrc); + } + } + + // Mark globals of active windows black. + nsGlobalWindowOuter::OuterWindowByIdTable* windowsById = + nsGlobalWindowOuter::GetWindowsTable(); + if (windowsById) { + for (nsGlobalWindowOuter* window : windowsById->Values()) { + if (!window->IsCleanedUp()) { + nsGlobalWindowInner* inner = nullptr; + for (PRCList* win = PR_LIST_HEAD(window); win != window; + win = PR_NEXT_LINK(inner)) { + inner = static_cast(win); + if (inner->IsCurrentInnerWindow() || + (inner->GetExtantDoc() && + inner->GetExtantDoc()->GetBFCacheEntry())) { + inner->TraceGlobalJSObject(aTrc); + EventListenerManager* elm = inner->GetExistingListenerManager(); + if (elm) { + elm->TraceListeners(aTrc); + } + CustomElementRegistry* cer = inner->GetExistingCustomElements(); + if (cer) { + cer->TraceDefinitions(aTrc); + } + } + } + + if (window->IsRootOuterWindow()) { + // In child process trace all the BrowserChildMessageManagers. + // Since there is one root outer window per + // BrowserChildMessageManager, we need to look for only those windows, + // not all. + nsIDocShell* ds = window->GetDocShell(); + if (ds) { + nsCOMPtr browserChild = ds->GetBrowserChild(); + if (browserChild) { + RefPtr mm; + browserChild->GetMessageManager(getter_AddRefs(mm)); + if (mm) { + nsCOMPtr browserChildAsSupports = + do_QueryInterface(browserChild); + mozilla::TraceScriptHolder(browserChildAsSupports, aTrc); + EventListenerManager* elm = mm->GetExistingListenerManager(); + if (elm) { + elm->TraceListeners(aTrc); + } + // As of now there isn't an easy way to trace message listeners. + } + } + } + } + } + } + } +} diff --git a/dom/base/nsCCUncollectableMarker.h b/dom/base/nsCCUncollectableMarker.h new file mode 100644 index 0000000000..2948cc0589 --- /dev/null +++ b/dom/base/nsCCUncollectableMarker.h @@ -0,0 +1,46 @@ +/* -*- 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 nsCCUncollectableMarker_h_ +#define nsCCUncollectableMarker_h_ + +#include "js/TracingAPI.h" +#include "mozilla/Attributes.h" +#include "nsIObserver.h" + +class nsCCUncollectableMarker final : public nsIObserver { + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + /** + * Inits a global nsCCUncollectableMarker. Should only be called once. + */ + static nsresult Init(); + + /** + * Checks if we're collecting during a given generation + */ + static bool InGeneration(uint32_t aGeneration) { + return aGeneration && aGeneration == sGeneration; + } + + template + static bool InGeneration(CCCallback& aCb, uint32_t aGeneration) { + return InGeneration(aGeneration) && !aCb.WantAllTraces(); + } + + static uint32_t sGeneration; + + private: + nsCCUncollectableMarker() = default; + ~nsCCUncollectableMarker() = default; +}; + +namespace mozilla::dom { +void TraceBlackJS(JSTracer* aTrc); +} // namespace mozilla::dom + +#endif diff --git a/dom/base/nsCaseTreatment.h b/dom/base/nsCaseTreatment.h new file mode 100644 index 0000000000..a95efc19be --- /dev/null +++ b/dom/base/nsCaseTreatment.h @@ -0,0 +1,15 @@ +/* -*- 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 nsCaseTreatment_h___ +#define nsCaseTreatment_h___ + +/** + * This is the enum used by functions that need to be told whether to + * do case-sensitive or case-insensitive string comparisons. + */ +enum nsCaseTreatment { eCaseMatters, eIgnoreCase }; + +#endif /* nsCaseTreatment_h___ */ diff --git a/dom/base/nsChildContentList.h b/dom/base/nsChildContentList.h new file mode 100644 index 0000000000..af43253cbf --- /dev/null +++ b/dom/base/nsChildContentList.h @@ -0,0 +1,83 @@ +/* -*- 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 nsChildContentList_h__ +#define nsChildContentList_h__ + +#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" +#include "nsINodeList.h" // base class +#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext + +class nsIContent; +class nsINode; + +/** + * Class that implements the nsINodeList interface (a list of children of + * the content), by holding a reference to the content and delegating Length + * and Item to its existing child list. + * @see nsINodeList + */ +class nsAttrChildContentList : public nsINodeList { + public: + explicit nsAttrChildContentList(nsINode* aNode) : mNode(aNode) {} + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS(nsAttrChildContentList) + + // nsWrapperCache + virtual JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + + // nsINodeList interface + virtual int32_t IndexOf(nsIContent* aContent) override; + virtual nsIContent* Item(uint32_t aIndex) override; + uint32_t Length() override; + nsINode* GetParentObject() final { return mNode; } + + virtual void InvalidateCacheIfAvailable() {} + + protected: + virtual ~nsAttrChildContentList() = default; + + private: + // The node whose children make up the list. + RefPtr mNode; +}; + +class nsParentNodeChildContentList final : public nsAttrChildContentList { + public: + explicit nsParentNodeChildContentList(nsINode* aNode) + : nsAttrChildContentList(aNode), mIsCacheValid(false) { + ValidateCache(); + } + + // nsINodeList interface + virtual int32_t IndexOf(nsIContent* aContent) override; + virtual nsIContent* Item(uint32_t aIndex) override; + uint32_t Length() override; + + void InvalidateCacheIfAvailable() final { InvalidateCache(); } + + void InvalidateCache() { + mIsCacheValid = false; + mCachedChildArray.Clear(); + } + + private: + ~nsParentNodeChildContentList() = default; + + // Return true if validation succeeds, false otherwise + bool ValidateCache(); + + // Whether cached array of child nodes is valid + bool mIsCacheValid; + + // Cached array of child nodes + AutoTArray mCachedChildArray; +}; + +#endif /* nsChildContentList_h__ */ diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp new file mode 100644 index 0000000000..3ca21e725a --- /dev/null +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -0,0 +1,873 @@ +/* -*- 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 "nsReadableUtils.h" + +// Local Includes +#include "nsContentAreaDragDrop.h" + +// Helper Classes +#include "nsString.h" + +// Interfaces needed to be included +#include "nsCopySupport.h" +#include "nsISelectionController.h" +#include "nsPIDOMWindow.h" +#include "nsIFormControl.h" +#include "nsITransferable.h" +#include "nsComponentManagerUtils.h" +#include "nsXPCOM.h" +#include "nsISupportsPrimitives.h" +#include "nsServiceManagerUtils.h" +#include "nsNetUtil.h" +#include "nsIFile.h" +#include "nsFrameLoader.h" +#include "nsFrameLoaderOwner.h" +#include "nsIContent.h" +#include "nsIContentInlines.h" +#include "nsIContentPolicy.h" +#include "nsIImageLoadingContent.h" +#include "nsUnicharUtils.h" +#include "nsIURL.h" +#include "nsIURIMutator.h" +#include "mozilla/dom/Document.h" +#include "nsICookieJarSettings.h" +#include "nsIPrincipal.h" +#include "nsIWebBrowserPersist.h" +#include "nsEscape.h" +#include "nsContentUtils.h" +#include "nsIMIMEService.h" +#include "imgIContainer.h" +#include "imgIRequest.h" +#include "mozilla/dom/DataTransfer.h" +#include "nsIMIMEInfo.h" +#include "nsRange.h" +#include "BrowserParent.h" +#include "mozilla/TextControlElement.h" +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/HTMLAreaElement.h" +#include "mozilla/dom/HTMLAnchorElement.h" +#include "mozilla/dom/Selection.h" +#include "nsVariant.h" +#include "nsQueryObject.h" + +using namespace mozilla; +using namespace mozilla::dom; +using mozilla::IgnoreErrors; + +class MOZ_STACK_CLASS DragDataProducer { + public: + DragDataProducer(nsPIDOMWindowOuter* aWindow, nsIContent* aTarget, + nsIContent* aSelectionTargetNode, bool aIsAltKeyPressed); + nsresult Produce(DataTransfer* aDataTransfer, bool* aCanDrag, + Selection** aSelection, nsIContent** aDragNode, + nsIContentSecurityPolicy** aCsp, + nsICookieJarSettings** aCookieJarSettings); + + private: + // @param aHidden true, iff the data should be hidden from non-chrome code. + void AddString(DataTransfer* aDataTransfer, const nsAString& aFlavor, + const nsAString& aData, nsIPrincipal* aPrincipal, + bool aHidden = false); + nsresult AddStringsToDataTransfer(nsIContent* aDragNode, + DataTransfer* aDataTransfer); + nsresult GetImageData(imgIContainer* aImage, imgIRequest* aRequest); + static nsresult GetDraggableSelectionData(Selection* inSelection, + nsIContent* inRealTargetNode, + nsIContent** outImageOrLinkNode, + bool* outDragSelectedText); + [[nodiscard]] static nsresult GetAnchorURL(nsIContent* inNode, + nsAString& outURL); + static void CreateLinkText(const nsAString& inURL, const nsAString& inText, + nsAString& outLinkText); + + nsCOMPtr mWindow; + nsCOMPtr mTarget; + nsCOMPtr mSelectionTargetNode; + bool mIsAltKeyPressed; + + nsString mUrlString; + nsString mImageSourceString; + nsString mImageDestFileName; +#if defined(XP_MACOSX) + nsString mImageRequestMime; +#endif + nsString mTitleString; + // will be filled automatically if you fill urlstring + nsString mHtmlString; + nsString mContextString; + nsString mInfoString; + + bool mIsAnchor; + nsCOMPtr mImage; +}; + +nsresult nsContentAreaDragDrop::GetDragData( + nsPIDOMWindowOuter* aWindow, nsIContent* aTarget, + nsIContent* aSelectionTargetNode, bool aIsAltKeyPressed, + DataTransfer* aDataTransfer, bool* aCanDrag, Selection** aSelection, + nsIContent** aDragNode, nsIContentSecurityPolicy** aCsp, + nsICookieJarSettings** aCookieJarSettings) { + NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG); + + *aCanDrag = true; + + DragDataProducer provider(aWindow, aTarget, aSelectionTargetNode, + aIsAltKeyPressed); + return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode, aCsp, + aCookieJarSettings); +} + +NS_IMPL_ISUPPORTS(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider) + +// SaveURIToFile +// used on platforms where it's possible to drag items (e.g. images) +// into the file system +nsresult nsContentAreaDragDropDataProvider::SaveURIToFile( + nsIURI* inSourceURI, nsIPrincipal* inTriggeringPrincipal, + nsICookieJarSettings* inCookieJarSettings, nsIFile* inDestFile, + nsContentPolicyType inContentPolicyType, bool isPrivate) { + nsCOMPtr sourceURL = do_QueryInterface(inSourceURI); + if (!sourceURL) { + return NS_ERROR_NO_INTERFACE; + } + + nsresult rv = inDestFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); + NS_ENSURE_SUCCESS(rv, rv); + + // we rely on the fact that the WPB is refcounted by the channel etc, + // so we don't keep a ref to it. It will die when finished. + nsCOMPtr persist = do_CreateInstance( + "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + persist->SetPersistFlags( + nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION); + + // referrer policy can be anything since the referrer is nullptr + return persist->SaveURI(inSourceURI, inTriggeringPrincipal, 0, nullptr, + inCookieJarSettings, nullptr, nullptr, inDestFile, + inContentPolicyType, isPrivate); +} + +/* + * Check if the provided filename extension is valid for the MIME type and + * return the MIME type's primary extension. + * + * @param aExtension [in] the extension to check + * @param aMimeType [in] the MIME type to check the extension with + * @param aIsValidExtension [out] true if |aExtension| is valid for + * |aMimeType| + * @param aPrimaryExtension [out] the primary extension for the MIME type + * to potentially be used as a replacement + * for |aExtension| + */ +nsresult CheckAndGetExtensionForMime(const nsCString& aExtension, + const nsCString& aMimeType, + bool* aIsValidExtension, + nsACString* aPrimaryExtension) { + nsresult rv; + + nsCOMPtr mimeService = do_GetService("@mozilla.org/mime;1"); + if (NS_WARN_IF(!mimeService)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr mimeInfo; + rv = mimeService->GetFromTypeAndExtension(aMimeType, ""_ns, + getter_AddRefs(mimeInfo)); + NS_ENSURE_SUCCESS(rv, rv); + + mimeInfo->GetPrimaryExtension(*aPrimaryExtension); + + if (aExtension.IsEmpty()) { + *aIsValidExtension = false; + return NS_OK; + } + + rv = mimeInfo->ExtensionExists(aExtension, aIsValidExtension); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +// This is our nsIFlavorDataProvider callback. There are several +// assumptions here that make this work: +// +// 1. Someone put a kFilePromiseURLMime flavor into the transferable +// with the source URI of the file to save (as a string). We did +// that in AddStringsToDataTransfer. +// +// 2. Someone put a kFilePromiseDirectoryMime flavor into the +// transferable with an nsIFile for the directory we are to +// save in. That has to be done by platform-specific code (in +// widget), which gets the destination directory from +// OS-specific drag information. +// +NS_IMETHODIMP +nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable* aTransferable, + const char* aFlavor, + nsISupports** aData) { + NS_ENSURE_ARG_POINTER(aData); + *aData = nullptr; + + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + + if (strcmp(aFlavor, kFilePromiseMime) == 0) { + // get the URI from the kFilePromiseURLMime flavor + NS_ENSURE_ARG(aTransferable); + nsCOMPtr tmp; + rv = aTransferable->GetTransferData(kFilePromiseURLMime, + getter_AddRefs(tmp)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr supportsString = do_QueryInterface(tmp); + if (!supportsString) return NS_ERROR_FAILURE; + + nsAutoString sourceURLString; + supportsString->GetData(sourceURLString); + if (sourceURLString.IsEmpty()) return NS_ERROR_FAILURE; + + nsCOMPtr sourceURI; + rv = NS_NewURI(getter_AddRefs(sourceURI), sourceURLString); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aTransferable->GetTransferData(kFilePromiseDestFilename, + getter_AddRefs(tmp)); + NS_ENSURE_SUCCESS(rv, rv); + supportsString = do_QueryInterface(tmp); + if (!supportsString) return NS_ERROR_FAILURE; + + nsAutoString targetFilename; + supportsString->GetData(targetFilename); + if (targetFilename.IsEmpty()) return NS_ERROR_FAILURE; + +#if defined(XP_MACOSX) + // Use the image request's MIME type to ensure the filename's + // extension is compatible with the OS's handler for this type. + // If it isn't, or is missing, replace the extension with the + // primary extension. On Mac, do this in the parent process + // because sandboxing blocks access to MIME-handler info from + // content processes. + if (XRE_IsParentProcess()) { + rv = aTransferable->GetTransferData(kImageRequestMime, + getter_AddRefs(tmp)); + NS_ENSURE_SUCCESS(rv, rv); + supportsString = do_QueryInterface(tmp); + if (!supportsString) return NS_ERROR_FAILURE; + + nsAutoString contentType; + supportsString->GetData(contentType); + + nsCOMPtr mimeService = + do_GetService("@mozilla.org/mime;1"); + if (NS_WARN_IF(!mimeService)) { + return NS_ERROR_FAILURE; + } + + mimeService->ValidateFileNameForSaving( + targetFilename, NS_ConvertUTF16toUTF8(contentType), + nsIMIMEService::VALIDATE_DEFAULT, targetFilename); + } else { + // make the filename safe for the filesystem + targetFilename.ReplaceChar( + u"" FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, u'-'); + } +#endif /* defined(XP_MACOSX) */ + + // get the target directory from the kFilePromiseDirectoryMime + // flavor + nsCOMPtr dirPrimitive; + rv = aTransferable->GetTransferData(kFilePromiseDirectoryMime, + getter_AddRefs(dirPrimitive)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr destDirectory = do_QueryInterface(dirPrimitive); + if (!destDirectory) return NS_ERROR_FAILURE; + + nsCOMPtr file; + rv = destDirectory->Clone(getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); + + file->Append(targetFilename); + + bool isPrivate = aTransferable->GetIsPrivateData(); + + nsCOMPtr principal = aTransferable->GetRequestingPrincipal(); + nsContentPolicyType contentPolicyType = + aTransferable->GetContentPolicyType(); + nsCOMPtr cookieJarSettings = + aTransferable->GetCookieJarSettings(); + rv = SaveURIToFile(sourceURI, principal, cookieJarSettings, file, + contentPolicyType, isPrivate); + // send back an nsIFile + if (NS_SUCCEEDED(rv)) { + CallQueryInterface(file, aData); + } + } + + return rv; +} + +DragDataProducer::DragDataProducer(nsPIDOMWindowOuter* aWindow, + nsIContent* aTarget, + nsIContent* aSelectionTargetNode, + bool aIsAltKeyPressed) + : mWindow(aWindow), + mTarget(aTarget), + mSelectionTargetNode(aSelectionTargetNode), + mIsAltKeyPressed(aIsAltKeyPressed), + mIsAnchor(false) {} + +static nsIContent* FindDragTarget(nsIContent* aContent) { + for (nsIContent* content = aContent; content; + content = content->GetFlattenedTreeParent()) { + if (nsContentUtils::ContentIsDraggable(content)) { + return content; + } + } + return nullptr; +} + +// +// GetAnchorURL +// +nsresult DragDataProducer::GetAnchorURL(nsIContent* aContent, nsAString& aURL) { + aURL.Truncate(); + auto* element = Element::FromNodeOrNull(aContent); + if (!element || !element->IsLink()) { + return NS_OK; + } + + nsCOMPtr linkURI = element->GetHrefURI(); + if (!linkURI) { + return NS_OK; + } + + nsAutoCString spec; + nsresult rv = linkURI->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); + rv = secMan->CheckLoadURIStrWithPrincipal(aContent->NodePrincipal(), spec, 0); + NS_ENSURE_SUCCESS(rv, rv); + CopyUTF8toUTF16(spec, aURL); + return NS_OK; +} + +// +// CreateLinkText +// +// Creates the html for an anchor in the form +// inText +// +void DragDataProducer::CreateLinkText(const nsAString& inURL, + const nsAString& inText, + nsAString& outLinkText) { + // use a temp var in case |inText| is the same string as + // |outLinkText| to avoid overwriting it while building up the + // string in pieces. + nsAutoString linkText(u""_ns + inText + + u""_ns); + + outLinkText = linkText; +} + +nsresult DragDataProducer::GetImageData(imgIContainer* aImage, + imgIRequest* aRequest) { + nsCOMPtr imgUri = aRequest->GetURI(); + + nsCOMPtr imgUrl(do_QueryInterface(imgUri)); + if (imgUrl) { + nsAutoCString spec; + nsresult rv = imgUrl->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + + // pass out the image source string + CopyUTF8toUTF16(spec, mImageSourceString); + + nsCString mimeType; + aRequest->GetMimeType(getter_Copies(mimeType)); + + nsAutoCString fileName; + aRequest->GetFileName(fileName); + +#if defined(XP_MACOSX) + // Save the MIME type so we can make sure the extension + // is compatible (and replace it if it isn't) when the + // image is dropped. On Mac, we need to get the OS MIME + // handler information in the parent due to sandboxing. + CopyUTF8toUTF16(mimeType, mImageRequestMime); + CopyUTF8toUTF16(fileName, mImageDestFileName); +#else + nsCOMPtr mimeService = do_GetService("@mozilla.org/mime;1"); + if (NS_WARN_IF(!mimeService)) { + return NS_ERROR_FAILURE; + } + + CopyUTF8toUTF16(fileName, mImageDestFileName); + mimeService->ValidateFileNameForSaving(mImageDestFileName, mimeType, + nsIMIMEService::VALIDATE_DEFAULT, + mImageDestFileName); +#endif + + // and the image object + mImage = aImage; + } + + return NS_OK; +} + +nsresult DragDataProducer::Produce(DataTransfer* aDataTransfer, bool* aCanDrag, + Selection** aSelection, + nsIContent** aDragNode, + nsIContentSecurityPolicy** aCsp, + nsICookieJarSettings** aCookieJarSettings) { + MOZ_ASSERT(aCanDrag && aSelection && aDataTransfer && aDragNode, + "null pointer passed to Produce"); + NS_ASSERTION(mWindow, "window not set"); + NS_ASSERTION(mSelectionTargetNode, + "selection target node should have been set"); + + *aDragNode = nullptr; + + nsresult rv; + nsIContent* dragNode = nullptr; + *aSelection = nullptr; + + // Find the selection to see what we could be dragging and if what we're + // dragging is in what is selected. If this is an editable textbox, use + // the textbox's selection, otherwise use the window's selection. + RefPtr selection; + nsIContent* editingElement = mSelectionTargetNode->IsEditable() + ? mSelectionTargetNode->GetEditingHost() + : nullptr; + RefPtr textControlElement = + TextControlElement::GetTextControlElementFromEditingHost(editingElement); + if (textControlElement) { + nsISelectionController* selcon = + textControlElement->GetSelectionController(); + if (selcon) { + selection = + selcon->GetSelection(nsISelectionController::SELECTION_NORMAL); + } + + if (!selection) return NS_OK; + } else { + selection = mWindow->GetSelection(); + if (!selection) return NS_OK; + + // Check if the node is inside a form control. Don't set aCanDrag to false + // however, as we still want to allow the drag. + nsCOMPtr findFormNode = mSelectionTargetNode; + nsIContent* findFormParent = findFormNode->GetParent(); + while (findFormParent) { + nsCOMPtr form(do_QueryInterface(findFormParent)); + if (form && !form->AllowDraggableChildren()) { + return NS_OK; + } + findFormParent = findFormParent->GetParent(); + } + } + + // if set, serialize the content under this node + nsCOMPtr nodeToSerialize; + + BrowsingContext* bc = mWindow->GetBrowsingContext(); + const bool isChromeShell = bc && bc->IsChrome(); + + // In chrome shells, only allow dragging inside editable areas. + if (isChromeShell && !editingElement) { + // This path should already be filtered out in + // EventStateManager::DetermineDragTargetAndDefaultData. + MOZ_ASSERT_UNREACHABLE("Shouldn't be generating drag data for chrome"); + return NS_OK; + } + + if (isChromeShell && textControlElement) { + // Only use the selection if the target node is in the selection. + if (!selection->ContainsNode(*mSelectionTargetNode, false, IgnoreErrors())) + return NS_OK; + + selection.swap(*aSelection); + } else { + // In content shells, a number of checks are made below to determine + // whether an image or a link is being dragged. If so, add additional + // data to the data transfer. This is also done for chrome shells, but + // only when in a non-textbox editor. + + bool haveSelectedContent = false; + + // possible parent link node + nsCOMPtr parentLink; + nsCOMPtr draggedNode; + + { + // only drag form elements by using the alt key, + // otherwise buttons and select widgets are hard to use + + // Note that while elements implement nsIFormControl, we should + // really allow dragging them if they happen to be images. + nsCOMPtr form(do_QueryInterface(mTarget)); + if (form && !mIsAltKeyPressed && + form->ControlType() != FormControlType::Object) { + *aCanDrag = false; + return NS_OK; + } + + draggedNode = FindDragTarget(mTarget); + } + + nsCOMPtr image; + + nsCOMPtr selectedImageOrLinkNode; + GetDraggableSelectionData(selection, mSelectionTargetNode, + getter_AddRefs(selectedImageOrLinkNode), + &haveSelectedContent); + + // either plain text or anchor text is selected + if (haveSelectedContent) { + selection.swap(*aSelection); + } else if (selectedImageOrLinkNode) { + // an image is selected + image = do_QueryInterface(selectedImageOrLinkNode); + } else { + // nothing is selected - + // + // look for draggable elements under the mouse + // + // if the alt key is down, don't start a drag if we're in an + // anchor because we want to do selection. + parentLink = nsContentUtils::GetClosestLinkInFlatTree(draggedNode); + if (parentLink && mIsAltKeyPressed) { + *aCanDrag = false; + return NS_OK; + } + image = do_QueryInterface(draggedNode); + } + + { + // set for linked images, and links + nsCOMPtr linkNode; + if (const auto* areaElem = HTMLAreaElement::FromNodeOrNull(draggedNode)) { + // use the alt text (or, if missing, the href) as the title + areaElem->GetAttr(nsGkAtoms::alt, mTitleString); + if (mTitleString.IsEmpty()) { + // this can be a relative link + areaElem->GetAttr(nsGkAtoms::href, mTitleString); + } + + // gives an absolute link + nsresult rv = GetAnchorURL(draggedNode, mUrlString); + NS_ENSURE_SUCCESS(rv, rv); + + // we'll generate HTML like alt text + mIsAnchor = true; + + mHtmlString.AssignLiteral(""); + mHtmlString.Append(mTitleString); + mHtmlString.AppendLiteral(""); + + dragNode = draggedNode; + } else if (image) { + // grab the href as the url, use alt text as the title of the + // area if it's there. the drag data is the image tag and src + // attribute. + nsCOMPtr imageURI; + image->GetCurrentURI(getter_AddRefs(imageURI)); + nsCOMPtr imageElement(do_QueryInterface(image)); + if (imageURI) { + nsAutoCString spec; + rv = imageURI->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + nsIScriptSecurityManager* secMan = + nsContentUtils::GetSecurityManager(); + rv = secMan->CheckLoadURIStrWithPrincipal( + imageElement->NodePrincipal(), spec, 0); + NS_ENSURE_SUCCESS(rv, rv); + mIsAnchor = true; + CopyUTF8toUTF16(spec, mUrlString); + } + + // XXXbz Shouldn't we use the "title" attr for title? Using + // "alt" seems very wrong.... + // XXXbz Also, what if this is an nsIImageLoadingContent + // that's not an ? + if (imageElement) { + imageElement->GetAttr(nsGkAtoms::alt, mTitleString); + } + + if (mTitleString.IsEmpty()) { + mTitleString = mUrlString; + } + + nsCOMPtr imgRequest; + + // grab the image data, and its request. + nsCOMPtr img = nsContentUtils::GetImageFromContent( + image, getter_AddRefs(imgRequest)); + if (imgRequest) { + rv = GetImageData(img, imgRequest); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (parentLink) { + // If we are dragging around an image in an anchor, then we + // are dragging the entire anchor + linkNode = parentLink; + nodeToSerialize = linkNode; + } else { + nodeToSerialize = draggedNode; + } + dragNode = nodeToSerialize; + } else if (parentLink) { + // parentLink will always be null if there's selected content + linkNode = parentLink; + nodeToSerialize = linkNode; + } else if (!haveSelectedContent) { + // nothing draggable + return NS_OK; + } + + if (linkNode) { + rv = GetAnchorURL(linkNode, mUrlString); + NS_ENSURE_SUCCESS(rv, rv); + mIsAnchor = true; + dragNode = linkNode; + } + } + } + + if (nodeToSerialize || *aSelection) { + mHtmlString.Truncate(); + mContextString.Truncate(); + mInfoString.Truncate(); + mTitleString.Truncate(); + + nsCOMPtr doc = mWindow->GetDoc(); + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); + + nsCOMPtr csp = doc->GetCsp(); + if (csp) { + NS_IF_ADDREF(*aCsp = csp); + } + + nsCOMPtr cookieJarSettings = doc->CookieJarSettings(); + if (cookieJarSettings) { + NS_IF_ADDREF(*aCookieJarSettings = cookieJarSettings); + } + + // if we have selected text, use it in preference to the node + nsCOMPtr transferable; + if (*aSelection) { + rv = nsCopySupport::GetTransferableForSelection( + *aSelection, doc, getter_AddRefs(transferable)); + } else { + rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc, + getter_AddRefs(transferable)); + } + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr supports; + nsCOMPtr data; + rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(supports)); + data = do_QueryInterface(supports); + if (NS_SUCCEEDED(rv)) { + data->GetData(mHtmlString); + } + rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(supports)); + data = do_QueryInterface(supports); + if (NS_SUCCEEDED(rv)) { + data->GetData(mContextString); + } + rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(supports)); + data = do_QueryInterface(supports); + if (NS_SUCCEEDED(rv)) { + data->GetData(mInfoString); + } + rv = transferable->GetTransferData(kTextMime, getter_AddRefs(supports)); + data = do_QueryInterface(supports); + NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum + data->GetData(mTitleString); + } + + // default text value is the URL + if (mTitleString.IsEmpty()) { + mTitleString = mUrlString; + } + + // if we haven't constructed a html version, make one now + if (mHtmlString.IsEmpty() && !mUrlString.IsEmpty()) + CreateLinkText(mUrlString, mTitleString, mHtmlString); + + // if there is no drag node, which will be the case for a selection, just + // use the selection target node. + rv = AddStringsToDataTransfer( + dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*aDragNode = dragNode); + return NS_OK; +} + +void DragDataProducer::AddString(DataTransfer* aDataTransfer, + const nsAString& aFlavor, + const nsAString& aData, + nsIPrincipal* aPrincipal, bool aHidden) { + RefPtr variant = new nsVariantCC(); + variant->SetAsAString(aData); + aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal, aHidden); +} + +nsresult DragDataProducer::AddStringsToDataTransfer( + nsIContent* aDragNode, DataTransfer* aDataTransfer) { + NS_ASSERTION(aDragNode, "adding strings for null node"); + + // set all of the data to have the principal of the node where the data came + // from + nsIPrincipal* principal = aDragNode->NodePrincipal(); + + // add a special flavor if we're an anchor to indicate that we have + // a URL in the drag data + if (!mUrlString.IsEmpty() && mIsAnchor) { + nsAutoString dragData(mUrlString); + dragData.Append('\n'); + // Remove leading and trailing newlines in the title and replace them with + // space in remaining positions - they confuse PlacesUtils::unwrapNodes + // that expects url\ntitle formatted data for x-moz-url. + nsAutoString title(mTitleString); + title.Trim("\r\n"); + title.ReplaceChar(u"\r\n", ' '); + dragData += title; + + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kURLMime), dragData, + principal); + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kURLDataMime), + mUrlString, principal); + AddString(aDataTransfer, + NS_LITERAL_STRING_FROM_CSTRING(kURLDescriptionMime), mTitleString, + principal); + AddString(aDataTransfer, u"text/uri-list"_ns, mUrlString, principal); + } + + // add a special flavor for the html context data + if (!mContextString.IsEmpty()) + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kHTMLContext), + mContextString, principal); + + // add a special flavor if we have html info data + if (!mInfoString.IsEmpty()) + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kHTMLInfo), + mInfoString, principal); + + // add the full html + if (!mHtmlString.IsEmpty()) + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kHTMLMime), + mHtmlString, principal); + + // add the plain text. we use the url for text/plain data if an anchor is + // being dragged, rather than the title text of the link or the alt text for + // an anchor image. + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kTextMime), + mIsAnchor ? mUrlString : mTitleString, principal); + + // add image data, if present. For now, all we're going to do with + // this is turn it into a native data flavor, so indicate that with + // a new flavor so as not to confuse anyone who is really registered + // for image/gif or image/jpg. + if (mImage) { + RefPtr variant = new nsVariantCC(); + variant->SetAsISupports(mImage); + aDataTransfer->SetDataWithPrincipal( + NS_LITERAL_STRING_FROM_CSTRING(kNativeImageMime), variant, 0, + principal); + + // assume the image comes from a file, and add a file promise. We + // register ourselves as a nsIFlavorDataProvider, and will use the + // GetFlavorData callback to save the image to disk. + + nsCOMPtr dataProvider = + new nsContentAreaDragDropDataProvider(); + if (dataProvider) { + RefPtr variant = new nsVariantCC(); + variant->SetAsISupports(dataProvider); + aDataTransfer->SetDataWithPrincipal( + NS_LITERAL_STRING_FROM_CSTRING(kFilePromiseMime), variant, 0, + principal); + } + + AddString(aDataTransfer, + NS_LITERAL_STRING_FROM_CSTRING(kFilePromiseURLMime), + mImageSourceString, principal); + AddString(aDataTransfer, + NS_LITERAL_STRING_FROM_CSTRING(kFilePromiseDestFilename), + mImageDestFileName, principal); +#if defined(XP_MACOSX) + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kImageRequestMime), + mImageRequestMime, principal, /* aHidden= */ true); +#endif + + // if not an anchor, add the image url + if (!mIsAnchor) { + AddString(aDataTransfer, NS_LITERAL_STRING_FROM_CSTRING(kURLDataMime), + mUrlString, principal); + AddString(aDataTransfer, u"text/uri-list"_ns, mUrlString, principal); + } + } + + return NS_OK; +} + +// note that this can return NS_OK, but a null out param (by design) +// static +nsresult DragDataProducer::GetDraggableSelectionData( + Selection* inSelection, nsIContent* inRealTargetNode, + nsIContent** outImageOrLinkNode, bool* outDragSelectedText) { + NS_ENSURE_ARG(inSelection); + NS_ENSURE_ARG(inRealTargetNode); + NS_ENSURE_ARG_POINTER(outImageOrLinkNode); + + *outImageOrLinkNode = nullptr; + *outDragSelectedText = false; + + if (!inSelection->IsCollapsed()) { + if (inSelection->ContainsNode(*inRealTargetNode, false, IgnoreErrors())) { + // track down the anchor node, if any, for the url + nsINode* selectionStart = inSelection->GetAnchorNode(); + nsINode* selectionEnd = inSelection->GetFocusNode(); + + // look for a selection around a single node, like an image. + // in this case, drag the image, rather than a serialization of the HTML + // XXX generalize this to other draggable element types? + if (selectionStart == selectionEnd) { + nsCOMPtr selStartContent = + nsIContent::FromNodeOrNull(selectionStart); + if (selStartContent && selStartContent->HasChildNodes()) { + // see if just one node is selected + uint32_t anchorOffset = inSelection->AnchorOffset(); + uint32_t focusOffset = inSelection->FocusOffset(); + if (anchorOffset == focusOffset + 1 || + focusOffset == anchorOffset + 1) { + uint32_t childOffset = std::min(anchorOffset, focusOffset); + nsIContent* childContent = + selStartContent->GetChildAt_Deprecated(childOffset); + // if we find an image, we'll fall into the node-dragging code, + // rather the the selection-dragging code + if (nsContentUtils::IsDraggableImage(childContent)) { + NS_ADDREF(*outImageOrLinkNode = childContent); + return NS_OK; + } + } + } + } + + // indicate that a link or text is selected + *outDragSelectedText = true; + } + } + + return NS_OK; +} diff --git a/dom/base/nsContentAreaDragDrop.h b/dom/base/nsContentAreaDragDrop.h new file mode 100644 index 0000000000..27ef90f272 --- /dev/null +++ b/dom/base/nsContentAreaDragDrop.h @@ -0,0 +1,81 @@ +/* -*- 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 nsContentAreaDragDrop_h__ +#define nsContentAreaDragDrop_h__ + +#include "nsCOMPtr.h" + +#include "nsITransferable.h" +#include "nsIContentSecurityPolicy.h" + +class nsICookieJarSettings; +class nsPIDOMWindowOuter; +class nsITransferable; +class nsIContent; +class nsIFile; + +namespace mozilla::dom { +class DataTransfer; +class Selection; +} // namespace mozilla::dom + +// +// class nsContentAreaDragDrop, used to generate the dragdata +// +class nsContentAreaDragDrop { + public: + /** + * Determine what data in the content area, if any, is being dragged. + * + * aWindow - the window containing the target node + * aTarget - the mousedown event target that started the drag + * aSelectionTargetNode - the node where the drag event should be fired + * aIsAltKeyPressed - true if the Alt key is pressed. In some cases, this + * will prevent the drag from occuring. For example, + * holding down Alt over a link should select the text, + * not drag the link. + * aDataTransfer - the dataTransfer for the drag event. + * aCanDrag - [out] set to true if the drag may proceed, false to stop the + * drag entirely + * aSelection - [out] set to the selection being dragged, or null if no + * selection is being dragged. + * aDragNode - [out] the link, image or area being dragged, or null if the + * drag occurred on another element. + * aCSP - [out] set to the CSP of the Drag, or null if + * it's from browser chrome or OS + * aCookieJarSettings - [out] set to the cookieJarSetting of the Drag, or null + * if it's from browser chrome or OS + */ + static nsresult GetDragData(nsPIDOMWindowOuter* aWindow, nsIContent* aTarget, + nsIContent* aSelectionTargetNode, + bool aIsAltKeyPressed, + mozilla::dom::DataTransfer* aDataTransfer, + bool* aCanDrag, + mozilla::dom::Selection** aSelection, + nsIContent** aDragNode, + nsIContentSecurityPolicy** aCsp, + nsICookieJarSettings** aCookieJarSettings); +}; + +// this is used to save images to disk lazily when the image data is asked for +// during the drop instead of when it is added to the drag data transfer. This +// ensures that the image data is only created when an image drop is allowed. +class nsContentAreaDragDropDataProvider : public nsIFlavorDataProvider { + virtual ~nsContentAreaDragDropDataProvider() = default; + + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIFLAVORDATAPROVIDER + + nsresult SaveURIToFile(nsIURI* inSourceURI, + nsIPrincipal* inTriggeringPrincipal, + nsICookieJarSettings* inCookieJarSettings, + nsIFile* inDestFile, nsContentPolicyType inPolicyType, + bool isPrivate); +}; + +#endif /* nsContentAreaDragDrop_h__ */ diff --git a/dom/base/nsContentCID.h b/dom/base/nsContentCID.h new file mode 100644 index 0000000000..cda1cb4075 --- /dev/null +++ b/dom/base/nsContentCID.h @@ -0,0 +1,195 @@ +/* -*- 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 nsContentCID_h__ +#define nsContentCID_h__ + +// {972D8D8F-F0DA-11d4-9885-00C04FA0CF4B} +#define NS_CONTENT_VIEWER_CID \ + { \ + 0x972d8d8f, 0xf0da, 0x11d4, { \ + 0x98, 0x85, 0x0, 0xc0, 0x4f, 0xa0, 0xcf, 0x4b \ + } \ + } + +// {FC886801-E768-11d4-9885-00C04FA0CF4B} +#define NS_CONTENT_DOCUMENT_LOADER_FACTORY_CID \ + { \ + 0xfc886801, 0xe768, 0x11d4, { \ + 0x98, 0x85, 0x0, 0xc0, 0x4f, 0xa0, 0xcf, 0x4b \ + } \ + } + +#define NS_NAMESPACEMANAGER_CID \ + { /* d9783472-8fe9-11d2-9d3c-0060088f9ff7 */ \ + 0xd9783472, 0x8fe9, 0x11d2, { \ + 0x9d, 0x3c, 0x00, 0x60, 0x08, 0x8f, 0x9f, 0xf7 \ + } \ + } + +// {09F689E0-B4DA-11d2-A68B-00104BDE6048} +#define NS_EVENTLISTENERMANAGER_CID \ + { \ + 0x9f689e0, 0xb4da, 0x11d2, { \ + 0xa6, 0x8b, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 \ + } \ + } + +// {64F300A1-C88C-11d3-97FB-00400553EEF0} +#define NS_XBLSERVICE_CID \ + { \ + 0x64f300a1, 0xc88c, 0x11d3, { \ + 0x97, 0xfb, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 \ + } \ + } + +// {4aef38b7-6364-4e23-a5e7-12f837fbbd9c} +#define NS_XMLCONTENTSERIALIZER_CID \ + { \ + 0x4aef38b7, 0x6364, 0x4e23, { \ + 0xa5, 0xe7, 0x12, 0xf8, 0x37, 0xfb, 0xbd, 0x9c \ + } \ + } + +// {e7c2aaf5-c11a-4954-9dbf-e28edec1fd91} +#define NS_XHTMLCONTENTSERIALIZER_CID \ + { \ + 0xe7c2aaf5, 0xc11a, 0x4954, { \ + 0x9d, 0xbf, 0xe2, 0x8e, 0xde, 0xc1, 0xfd, 0x91 \ + } \ + } + +// {9d3f70da-86e9-11d4-95ec-00b0d03e37b7} +#define NS_HTMLCONTENTSERIALIZER_CID \ + { \ + 0x9d3f70da, 0x86e9, 0x11d4, { \ + 0x95, 0xec, 0x00, 0xb0, 0xd0, 0x3e, 0x37, 0xb7 \ + } \ + } + +// {feca3c34-205e-4ae5-bd1c-03c686ff012b} +#define MOZ_SANITIZINGHTMLSERIALIZER_CID \ + { \ + 0xfeca3c34, 0x205e, 0x4ae5, { \ + 0xbd, 0x1c, 0x03, 0xc6, 0x86, 0xff, 0x01, 0x2b \ + } \ + } + +// {6030f7ef-32ed-46a7-9a63-6a5d3f90445f} +#define NS_PLAINTEXTSERIALIZER_CID \ + { \ + 0x6030f7ef, 0x32ed, 0x46a7, { \ + 0x9a, 0x63, 0x6a, 0x5d, 0x3f, 0x90, 0x44, 0x5f \ + } \ + } + +// {d4f2b600-b5c1-11d6-b483-cc97c63e567c} +#define NS_HTMLFRAGMENTSINK_CID \ + { \ + 0xd4f2b600, 0xb5c1, 0x11d6, { \ + 0xb4, 0x83, 0xcc, 0x97, 0xc6, 0x3e, 0x56, 0x7c \ + } \ + } + +// {13111d00-ce81-11d6-8082-ecf3665af67c} +#define NS_HTMLFRAGMENTSINK2_CID \ + { \ + 0x13111d00, 0xce81, 0x11d6, { \ + 0x80, 0x82, 0xec, 0xf3, 0x66, 0x5a, 0xf6, 0x7c \ + } \ + } + +// {4B664E54-72A2-4bbf-A5C2-66D4DC3066A0} +#define NS_XMLFRAGMENTSINK_CID \ + { \ + 0x4b664e54, 0x72a2, 0x4bbf, { \ + 0xa5, 0xc2, 0x66, 0xd4, 0xdc, 0x30, 0x66, 0xa0 \ + } \ + } + +// {4DC30689-929D-425e-A709-082C6294E542} +#define NS_XMLFRAGMENTSINK2_CID \ + { \ + 0x4dc30689, 0x929d, 0x425e, { \ + 0xa7, 0x9, 0x8, 0x2c, 0x62, 0x94, 0xe5, 0x42 \ + } \ + } + +// {3986B301-097C-11d3-BF87-00105A1B0627} +#define NS_XULPOPUPLISTENER_CID \ + { \ + 0x3986b301, 0x97c, 0x11d3, { \ + 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 \ + } \ + } + +// {3D262D00-8B5A-11d2-8EB0-00805F29F370} +#define NS_XULTEMPLATEBUILDER_CID \ + { \ + 0x3d262d00, 0x8b5a, 0x11d2, { \ + 0x8e, 0xb0, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 \ + } \ + } + +// {1abdcc96-1dd2-11b2-b520-f8f59cdd67bc} +#define NS_XULTREEBUILDER_CID \ + { \ + 0x1abdcc96, 0x1dd2, 0x11b2, { \ + 0xb5, 0x20, 0xf8, 0xf5, 0x9c, 0xdd, 0x67, 0xbc \ + } \ + } + +#define NS_EVENTLISTENERSERVICE_CID \ + { /* baa34652-f1f1-4185-b224-244ee82a413a */ \ + 0xbaa34652, 0xf1f1, 0x4185, { \ + 0xb2, 0x24, 0x24, 0x4e, 0xe8, 0x2a, 0x41, 0x3a \ + } \ + } +#define NS_EVENTLISTENERSERVICE_CONTRACTID "@mozilla.org/eventlistenerservice;1" + +#define NS_GLOBALMESSAGEMANAGER_CID \ + { /* 130b016f-fad7-4526-bc7f-827dabf79265 */ \ + 0x130b016f, 0xfad7, 0x4526, { \ + 0xbc, 0x7f, 0x82, 0x7d, 0xab, 0xf7, 0x92, 0x65 \ + } \ + } +#define NS_GLOBALMESSAGEMANAGER_CONTRACTID "@mozilla.org/globalmessagemanager;1" + +#define NS_PARENTPROCESSMESSAGEMANAGER_CID \ + { /* 2a058404-fb85-44ec-8cfd-e8cbdc988dc1 */ \ + 0x2a058404, 0xfb85, 0x44ec, { \ + 0x8c, 0xfd, 0xe8, 0xcb, 0xdc, 0x98, 0x8d, 0xc1 \ + } \ + } +#define NS_PARENTPROCESSMESSAGEMANAGER_CONTRACTID \ + "@mozilla.org/parentprocessmessagemanager;1" + +#define NS_CHILDPROCESSMESSAGEMANAGER_CID \ + { /* fe0ff7c3-8e97-448b-9a8a-86afdb9fbbb6 */ \ + 0xfe0ff7c3, 0x8e97, 0x448b, { \ + 0x9a, 0x8a, 0x86, 0xaf, 0xdb, 0x9f, 0xbb, 0xb6 \ + } \ + } +#define NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID \ + "@mozilla.org/childprocessmessagemanager;1" + +// {08c6cc8b-cfb0-421d-b1f7-683ff2989681} +#define THIRDPARTYUTIL_CID \ + { \ + 0x08c6cc8b, 0xcfb0, 0x421d, { \ + 0xb1, 0xf7, 0x68, 0x3f, 0xf2, 0x98, 0x96, 0x81 \ + } \ + } + +// {7B121F7E-EBE4-43AB-9410-DC9087A1DBA6} +#define GECKO_MEDIA_PLUGIN_SERVICE_CID \ + { \ + 0x7B121F7E, 0xEBE4, 0x43AB, { \ + 0x94, 0x10, 0xDC, 0x90, 0x87, 0xA1, 0xDB, 0xA6 \ + } \ + } + +#endif /* nsContentCID_h__ */ diff --git a/dom/base/nsContentCreatorFunctions.h b/dom/base/nsContentCreatorFunctions.h new file mode 100644 index 0000000000..3bbc40942f --- /dev/null +++ b/dom/base/nsContentCreatorFunctions.h @@ -0,0 +1,75 @@ +/* -*- 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 nsContentCreatorFunctions_h__ +#define nsContentCreatorFunctions_h__ + +#include "nsError.h" +#include "nsCOMPtr.h" +#include "mozilla/dom/FromParser.h" + +/** + * Functions to create content, to be used only inside Gecko + * (mozilla/content and mozilla/layout). + */ + +class nsAtom; +class nsIContent; + +class imgRequestProxy; +class nsGenericHTMLElement; + +namespace mozilla::dom { +class Element; +class NodeInfo; +struct CustomElementDefinition; +} // namespace mozilla::dom + +nsresult NS_NewElement(mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser, + const nsAString* aIs); + +nsresult NS_NewElement( + mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser, nsAtom* aIsAtom = nullptr, + mozilla::dom::CustomElementDefinition* aDefinition = nullptr); + +nsresult NS_NewXMLElement(mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo); + +nsresult NS_NewHTMLElement( + mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser, nsAtom* aIsAtom = nullptr, + mozilla::dom::CustomElementDefinition* aDefinition = nullptr); + +// First argument should be nsHTMLTag, but that adds dependency to parser +// for a bunch of files. +already_AddRefed CreateHTMLElement( + uint32_t aNodeType, already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser); + +nsresult NS_NewMathMLElement( + mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo); + +nsresult NS_NewXULElement( + mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser, nsAtom* aIsAtom = nullptr, + mozilla::dom::CustomElementDefinition* aDefinition = nullptr); + +void NS_TrustedNewXULElement( + mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo); + +nsresult NS_NewSVGElement(mozilla::dom::Element** aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser); + +#endif // nsContentCreatorFunctions_h__ diff --git a/dom/base/nsContentList.cpp b/dom/base/nsContentList.cpp new file mode 100644 index 0000000000..de8fb46d89 --- /dev/null +++ b/dom/base/nsContentList.cpp @@ -0,0 +1,1181 @@ +/* -*- 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/. */ + +/* + * nsBaseContentList is a basic list of content nodes; nsContentList + * is a commonly used NodeList implementation (used for + * getElementsByTagName, some properties on HTMLDocument/Document, etc). + */ + +#include "nsContentList.h" +#include "nsIContent.h" +#include "mozilla/dom/Document.h" +#include "mozilla/ContentIterator.h" +#include "mozilla/dom/Element.h" +#include "nsWrapperCacheInlines.h" +#include "nsContentUtils.h" +#include "nsCCUncollectableMarker.h" +#include "nsGkAtoms.h" +#include "mozilla/dom/HTMLCollectionBinding.h" +#include "mozilla/dom/NodeListBinding.h" +#include "mozilla/Likely.h" +#include "nsGenericHTMLElement.h" +#include "jsfriendapi.h" +#include +#include "mozilla/dom/NodeInfoInlines.h" +#include "mozilla/MruCache.h" +#include "mozilla/StaticPtr.h" + +#include "PLDHashTable.h" +#include "nsTHashtable.h" + +#ifdef DEBUG_CONTENT_LIST +# define ASSERT_IN_SYNC AssertInSync() +#else +# define ASSERT_IN_SYNC PR_BEGIN_MACRO PR_END_MACRO +#endif + +using namespace mozilla; +using namespace mozilla::dom; + +nsBaseContentList::~nsBaseContentList() = default; + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(nsBaseContentList) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + tmp->RemoveFromCaches(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsBaseContentList) + if (nsCCUncollectableMarker::sGeneration && tmp->HasKnownLiveWrapper()) { + for (uint32_t i = 0; i < tmp->mElements.Length(); ++i) { + nsIContent* c = tmp->mElements[i]; + if (c->IsPurple()) { + c->RemovePurple(); + } + Element::MarkNodeChildren(c); + } + return true; + } +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsBaseContentList) + return nsCCUncollectableMarker::sGeneration && tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsBaseContentList) + return nsCCUncollectableMarker::sGeneration && tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + +// QueryInterface implementation for nsBaseContentList +NS_INTERFACE_TABLE_HEAD(nsBaseContentList) + NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY + NS_INTERFACE_TABLE(nsBaseContentList, nsINodeList) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsBaseContentList) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBaseContentList) +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsBaseContentList, + LastRelease()) + +nsIContent* nsBaseContentList::Item(uint32_t aIndex) { + return mElements.SafeElementAt(aIndex); +} + +int32_t nsBaseContentList::IndexOf(nsIContent* aContent, bool aDoFlush) { + return mElements.IndexOf(aContent); +} + +int32_t nsBaseContentList::IndexOf(nsIContent* aContent) { + return IndexOf(aContent, true); +} + +size_t nsBaseContentList::SizeOfIncludingThis( + MallocSizeOf aMallocSizeOf) const { + size_t n = aMallocSizeOf(this); + n += mElements.ShallowSizeOfExcludingThis(aMallocSizeOf); + return n; +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(nsSimpleContentList, nsBaseContentList, + mRoot) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSimpleContentList) +NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList) + +NS_IMPL_ADDREF_INHERITED(nsSimpleContentList, nsBaseContentList) +NS_IMPL_RELEASE_INHERITED(nsSimpleContentList, nsBaseContentList) + +JSObject* nsSimpleContentList::WrapObject(JSContext* cx, + JS::Handle aGivenProto) { + return NodeList_Binding::Wrap(cx, this, aGivenProto); +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(nsEmptyContentList, nsBaseContentList, mRoot) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEmptyContentList) + NS_INTERFACE_MAP_ENTRY(nsIHTMLCollection) +NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList) + +NS_IMPL_ADDREF_INHERITED(nsEmptyContentList, nsBaseContentList) +NS_IMPL_RELEASE_INHERITED(nsEmptyContentList, nsBaseContentList) + +JSObject* nsEmptyContentList::WrapObject(JSContext* cx, + JS::Handle aGivenProto) { + return HTMLCollection_Binding::Wrap(cx, this, aGivenProto); +} + +mozilla::dom::Element* nsEmptyContentList::GetElementAt(uint32_t index) { + return nullptr; +} + +mozilla::dom::Element* nsEmptyContentList::GetFirstNamedElement( + const nsAString& aName, bool& aFound) { + aFound = false; + return nullptr; +} + +void nsEmptyContentList::GetSupportedNames(nsTArray& aNames) {} + +nsIContent* nsEmptyContentList::Item(uint32_t aIndex) { return nullptr; } + +struct ContentListCache + : public MruCache { + static HashNumber Hash(const nsContentListKey& aKey) { + return aKey.GetHash(); + } + static bool Match(const nsContentListKey& aKey, const nsContentList* aVal) { + return aVal->MatchesKey(aKey); + } +}; + +static ContentListCache sRecentlyUsedContentLists; + +class nsContentList::HashEntry : public PLDHashEntryHdr { + public: + using KeyType = const nsContentListKey*; + using KeyTypePointer = KeyType; + + // Note that this is creating a blank entry, so you'll have to manually + // initialize it after it has been inserted into the hash table. + explicit HashEntry(KeyTypePointer aKey) : mContentList(nullptr) {} + + HashEntry(HashEntry&& aEnt) : mContentList(std::move(aEnt.mContentList)) {} + + ~HashEntry() { + if (mContentList) { + MOZ_RELEASE_ASSERT(mContentList->mInHashtable); + mContentList->mInHashtable = false; + } + } + + bool KeyEquals(KeyTypePointer aKey) const { + return mContentList->MatchesKey(*aKey); + } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; } + + static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->GetHash(); } + + nsContentList* GetContentList() const { return mContentList; } + void SetContentList(nsContentList* aContentList) { + MOZ_RELEASE_ASSERT(!mContentList); + MOZ_ASSERT(aContentList); + MOZ_RELEASE_ASSERT(!aContentList->mInHashtable); + mContentList = aContentList; + mContentList->mInHashtable = true; + } + + enum { ALLOW_MEMMOVE = true }; + + private: + nsContentList* MOZ_UNSAFE_REF( + "This entry will be removed in nsContentList::RemoveFromHashtable " + "before mContentList is destroyed") mContentList; +}; + +// Hashtable for storing nsContentLists +static StaticAutoPtr> + gContentListHashTable; + +already_AddRefed NS_GetContentList(nsINode* aRootNode, + int32_t aMatchNameSpaceId, + const nsAString& aTagname) { + NS_ASSERTION(aRootNode, "content list has to have a root"); + + RefPtr list; + nsContentListKey hashKey(aRootNode, aMatchNameSpaceId, aTagname, + aRootNode->OwnerDoc()->IsHTMLDocument()); + auto p = sRecentlyUsedContentLists.Lookup(hashKey); + if (p) { + list = p.Data(); + return list.forget(); + } + + // Initialize the hashtable if needed. + if (!gContentListHashTable) { + gContentListHashTable = new nsTHashtable(); + } + + // First we look in our hashtable. Then we create a content list if needed + auto entry = gContentListHashTable->PutEntry(&hashKey, fallible); + if (entry) { + list = entry->GetContentList(); + } + + if (!list) { + // We need to create a ContentList and add it to our new entry, if + // we have an entry + RefPtr xmlAtom = NS_Atomize(aTagname); + RefPtr htmlAtom; + if (aMatchNameSpaceId == kNameSpaceID_Unknown) { + nsAutoString lowercaseName; + nsContentUtils::ASCIIToLower(aTagname, lowercaseName); + htmlAtom = NS_Atomize(lowercaseName); + } else { + htmlAtom = xmlAtom; + } + list = new nsContentList(aRootNode, aMatchNameSpaceId, htmlAtom, xmlAtom); + if (entry) { + entry->SetContentList(list); + } + } + + p.Set(list); + return list.forget(); +} + +#ifdef DEBUG +const nsCacheableFuncStringContentList::ContentListType + nsCachableElementsByNameNodeList::sType = + nsCacheableFuncStringContentList::eNodeList; +const nsCacheableFuncStringContentList::ContentListType + nsCacheableFuncStringHTMLCollection::sType = + nsCacheableFuncStringContentList::eHTMLCollection; +#endif + +class nsCacheableFuncStringContentList::HashEntry : public PLDHashEntryHdr { + public: + using KeyType = const nsFuncStringCacheKey*; + using KeyTypePointer = KeyType; + + // Note that this is creating a blank entry, so you'll have to manually + // initialize it after it has been inserted into the hash table. + explicit HashEntry(KeyTypePointer aKey) : mContentList(nullptr) {} + + HashEntry(HashEntry&& aEnt) : mContentList(std::move(aEnt.mContentList)) {} + + ~HashEntry() { + if (mContentList) { + MOZ_RELEASE_ASSERT(mContentList->mInHashtable); + mContentList->mInHashtable = false; + } + } + + bool KeyEquals(KeyTypePointer aKey) const { + return mContentList->Equals(aKey); + } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; } + + static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->GetHash(); } + + nsCacheableFuncStringContentList* GetContentList() const { + return mContentList; + } + void SetContentList(nsCacheableFuncStringContentList* aContentList) { + MOZ_RELEASE_ASSERT(!mContentList); + MOZ_ASSERT(aContentList); + MOZ_RELEASE_ASSERT(!aContentList->mInHashtable); + mContentList = aContentList; + mContentList->mInHashtable = true; + } + + enum { ALLOW_MEMMOVE = true }; + + private: + nsCacheableFuncStringContentList* MOZ_UNSAFE_REF( + "This entry will be removed in " + "nsCacheableFuncStringContentList::RemoveFromFuncStringHashtable " + "before mContentList is destroyed") mContentList; +}; + +// Hashtable for storing nsCacheableFuncStringContentList +static StaticAutoPtr> + gFuncStringContentListHashTable; + +template +already_AddRefed GetFuncStringContentList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString) { + NS_ASSERTION(aRootNode, "content list has to have a root"); + + RefPtr list; + + // Initialize the hashtable if needed. + if (!gFuncStringContentListHashTable) { + gFuncStringContentListHashTable = + new nsTHashtable(); + } + + nsCacheableFuncStringContentList::HashEntry* entry = nullptr; + // First we look in our hashtable. Then we create a content list if needed + if (gFuncStringContentListHashTable) { + nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString); + + entry = gFuncStringContentListHashTable->PutEntry(&hashKey, fallible); + if (entry) { + list = entry->GetContentList(); +#ifdef DEBUG + MOZ_ASSERT_IF(list, list->mType == ListType::sType); +#endif + } + } + + if (!list) { + // We need to create a ContentList and add it to our new entry, if + // we have an entry + list = + new ListType(aRootNode, aFunc, aDestroyFunc, aDataAllocator, aString); + if (entry) { + entry->SetContentList(list); + } + } + + // Don't cache these lists globally + + return list.forget(); +} + +// Explicit instantiations to avoid link errors +template already_AddRefed +GetFuncStringContentList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString); +template already_AddRefed +GetFuncStringContentList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString); + +//----------------------------------------------------- +// nsContentList implementation + +nsContentList::nsContentList(nsINode* aRootNode, int32_t aMatchNameSpaceId, + nsAtom* aHTMLMatchAtom, nsAtom* aXMLMatchAtom, + bool aDeep, bool aLiveList) + : nsBaseContentList(), + mRootNode(aRootNode), + mMatchNameSpaceId(aMatchNameSpaceId), + mHTMLMatchAtom(aHTMLMatchAtom), + mXMLMatchAtom(aXMLMatchAtom), + mState(State::Dirty), + mDeep(aDeep), + mFuncMayDependOnAttr(false), + mIsHTMLDocument(aRootNode->OwnerDoc()->IsHTMLDocument()), + mNamedItemsCacheValid(false), + mIsLiveList(aLiveList), + mInHashtable(false) { + NS_ASSERTION(mRootNode, "Must have root"); + if (nsGkAtoms::_asterisk == mHTMLMatchAtom) { + NS_ASSERTION(mXMLMatchAtom == nsGkAtoms::_asterisk, + "HTML atom and XML atom are not both asterisk?"); + mMatchAll = true; + } else { + mMatchAll = false; + } + // This is aLiveList instead of mIsLiveList to avoid Valgrind errors. + if (aLiveList) { + SetEnabledCallbacks(nsIMutationObserver::kNodeWillBeDestroyed); + mRootNode->AddMutationObserver(this); + } + + // We only need to flush if we're in an non-HTML document, since the + // HTML5 parser doesn't need flushing. Further, if we're not in a + // document at all right now (in the GetUncomposedDoc() sense), we're + // not parser-created and don't need to be flushing stuff under us + // to get our kids right. + Document* doc = mRootNode->GetUncomposedDoc(); + mFlushesNeeded = doc && !doc->IsHTMLDocument(); +} + +nsContentList::nsContentList(nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, void* aData, + bool aDeep, nsAtom* aMatchAtom, + int32_t aMatchNameSpaceId, + bool aFuncMayDependOnAttr, bool aLiveList) + : nsBaseContentList(), + mRootNode(aRootNode), + mMatchNameSpaceId(aMatchNameSpaceId), + mHTMLMatchAtom(aMatchAtom), + mXMLMatchAtom(aMatchAtom), + mFunc(aFunc), + mDestroyFunc(aDestroyFunc), + mData(aData), + mState(State::Dirty), + mMatchAll(false), + mDeep(aDeep), + mFuncMayDependOnAttr(aFuncMayDependOnAttr), + mIsHTMLDocument(false), + mNamedItemsCacheValid(false), + mIsLiveList(aLiveList), + mInHashtable(false) { + NS_ASSERTION(mRootNode, "Must have root"); + // This is aLiveList instead of mIsLiveList to avoid Valgrind errors. + if (aLiveList) { + SetEnabledCallbacks(nsIMutationObserver::kNodeWillBeDestroyed); + mRootNode->AddMutationObserver(this); + } + + // We only need to flush if we're in an non-HTML document, since the + // HTML5 parser doesn't need flushing. Further, if we're not in a + // document at all right now (in the GetUncomposedDoc() sense), we're + // not parser-created and don't need to be flushing stuff under us + // to get our kids right. + Document* doc = mRootNode->GetUncomposedDoc(); + mFlushesNeeded = doc && !doc->IsHTMLDocument(); +} + +nsContentList::~nsContentList() { + RemoveFromHashtable(); + if (mIsLiveList && mRootNode) { + mRootNode->RemoveMutationObserver(this); + } + + if (mDestroyFunc) { + // Clean up mData + (*mDestroyFunc)(mData); + } +} + +JSObject* nsContentList::WrapObject(JSContext* cx, + JS::Handle aGivenProto) { + return HTMLCollection_Binding::Wrap(cx, this, aGivenProto); +} + +NS_IMPL_ISUPPORTS_INHERITED(nsContentList, nsBaseContentList, nsIHTMLCollection, + nsIMutationObserver) + +uint32_t nsContentList::Length(bool aDoFlush) { + BringSelfUpToDate(aDoFlush); + + return mElements.Length(); +} + +nsIContent* nsContentList::Item(uint32_t aIndex, bool aDoFlush) { + if (mRootNode && aDoFlush && mFlushesNeeded) { + // XXX sXBL/XBL2 issue + Document* doc = mRootNode->GetUncomposedDoc(); + if (doc) { + // Flush pending content changes Bug 4891. + doc->FlushPendingNotifications(FlushType::ContentAndNotify); + } + } + + if (mState != State::UpToDate) { + PopulateSelf(std::min(aIndex, UINT32_MAX - 1) + 1); + } + + ASSERT_IN_SYNC; + NS_ASSERTION(!mRootNode || mState != State::Dirty, + "PopulateSelf left the list in a dirty (useless) state!"); + + return mElements.SafeElementAt(aIndex); +} + +inline void nsContentList::InsertElementInNamedItemsCache( + nsIContent& aContent) { + const bool hasName = aContent.HasName(); + const bool hasId = aContent.HasID(); + if (!hasName && !hasId) { + return; + } + + Element* el = aContent.AsElement(); + MOZ_ASSERT_IF(hasName, el->IsHTMLElement()); + + uint32_t i = 0; + while (BorrowedAttrInfo info = el->GetAttrInfoAt(i++)) { + const bool valid = (info.mName->Equals(nsGkAtoms::name) && hasName) || + (info.mName->Equals(nsGkAtoms::id) && hasId); + if (!valid) { + continue; + } + + if (!mNamedItemsCache) { + mNamedItemsCache = MakeUnique(); + } + + nsAtom* name = info.mValue->GetAtomValue(); + // NOTE: LookupOrInsert makes sure we keep the first element we find for a + // given name. + mNamedItemsCache->LookupOrInsert(name, el); + } +} + +inline void nsContentList::InvalidateNamedItemsCacheForAttributeChange( + int32_t aNamespaceID, nsAtom* aAttribute) { + if (!mNamedItemsCacheValid) { + return; + } + if ((aAttribute == nsGkAtoms::id || aAttribute == nsGkAtoms::name) && + aNamespaceID == kNameSpaceID_None) { + InvalidateNamedItemsCache(); + } +} + +inline void nsContentList::InvalidateNamedItemsCacheForInsertion( + Element& aElement) { + if (!mNamedItemsCacheValid) { + return; + } + + InsertElementInNamedItemsCache(aElement); +} + +inline void nsContentList::InvalidateNamedItemsCacheForDeletion( + Element& aElement) { + if (!mNamedItemsCacheValid) { + return; + } + if (aElement.HasName() || aElement.HasID()) { + InvalidateNamedItemsCache(); + } +} + +void nsContentList::EnsureNamedItemsCacheValid(bool aDoFlush) { + BringSelfUpToDate(aDoFlush); + + if (mNamedItemsCacheValid) { + return; + } + + MOZ_ASSERT(!mNamedItemsCache); + + // https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem-key + // XXX: Blink/WebKit don't follow the spec here, and searches first-by-id, + // then by name. + for (const nsCOMPtr& content : mElements) { + InsertElementInNamedItemsCache(*content); + } + + mNamedItemsCacheValid = true; +} + +Element* nsContentList::NamedItem(const nsAString& aName, bool aDoFlush) { + if (aName.IsEmpty()) { + return nullptr; + } + + EnsureNamedItemsCacheValid(aDoFlush); + + if (!mNamedItemsCache) { + return nullptr; + } + + // Typically IDs and names are atomized + RefPtr name = NS_Atomize(aName); + NS_ENSURE_TRUE(name, nullptr); + + return mNamedItemsCache->Get(name); +} + +void nsContentList::GetSupportedNames(nsTArray& aNames) { + BringSelfUpToDate(true); + + AutoTArray atoms; + for (uint32_t i = 0; i < mElements.Length(); ++i) { + nsIContent* content = mElements.ElementAt(i); + if (content->HasID()) { + nsAtom* id = content->GetID(); + MOZ_ASSERT(id != nsGkAtoms::_empty, "Empty ids don't get atomized"); + if (!atoms.Contains(id)) { + atoms.AppendElement(id); + } + } + + nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(content); + if (el) { + // XXXbz should we be checking for particular tags here? How + // stable is this part of the spec? + // Note: nsINode::HasName means the name is exposed on the document, + // which is false for options, so we don't check it here. + const nsAttrValue* val = el->GetParsedAttr(nsGkAtoms::name); + if (val && val->Type() == nsAttrValue::eAtom) { + nsAtom* name = val->GetAtomValue(); + MOZ_ASSERT(name != nsGkAtoms::_empty, "Empty names don't get atomized"); + if (!atoms.Contains(name)) { + atoms.AppendElement(name); + } + } + } + } + + uint32_t atomsLen = atoms.Length(); + nsString* names = aNames.AppendElements(atomsLen); + for (uint32_t i = 0; i < atomsLen; ++i) { + atoms[i]->ToString(names[i]); + } +} + +int32_t nsContentList::IndexOf(nsIContent* aContent, bool aDoFlush) { + BringSelfUpToDate(aDoFlush); + + return mElements.IndexOf(aContent); +} + +int32_t nsContentList::IndexOf(nsIContent* aContent) { + return IndexOf(aContent, true); +} + +void nsContentList::NodeWillBeDestroyed(nsINode* aNode) { + // We shouldn't do anything useful from now on + + RemoveFromCaches(); + mRootNode = nullptr; + + // We will get no more updates, so we can never know we're up to + // date + SetDirty(); +} + +void nsContentList::LastRelease() { + RemoveFromCaches(); + if (mIsLiveList && mRootNode) { + mRootNode->RemoveMutationObserver(this); + mRootNode = nullptr; + } + SetDirty(); +} + +Element* nsContentList::GetElementAt(uint32_t aIndex) { + return static_cast(Item(aIndex, true)); +} + +nsIContent* nsContentList::Item(uint32_t aIndex) { + return GetElementAt(aIndex); +} + +void nsContentList::AttributeChanged(Element* aElement, int32_t aNameSpaceID, + nsAtom* aAttribute, int32_t aModType, + const nsAttrValue* aOldValue) { + MOZ_ASSERT(aElement, "Must have a content node to work with"); + + if (mState == State::Dirty || + !MayContainRelevantNodes(aElement->GetParentNode()) || + !nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) { + // Either we're already dirty or aElement will never match us. + return; + } + + InvalidateNamedItemsCacheForAttributeChange(aNameSpaceID, aAttribute); + + if (!mFunc || !mFuncMayDependOnAttr) { + // aElement might be relevant but the attribute change doesn't affect + // whether we match it. + return; + } + + if (Match(aElement)) { + if (mElements.IndexOf(aElement) == mElements.NoIndex) { + // We match aElement now, and it's not in our list already. Just dirty + // ourselves; this is simpler than trying to figure out where to insert + // aElement. + SetDirty(); + } + } else { + // We no longer match aElement. Remove it from our list. If it's + // already not there, this is a no-op (though a potentially + // expensive one). Either way, no change of mState is required + // here. + if (mElements.RemoveElement(aElement)) { + InvalidateNamedItemsCacheForDeletion(*aElement); + } + } +} + +void nsContentList::ContentAppended(nsIContent* aFirstNewContent) { + nsIContent* container = aFirstNewContent->GetParent(); + MOZ_ASSERT(container, "Can't get at the new content if no container!"); + + /* + * If the state is State::Dirty then we have no useful information in our list + * and we want to put off doing work as much as possible. + * + * Also, if container is anonymous from our point of view, we know that we + * can't possibly be matching any of the kids. + * + * Optimize out also the common case when just one new node is appended and + * it doesn't match us. + */ + if (mState == State::Dirty || + !nsContentUtils::IsInSameAnonymousTree(mRootNode, container) || + !MayContainRelevantNodes(container) || + (!aFirstNewContent->HasChildren() && + !aFirstNewContent->GetNextSibling() && !MatchSelf(aFirstNewContent))) { + MaybeMarkDirty(); + return; + } + + /* + * We want to handle the case of ContentAppended by sometimes + * appending the content to our list, not just setting state to + * State::Dirty, since most of our ContentAppended notifications + * should come during pageload and be at the end of the document. + * Do a bit of work to see whether we could just append to what we + * already have. + */ + + uint32_t ourCount = mElements.Length(); + const bool appendingToList = [&] { + if (ourCount == 0) { + return true; + } + if (mRootNode == container) { + return true; + } + return nsContentUtils::PositionIsBefore(mElements.LastElement(), + aFirstNewContent); + }(); + + if (!appendingToList) { + // The new stuff is somewhere in the middle of our list; check + // whether we need to invalidate + for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) { + if (MatchSelf(cur)) { + // Uh-oh. We're gonna have to add elements into the middle + // of our list. That's not worth the effort. + SetDirty(); + break; + } + } + + ASSERT_IN_SYNC; + return; + } + + /* + * At this point we know we could append. If we're not up to + * date, however, that would be a bad idea -- it could miss some + * content that we never picked up due to being lazy. Further, we + * may never get asked for this content... so don't grab it yet. + */ + if (mState == State::Lazy) { + return; + } + + /* + * We're up to date. That means someone's actively using us; we + * may as well grab this content.... + */ + if (mDeep) { + for (nsIContent* cur = aFirstNewContent; cur; + cur = cur->GetNextNode(container)) { + if (cur->IsElement() && Match(cur->AsElement())) { + mElements.AppendElement(cur); + InvalidateNamedItemsCacheForInsertion(*cur->AsElement()); + } + } + } else { + for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) { + if (cur->IsElement() && Match(cur->AsElement())) { + mElements.AppendElement(cur); + InvalidateNamedItemsCacheForInsertion(*cur->AsElement()); + } + } + } + + ASSERT_IN_SYNC; +} + +void nsContentList::ContentInserted(nsIContent* aChild) { + // Note that aChild->GetParentNode() can be null here if we are inserting into + // the document itself; any attempted optimizations to this method should deal + // with that. + if (mState != State::Dirty && + MayContainRelevantNodes(aChild->GetParentNode()) && + nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) && + MatchSelf(aChild)) { + SetDirty(); + } + + ASSERT_IN_SYNC; +} + +void nsContentList::ContentRemoved(nsIContent* aChild, + nsIContent* aPreviousSibling) { + if (mState != State::Dirty && + MayContainRelevantNodes(aChild->GetParentNode()) && + nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) && + MatchSelf(aChild)) { + SetDirty(); + } + + ASSERT_IN_SYNC; +} + +bool nsContentList::Match(Element* aElement) { + if (mFunc) { + return (*mFunc)(aElement, mMatchNameSpaceId, mXMLMatchAtom, mData); + } + + if (!mXMLMatchAtom) return false; + + NodeInfo* ni = aElement->NodeInfo(); + + bool unknown = mMatchNameSpaceId == kNameSpaceID_Unknown; + bool wildcard = mMatchNameSpaceId == kNameSpaceID_Wildcard; + bool toReturn = mMatchAll; + if (!unknown && !wildcard) toReturn &= ni->NamespaceEquals(mMatchNameSpaceId); + + if (toReturn) return toReturn; + + bool matchHTML = + mIsHTMLDocument && aElement->GetNameSpaceID() == kNameSpaceID_XHTML; + + if (unknown) { + return matchHTML ? ni->QualifiedNameEquals(mHTMLMatchAtom) + : ni->QualifiedNameEquals(mXMLMatchAtom); + } + + if (wildcard) { + return matchHTML ? ni->Equals(mHTMLMatchAtom) : ni->Equals(mXMLMatchAtom); + } + + return matchHTML ? ni->Equals(mHTMLMatchAtom, mMatchNameSpaceId) + : ni->Equals(mXMLMatchAtom, mMatchNameSpaceId); +} + +bool nsContentList::MatchSelf(nsIContent* aContent) { + MOZ_ASSERT(aContent, "Can't match null stuff, you know"); + MOZ_ASSERT(mDeep || aContent->GetParentNode() == mRootNode, + "MatchSelf called on a node that we can't possibly match"); + + if (!aContent->IsElement()) { + return false; + } + + if (Match(aContent->AsElement())) return true; + + if (!mDeep) return false; + + for (nsIContent* cur = aContent->GetFirstChild(); cur; + cur = cur->GetNextNode(aContent)) { + if (cur->IsElement() && Match(cur->AsElement())) { + return true; + } + } + + return false; +} + +void nsContentList::PopulateSelf(uint32_t aNeededLength, + uint32_t aExpectedElementsIfDirty) { + if (!mRootNode) { + return; + } + + ASSERT_IN_SYNC; + + uint32_t count = mElements.Length(); + NS_ASSERTION(mState != State::Dirty || count == aExpectedElementsIfDirty, + "Reset() not called when setting state to State::Dirty?"); + + if (count >= aNeededLength) // We're all set + return; + + uint32_t elementsToAppend = aNeededLength - count; +#ifdef DEBUG + uint32_t invariant = elementsToAppend + mElements.Length(); +#endif + + if (mDeep) { + // If we already have nodes start searching at the last one, otherwise + // start searching at the root. + nsINode* cur = count ? mElements[count - 1].get() : mRootNode; + do { + cur = cur->GetNextNode(mRootNode); + if (!cur) { + break; + } + if (cur->IsElement() && Match(cur->AsElement())) { + // Append AsElement() to get nsIContent instead of nsINode + mElements.AppendElement(cur->AsElement()); + --elementsToAppend; + } + } while (elementsToAppend); + } else { + nsIContent* cur = count ? mElements[count - 1]->GetNextSibling() + : mRootNode->GetFirstChild(); + for (; cur && elementsToAppend; cur = cur->GetNextSibling()) { + if (cur->IsElement() && Match(cur->AsElement())) { + mElements.AppendElement(cur); + --elementsToAppend; + } + } + } + + NS_ASSERTION(elementsToAppend + mElements.Length() == invariant, + "Something is awry!"); + + if (elementsToAppend != 0) { + mState = State::UpToDate; + } else { + mState = State::Lazy; + } + + SetEnabledCallbacks(nsIMutationObserver::kAll); + + ASSERT_IN_SYNC; +} + +void nsContentList::RemoveFromHashtable() { + if (mFunc) { + // nsCacheableFuncStringContentList can be in a hash table without being + // in gContentListHashTable, but it will have been removed from the hash + // table in its dtor before it runs the nsContentList dtor. + MOZ_RELEASE_ASSERT(!mInHashtable); + + // This can't be in gContentListHashTable. + return; + } + + nsDependentAtomString str(mXMLMatchAtom); + nsContentListKey key(mRootNode, mMatchNameSpaceId, str, mIsHTMLDocument); + sRecentlyUsedContentLists.Remove(key); + + if (gContentListHashTable) { + gContentListHashTable->RemoveEntry(&key); + + if (gContentListHashTable->Count() == 0) { + gContentListHashTable = nullptr; + } + } + + MOZ_RELEASE_ASSERT(!mInHashtable); +} + +void nsContentList::BringSelfUpToDate(bool aDoFlush) { + if (mFlushesNeeded && mRootNode && aDoFlush) { + // XXX sXBL/XBL2 issue + if (Document* doc = mRootNode->GetUncomposedDoc()) { + // Flush pending content changes Bug 4891. + doc->FlushPendingNotifications(FlushType::ContentAndNotify); + } + } + + if (mState != State::UpToDate) { + PopulateSelf(uint32_t(-1)); + } + + mMissedUpdates = 0; + + ASSERT_IN_SYNC; + NS_ASSERTION(!mRootNode || mState == State::UpToDate, + "PopulateSelf dod not bring content list up to date!"); +} + +nsCacheableFuncStringContentList::~nsCacheableFuncStringContentList() { + RemoveFromFuncStringHashtable(); +} + +void nsCacheableFuncStringContentList::RemoveFromFuncStringHashtable() { + if (!gFuncStringContentListHashTable) { + MOZ_RELEASE_ASSERT(!mInHashtable); + return; + } + + nsFuncStringCacheKey key(mRootNode, mFunc, mString); + gFuncStringContentListHashTable->RemoveEntry(&key); + + if (gFuncStringContentListHashTable->Count() == 0) { + gFuncStringContentListHashTable = nullptr; + } + + MOZ_RELEASE_ASSERT(!mInHashtable); +} + +#ifdef DEBUG_CONTENT_LIST +void nsContentList::AssertInSync() { + if (mState == State::Dirty) { + return; + } + + if (!mRootNode) { + NS_ASSERTION(mElements.Length() == 0 && mState == State::Dirty, + "Empty iterator isn't quite empty?"); + return; + } + + // XXX This code will need to change if nsContentLists can ever match + // elements that are outside of the document element. + nsIContent* root = mRootNode->IsDocument() + ? mRootNode->AsDocument()->GetRootElement() + : mRootNode->AsContent(); + + PreContentIterator preOrderIter; + if (mDeep) { + preOrderIter.Init(root); + preOrderIter.First(); + } + + uint32_t cnt = 0, index = 0; + while (true) { + if (cnt == mElements.Length() && mState == State::Lazy) { + break; + } + + nsIContent* cur = + mDeep ? preOrderIter.GetCurrentNode() : mRootNode->GetChildAt(index++); + if (!cur) { + break; + } + + if (cur->IsElement() && Match(cur->AsElement())) { + NS_ASSERTION(cnt < mElements.Length() && mElements[cnt] == cur, + "Elements is out of sync"); + ++cnt; + } + + if (mDeep) { + preOrderIter.Next(); + } + } + + NS_ASSERTION(cnt == mElements.Length(), "Too few elements"); +} +#endif + +//----------------------------------------------------- +// nsCachableElementsByNameNodeList + +JSObject* nsCachableElementsByNameNodeList::WrapObject( + JSContext* cx, JS::Handle aGivenProto) { + return NodeList_Binding::Wrap(cx, this, aGivenProto); +} + +void nsCachableElementsByNameNodeList::AttributeChanged( + Element* aElement, int32_t aNameSpaceID, nsAtom* aAttribute, + int32_t aModType, const nsAttrValue* aOldValue) { + // No need to rebuild the list if the changed attribute is not the name + // attribute. + if (aAttribute != nsGkAtoms::name) { + InvalidateNamedItemsCacheForAttributeChange(aNameSpaceID, aAttribute); + return; + } + + nsCacheableFuncStringContentList::AttributeChanged( + aElement, aNameSpaceID, aAttribute, aModType, aOldValue); +} + +//----------------------------------------------------- +// nsCacheableFuncStringHTMLCollection + +JSObject* nsCacheableFuncStringHTMLCollection::WrapObject( + JSContext* cx, JS::Handle aGivenProto) { + return HTMLCollection_Binding::Wrap(cx, this, aGivenProto); +} + +//----------------------------------------------------- +// nsLabelsNodeList + +JSObject* nsLabelsNodeList::WrapObject(JSContext* cx, + JS::Handle aGivenProto) { + return NodeList_Binding::Wrap(cx, this, aGivenProto); +} + +void nsLabelsNodeList::AttributeChanged(Element* aElement, int32_t aNameSpaceID, + nsAtom* aAttribute, int32_t aModType, + const nsAttrValue* aOldValue) { + MOZ_ASSERT(aElement, "Must have a content node to work with"); + if (mState == State::Dirty || + !nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) { + return; + } + + InvalidateNamedItemsCacheForAttributeChange(aNameSpaceID, aAttribute); + + // We need to handle input type changes to or from "hidden". + if (aElement->IsHTMLElement(nsGkAtoms::input) && + aAttribute == nsGkAtoms::type && aNameSpaceID == kNameSpaceID_None) { + SetDirty(); + return; + } +} + +void nsLabelsNodeList::ContentAppended(nsIContent* aFirstNewContent) { + nsIContent* container = aFirstNewContent->GetParent(); + // If a labelable element is moved to outside or inside of + // nested associated labels, we're gonna have to modify + // the content list. + if (mState != State::Dirty || + nsContentUtils::IsInSameAnonymousTree(mRootNode, container)) { + SetDirty(); + return; + } +} + +void nsLabelsNodeList::ContentInserted(nsIContent* aChild) { + // If a labelable element is moved to outside or inside of + // nested associated labels, we're gonna have to modify + // the content list. + if (mState != State::Dirty || + nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) { + SetDirty(); + return; + } +} + +void nsLabelsNodeList::ContentRemoved(nsIContent* aChild, + nsIContent* aPreviousSibling) { + // If a labelable element is removed, we're gonna have to clean + // the content list. + if (mState != State::Dirty || + nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) { + SetDirty(); + return; + } +} + +void nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode) { + MOZ_ASSERT(aRootNode, "Must have root"); + if (mRootNode == aRootNode) { + return; + } + + MOZ_ASSERT(mIsLiveList, "nsLabelsNodeList is always a live list"); + if (mRootNode) { + mRootNode->RemoveMutationObserver(this); + } + mRootNode = aRootNode; + mRootNode->AddMutationObserver(this); + SetDirty(); +} + +void nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength, + uint32_t aExpectedElementsIfDirty) { + if (!mRootNode) { + return; + } + + // Start searching at the root. + nsINode* cur = mRootNode; + if (mElements.IsEmpty() && cur->IsElement() && Match(cur->AsElement())) { + mElements.AppendElement(cur->AsElement()); + ++aExpectedElementsIfDirty; + } + + nsContentList::PopulateSelf(aNeededLength, aExpectedElementsIfDirty); +} diff --git a/dom/base/nsContentList.h b/dom/base/nsContentList.h new file mode 100644 index 0000000000..a70c5281b2 --- /dev/null +++ b/dom/base/nsContentList.h @@ -0,0 +1,655 @@ +/* -*- 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/. */ + +/* + * nsBaseContentList is a basic list of content nodes; nsContentList + * is a commonly used NodeList implementation (used for + * getElementsByTagName, some properties on HTMLDocument/Document, etc). + */ + +#ifndef nsContentList_h___ +#define nsContentList_h___ + +#include "mozilla/Attributes.h" +#include "nsContentListDeclarations.h" +#include "nsISupports.h" +#include "nsTArray.h" +#include "nsString.h" +#include "nsIHTMLCollection.h" +#include "nsINodeList.h" +#include "nsStubMutationObserver.h" +#include "nsAtomHashKeys.h" +#include "nsCycleCollectionParticipant.h" +#include "nsNameSpaceManager.h" +#include "nsWrapperCache.h" +#include "nsHashKeys.h" +#include "mozilla/HashFunctions.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/dom/NameSpaceConstants.h" + +// XXX Avoid including this here by moving function bodies to the cpp file. +#include "nsIContent.h" + +namespace mozilla::dom { +class Element; +} // namespace mozilla::dom + +class nsBaseContentList : public nsINodeList { + protected: + using Element = mozilla::dom::Element; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + // nsINodeList + int32_t IndexOf(nsIContent* aContent) override; + nsIContent* Item(uint32_t aIndex) override; + + uint32_t Length() override { return mElements.Length(); } + + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS(nsBaseContentList) + + void AppendElement(nsIContent* aContent) { + MOZ_ASSERT(aContent); + mElements.AppendElement(aContent); + } + void MaybeAppendElement(nsIContent* aContent) { + if (aContent) { + AppendElement(aContent); + } + } + + /** + * Insert the element at a given index, shifting the objects at + * the given index and later to make space. + * @param aContent Element to insert, must not be null + * @param aIndex Index to insert the element at. + */ + void InsertElementAt(nsIContent* aContent, int32_t aIndex) { + NS_ASSERTION(aContent, "Element to insert must not be null"); + mElements.InsertElementAt(aIndex, aContent); + } + + void RemoveElement(nsIContent* aContent) { + mElements.RemoveElement(aContent); + } + + void Reset() { mElements.Clear(); } + + virtual int32_t IndexOf(nsIContent* aContent, bool aDoFlush); + + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override = 0; + + void SetCapacity(uint32_t aCapacity) { mElements.SetCapacity(aCapacity); } + + virtual void LastRelease() {} + + // Memory reporting. For now, subclasses of nsBaseContentList don't really + // need to report any members that are not part of the object itself, so we + // don't need to make this virtual. + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + protected: + virtual ~nsBaseContentList(); + + /** + * To be called from non-destructor locations (e.g. unlink) that want to + * remove from caches. Cacheable subclasses should override. + */ + virtual void RemoveFromCaches() {} + + AutoTArray, 10> mElements; +}; + +class nsSimpleContentList : public nsBaseContentList { + public: + explicit nsSimpleContentList(nsINode* aRoot) + : nsBaseContentList(), mRoot(aRoot) {} + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSimpleContentList, + nsBaseContentList) + + nsINode* GetParentObject() override { return mRoot; } + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + + protected: + virtual ~nsSimpleContentList() = default; + + private: + // This has to be a strong reference, the root might go away before the list. + nsCOMPtr mRoot; +}; + +// Used for returning lists that will always be empty, such as the applets list +// in HTML Documents +class nsEmptyContentList final : public nsBaseContentList, + public nsIHTMLCollection { + public: + explicit nsEmptyContentList(nsINode* aRoot) + : nsBaseContentList(), mRoot(aRoot) {} + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsEmptyContentList, + nsBaseContentList) + + nsINode* GetParentObject() override { return mRoot; } + + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + + JSObject* GetWrapperPreserveColorInternal() override { + return nsWrapperCache::GetWrapperPreserveColor(); + } + void PreserveWrapperInternal(nsISupports* aScriptObjectHolder) override { + nsWrapperCache::PreserveWrapper(aScriptObjectHolder); + } + + uint32_t Length() final { return 0; } + nsIContent* Item(uint32_t aIndex) override; + Element* GetElementAt(uint32_t index) override; + Element* GetFirstNamedElement(const nsAString& aName, bool& aFound) override; + void GetSupportedNames(nsTArray& aNames) override; + + protected: + virtual ~nsEmptyContentList() = default; + + private: + // This has to be a strong reference, the root might go away before the list. + nsCOMPtr mRoot; +}; + +/** + * Class that's used as the key to hash nsContentList implementations + * for fast retrieval + */ +struct nsContentListKey { + // We have to take an aIsHTMLDocument arg for two reasons: + // 1) We don't want to include Document.h in this header. + // 2) We need to do that to make nsContentList::RemoveFromHashtable + // work, because by the time it's called the document of the + // list's root node might have changed. + nsContentListKey(nsINode* aRootNode, int32_t aMatchNameSpaceId, + const nsAString& aTagname, bool aIsHTMLDocument) + : mRootNode(aRootNode), + mMatchNameSpaceId(aMatchNameSpaceId), + mTagname(aTagname), + mIsHTMLDocument(aIsHTMLDocument), + mHash(mozilla::AddToHash(mozilla::HashString(aTagname), mRootNode, + mMatchNameSpaceId, mIsHTMLDocument)) {} + + nsContentListKey(const nsContentListKey& aContentListKey) = default; + + inline uint32_t GetHash(void) const { return mHash; } + + nsINode* const mRootNode; // Weak ref + const int32_t mMatchNameSpaceId; + const nsAString& mTagname; + bool mIsHTMLDocument; + const uint32_t mHash; +}; + +/** + * Class that implements a possibly live NodeList that matches Elements + * in the tree based on some criterion. + */ +class nsContentList : public nsBaseContentList, + public nsIHTMLCollection, + public nsStubMutationObserver { + protected: + enum class State : uint8_t { + // The list is up to date and need not do any walking to be able to answer + // any questions anyone may have. + UpToDate = 0, + // The list contains no useful information and if anyone asks it anything it + // will have to populate itself before answering. + Dirty, + // The list has populated itself to a certain extent and that that part of + // the list is still valid. Requests for things outside that part of the + // list will require walking the tree some more. When a list is in this + // state, the last thing in mElements is the last node in the tree that the + // list looked at. + Lazy, + }; + + public: + NS_DECL_ISUPPORTS_INHERITED + + /** + * @param aRootNode The node under which to limit our search. + * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId. + * The special value "*" always matches whatever aMatchAtom + * is matched against. + * @param aMatchNameSpaceId If kNameSpaceID_Unknown, then aMatchAtom is the + * tagName to match. + * If kNameSpaceID_Wildcard, then aMatchAtom is the + * localName to match. + * Otherwise we match nodes whose namespace is + * aMatchNameSpaceId and localName matches + * aMatchAtom. + * @param aDeep If false, then look only at children of the root, nothing + * deeper. If true, then look at the whole subtree rooted at + * our root. + * @param aLiveList Whether the created list should be a live list observing + * mutations to the DOM tree. + */ + nsContentList(nsINode* aRootNode, int32_t aMatchNameSpaceId, + nsAtom* aHTMLMatchAtom, nsAtom* aXMLMatchAtom, + bool aDeep = true, bool aLiveList = true); + + /** + * @param aRootNode The node under which to limit our search. + * @param aFunc the function to be called to determine whether we match. + * This function MUST NOT ever cause mutation of the DOM. + * The nsContentList implementation guarantees that everything + * passed to the function will be IsElement(). + * @param aDestroyFunc the function that will be called to destroy aData + * @param aData closure data that will need to be passed back to aFunc + * @param aDeep If false, then look only at children of the root, nothing + * deeper. If true, then look at the whole subtree rooted at + * our root. + * @param aMatchAtom an atom to be passed back to aFunc + * @param aMatchNameSpaceId a namespace id to be passed back to aFunc + * @param aFuncMayDependOnAttr a boolean that indicates whether this list is + * sensitive to attribute changes. + * @param aLiveList Whether the created list should be a live list observing + * mutations to the DOM tree. + */ + nsContentList(nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, void* aData, + bool aDeep = true, nsAtom* aMatchAtom = nullptr, + int32_t aMatchNameSpaceId = kNameSpaceID_None, + bool aFuncMayDependOnAttr = true, bool aLiveList = true); + + // nsWrapperCache + using nsWrapperCache::GetWrapperPreserveColor; + using nsWrapperCache::PreserveWrapper; + JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + protected: + virtual ~nsContentList(); + + JSObject* GetWrapperPreserveColorInternal() override { + return nsWrapperCache::GetWrapperPreserveColor(); + } + void PreserveWrapperInternal(nsISupports* aScriptObjectHolder) override { + nsWrapperCache::PreserveWrapper(aScriptObjectHolder); + } + + public: + // nsBaseContentList overrides + int32_t IndexOf(nsIContent* aContent, bool aDoFlush) override; + int32_t IndexOf(nsIContent* aContent) override; + nsINode* GetParentObject() override { return mRootNode; } + + uint32_t Length() final { return Length(true); } + nsIContent* Item(uint32_t aIndex) final; + Element* GetElementAt(uint32_t index) override; + Element* GetFirstNamedElement(const nsAString& aName, bool& aFound) override { + Element* item = NamedItem(aName, true); + aFound = !!item; + return item; + } + void GetSupportedNames(nsTArray& aNames) override; + + // nsContentList public methods + uint32_t Length(bool aDoFlush); + nsIContent* Item(uint32_t aIndex, bool aDoFlush); + Element* NamedItem(const nsAString& aName, bool aDoFlush); + + // nsIMutationObserver + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + static nsContentList* FromSupports(nsISupports* aSupports) { + nsINodeList* list = static_cast(aSupports); +#ifdef DEBUG + { + nsCOMPtr list_qi = do_QueryInterface(aSupports); + + // If this assertion fires the QI implementation for the object in + // question doesn't use the nsINodeList pointer as the nsISupports + // pointer. That must be fixed, or we'll crash... + NS_ASSERTION(list_qi == list, "Uh, fix QI!"); + } +#endif + return static_cast(list); + } + + bool MatchesKey(const nsContentListKey& aKey) const { + // The root node is most commonly the same: the document. And the + // most common namespace id is kNameSpaceID_Unknown. So check the + // string first. Cases in which whether our root's ownerDocument + // is HTML changes are extremely rare, so check those last. + MOZ_ASSERT(mXMLMatchAtom, + "How did we get here with a null match atom on our list?"); + return mXMLMatchAtom->Equals(aKey.mTagname) && + mRootNode == aKey.mRootNode && + mMatchNameSpaceId == aKey.mMatchNameSpaceId && + mIsHTMLDocument == aKey.mIsHTMLDocument; + } + + /** + * Sets the state to LIST_DIRTY and clears mElements array. + * @note This is the only acceptable way to set state to LIST_DIRTY. + */ + void SetDirty() { + mState = State::Dirty; + InvalidateNamedItemsCache(); + Reset(); + SetEnabledCallbacks(nsIMutationObserver::kNodeWillBeDestroyed); + } + + void LastRelease() override; + + class HashEntry; + + protected: + // A cache from name to the first named item in mElements. Only possibly + // non-null when mState is State::UpToDate. Elements are kept alive by our + // mElements array. + using NamedItemsCache = nsTHashMap; + + void InvalidateNamedItemsCache() { + mNamedItemsCache = nullptr; + mNamedItemsCacheValid = false; + } + + inline void InsertElementInNamedItemsCache(nsIContent&); + inline void InvalidateNamedItemsCacheForAttributeChange(int32_t aNameSpaceID, + nsAtom* aAttribute); + inline void InvalidateNamedItemsCacheForInsertion(Element&); + inline void InvalidateNamedItemsCacheForDeletion(Element&); + + void EnsureNamedItemsCacheValid(bool aDoFlush); + + /** + * Returns whether the element matches our criterion + * + * @param aElement the element to attempt to match + * @return whether we match + */ + bool Match(Element* aElement); + /** + * See if anything in the subtree rooted at aContent, including + * aContent itself, matches our criterion. + * + * @param aContent the root of the subtree to match against + * @return whether we match something in the tree rooted at aContent + */ + bool MatchSelf(nsIContent* aContent); + + /** + * Populate our list. Stop once we have at least aNeededLength + * elements. At the end of PopulateSelf running, either the last + * node we examined is the last node in our array or we have + * traversed the whole document (or both). + * + * @param aNeededLength the length the list should have when we are + * done (unless it exhausts the document) + * @param aExpectedElementsIfDirty is for debugging only to + * assert that mElements has expected number of entries. + */ + virtual void PopulateSelf(uint32_t aNeededLength, + uint32_t aExpectedElementsIfDirty = 0); + + /** + * @param aContainer a content node which must be a descendant of + * mRootNode + * @return true if children or descendants of aContainer could match our + * criterion. + * false otherwise. + */ + bool MayContainRelevantNodes(nsINode* aContainer) { + return mDeep || aContainer == mRootNode; + } + + /** + * Remove ourselves from the hashtable that caches commonly accessed + * content lists. Generally done on destruction. + */ + void RemoveFromHashtable(); + /** + * If state is not LIST_UP_TO_DATE, fully populate ourselves with + * all the nodes we can find. + */ + inline void BringSelfUpToDate(bool aDoFlush); + + /** + * To be called from non-destructor locations that want to remove from caches. + * Needed because if subclasses want to have cache behavior they can't just + * override RemoveFromHashtable(), since we call that in our destructor. + */ + void RemoveFromCaches() override { RemoveFromHashtable(); } + + void MaybeMarkDirty() { + if (mState != State::Dirty && ++mMissedUpdates > 128) { + mMissedUpdates = 0; + SetDirty(); + } + } + + nsINode* mRootNode; // Weak ref + int32_t mMatchNameSpaceId; + RefPtr mHTMLMatchAtom; + RefPtr mXMLMatchAtom; + + /** + * Function to use to determine whether a piece of content matches + * our criterion + */ + nsContentListMatchFunc mFunc = nullptr; + /** + * Cleanup closure data with this. + */ + nsContentListDestroyFunc mDestroyFunc = nullptr; + /** + * Closure data to pass to mFunc when we call it + */ + void* mData = nullptr; + + mozilla::UniquePtr mNamedItemsCache; + + uint8_t mMissedUpdates = 0; + + // The current state of the list. + State mState; + + /** + * True if we are looking for elements named "*" + */ + bool mMatchAll : 1; + /** + * Whether to actually descend the tree. If this is false, we won't + * consider grandkids of mRootNode. + */ + bool mDeep : 1; + /** + * Whether the return value of mFunc could depend on the values of + * attributes. + */ + bool mFuncMayDependOnAttr : 1; + /** + * Whether we actually need to flush to get our state correct. + */ + bool mFlushesNeeded : 1; + /** + * Whether the ownerDocument of our root node at list creation time was an + * HTML document. Only needed when we're doing a namespace/atom match, not + * when doing function matching, always false otherwise. + */ + bool mIsHTMLDocument : 1; + /** + * True mNamedItemsCache is valid. Note mNamedItemsCache might still be null + * if there's no named items at all. + */ + bool mNamedItemsCacheValid : 1; + /** + * Whether the list observes mutations to the DOM tree. + */ + const bool mIsLiveList : 1; + /* + * True if this content list is cached in a hash table. + * For nsContentList (but not its subclasses), the hash table is + * gContentListHashTable. + * For nsCacheableFuncStringContentList, the hash table is + * gFuncStringContentListHashTable. + * Other subclasses of nsContentList can't be in hash tables. + */ + bool mInHashtable : 1; + +#ifdef DEBUG_CONTENT_LIST + void AssertInSync(); +#endif +}; + +/** + * A class of cacheable content list; cached on the combination of aRootNode + + * aFunc + aDataString + */ +class nsCacheableFuncStringContentList; + +class MOZ_STACK_CLASS nsFuncStringCacheKey { + public: + nsFuncStringCacheKey(nsINode* aRootNode, nsContentListMatchFunc aFunc, + const nsAString& aString) + : mRootNode(aRootNode), mFunc(aFunc), mString(aString) {} + + uint32_t GetHash(void) const { + uint32_t hash = mozilla::HashString(mString); + return mozilla::AddToHash(hash, mRootNode, mFunc); + } + + private: + friend class nsCacheableFuncStringContentList; + + nsINode* const mRootNode; + const nsContentListMatchFunc mFunc; + const nsAString& mString; +}; + +// aDestroyFunc is allowed to be null +// aDataAllocator must always return a non-null pointer +class nsCacheableFuncStringContentList : public nsContentList { + public: + virtual ~nsCacheableFuncStringContentList(); + + bool Equals(const nsFuncStringCacheKey* aKey) { + return mRootNode == aKey->mRootNode && mFunc == aKey->mFunc && + mString == aKey->mString; + } + + enum ContentListType { eNodeList, eHTMLCollection }; +#ifdef DEBUG + ContentListType mType; +#endif + + class HashEntry; + + protected: + nsCacheableFuncStringContentList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString, mozilla::DebugOnly aType) + : nsContentList(aRootNode, aFunc, aDestroyFunc, nullptr), +#ifdef DEBUG + mType(aType), +#endif + mString(aString) { + mData = (*aDataAllocator)(aRootNode, &mString); + MOZ_ASSERT(mData); + } + + void RemoveFromCaches() override { RemoveFromFuncStringHashtable(); } + void RemoveFromFuncStringHashtable(); + + nsString mString; +}; + +class nsCachableElementsByNameNodeList + : public nsCacheableFuncStringContentList { + public: + nsCachableElementsByNameNodeList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString) + : nsCacheableFuncStringContentList(aRootNode, aFunc, aDestroyFunc, + aDataAllocator, aString, eNodeList) {} + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + +#ifdef DEBUG + static const ContentListType sType; +#endif +}; + +class nsCacheableFuncStringHTMLCollection + : public nsCacheableFuncStringContentList { + public: + nsCacheableFuncStringHTMLCollection( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString) + : nsCacheableFuncStringContentList(aRootNode, aFunc, aDestroyFunc, + aDataAllocator, aString, + eHTMLCollection) {} + + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + +#ifdef DEBUG + static const ContentListType sType; +#endif +}; + +class nsLabelsNodeList final : public nsContentList { + public: + nsLabelsNodeList(nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, void* aData) + : nsContentList(aRootNode, aFunc, aDestroyFunc, aData) {} + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + + JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + + /** + * Reset root, mutation observer, and clear content list + * if the root has been changed. + * + * @param aRootNode The node under which to limit our search. + */ + void MaybeResetRoot(nsINode* aRootNode); + + private: + /** + * Start searching at the last one if we already have nodes, otherwise + * start searching at the root. + * + * @param aNeededLength The list of length should have when we are + * done (unless it exhausts the document). + * @param aExpectedElementsIfDirty is for debugging only to + * assert that mElements has expected number of entries. + */ + void PopulateSelf(uint32_t aNeededLength, + uint32_t aExpectedElementsIfDirty = 0) override; +}; +#endif // nsContentList_h___ diff --git a/dom/base/nsContentListDeclarations.h b/dom/base/nsContentListDeclarations.h new file mode 100644 index 0000000000..8c737bfa38 --- /dev/null +++ b/dom/base/nsContentListDeclarations.h @@ -0,0 +1,61 @@ +/* -*- 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 nsContentListDeclarations_h +#define nsContentListDeclarations_h + +#include +#include "nsCOMPtr.h" +#include "nsStringFwd.h" + +class nsContentList; +class nsAtom; +class nsIContent; +class nsINode; + +namespace mozilla::dom { +class Element; +} // namespace mozilla::dom + +// Magic namespace id that means "match all namespaces". This is +// negative so it won't collide with actual namespace constants. +#define kNameSpaceID_Wildcard INT32_MIN + +// This is a callback function type that can be used to implement an +// arbitrary matching algorithm. aContent is the content that may +// match the list, while aNamespaceID, aAtom, and aData are whatever +// was passed to the list's constructor. +using nsContentListMatchFunc = bool (*)(mozilla::dom::Element* aElement, + int32_t aNamespaceID, nsAtom* aAtom, + void* aData); + +using nsContentListDestroyFunc = void (*)(void* aData); + +/** + * A function that allocates the matching data for this + * FuncStringContentList. Returning aString is perfectly fine; in + * that case the destructor function should be a no-op. + */ +using nsFuncStringContentListDataAllocator = void* (*)(nsINode* aRootNode, + const nsString* aString); + +// If aMatchNameSpaceId is kNameSpaceID_Unknown, this will return a +// content list which matches ASCIIToLower(aTagname) against HTML +// elements in HTML documents and aTagname against everything else. +// For any other value of aMatchNameSpaceId, the list will match +// aTagname against all elements. +already_AddRefed NS_GetContentList(nsINode* aRootNode, + int32_t aMatchNameSpaceId, + const nsAString& aTagname); + +template +already_AddRefed GetFuncStringContentList( + nsINode* aRootNode, nsContentListMatchFunc aFunc, + nsContentListDestroyFunc aDestroyFunc, + nsFuncStringContentListDataAllocator aDataAllocator, + const nsAString& aString); + +#endif // nsContentListDeclarations_h diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp new file mode 100644 index 0000000000..0e1668ec5e --- /dev/null +++ b/dom/base/nsContentPermissionHelper.cpp @@ -0,0 +1,874 @@ +/* -*- 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 "nsCOMPtr.h" +#include "nsIPrincipal.h" +#include "mozilla/dom/BrowserChild.h" +#include "mozilla/dom/BrowserParent.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/PContentPermission.h" +#include "mozilla/dom/PermissionMessageUtils.h" +#include "mozilla/dom/PContentPermissionRequestParent.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/Unused.h" +#include "nsComponentManagerUtils.h" +#include "nsArrayUtils.h" +#include "nsIMutableArray.h" +#include "nsContentPermissionHelper.h" +#include "nsGlobalWindowInner.h" +#include "nsJSUtils.h" +#include "nsISupportsPrimitives.h" +#include "nsServiceManagerUtils.h" +#include "mozilla/dom/Document.h" +#include "nsIWeakReferenceUtils.h" +#include "js/PropertyAndElement.h" // JS_GetProperty, JS_SetProperty + +using mozilla::Unused; // +using namespace mozilla::dom; +using namespace mozilla; +using DelegateInfo = PermissionDelegateHandler::PermissionDelegateInfo; + +namespace mozilla::dom { + +class ContentPermissionRequestParent : public PContentPermissionRequestParent { + public: + // @param aIsRequestDelegatedToUnsafeThirdParty see + // mIsRequestDelegatedToUnsafeThirdParty. + ContentPermissionRequestParent( + const nsTArray& aRequests, Element* aElement, + nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal, + const bool aHasValidTransientUserGestureActivation, + const bool aIsRequestDelegatedToUnsafeThirdParty); + virtual ~ContentPermissionRequestParent(); + + bool IsBeingDestroyed(); + + nsCOMPtr mPrincipal; + nsCOMPtr mTopLevelPrincipal; + nsCOMPtr mElement; + bool mHasValidTransientUserGestureActivation; + + // See nsIPermissionDelegateHandler.maybeUnsafePermissionDelegate. + bool mIsRequestDelegatedToUnsafeThirdParty; + + RefPtr mProxy; + nsTArray mRequests; + + private: + // Not MOZ_CAN_RUN_SCRIPT because we can't annotate the thing we override yet. + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual mozilla::ipc::IPCResult Recvprompt() override; + virtual mozilla::ipc::IPCResult RecvDestroy() override; + virtual void ActorDestroy(ActorDestroyReason why) override; +}; + +ContentPermissionRequestParent::ContentPermissionRequestParent( + const nsTArray& aRequests, Element* aElement, + nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal, + const bool aHasValidTransientUserGestureActivation, + const bool aIsRequestDelegatedToUnsafeThirdParty) { + MOZ_COUNT_CTOR(ContentPermissionRequestParent); + + mPrincipal = aPrincipal; + mTopLevelPrincipal = aTopLevelPrincipal; + mElement = aElement; + mRequests = aRequests.Clone(); + mHasValidTransientUserGestureActivation = + aHasValidTransientUserGestureActivation; + mIsRequestDelegatedToUnsafeThirdParty = aIsRequestDelegatedToUnsafeThirdParty; +} + +ContentPermissionRequestParent::~ContentPermissionRequestParent() { + MOZ_COUNT_DTOR(ContentPermissionRequestParent); +} + +mozilla::ipc::IPCResult ContentPermissionRequestParent::Recvprompt() { + mProxy = new nsContentPermissionRequestProxy(this); + if (NS_FAILED(mProxy->Init(mRequests))) { + RefPtr proxy(mProxy); + proxy->Cancel(); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult ContentPermissionRequestParent::RecvDestroy() { + Unused << PContentPermissionRequestParent::Send__delete__(this); + return IPC_OK(); +} + +void ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why) { + if (mProxy) { + mProxy->OnParentDestroyed(); + } +} + +bool ContentPermissionRequestParent::IsBeingDestroyed() { + // When ContentParent::MarkAsDead() is called, we are being destroyed. + // It's unsafe to send out any message now. + ContentParent* contentParent = static_cast(Manager()); + return !contentParent->IsAlive(); +} + +NS_IMPL_ISUPPORTS(ContentPermissionType, nsIContentPermissionType) + +ContentPermissionType::ContentPermissionType( + const nsACString& aType, const nsTArray& aOptions) { + mType = aType; + mOptions = aOptions.Clone(); +} + +ContentPermissionType::~ContentPermissionType() = default; + +NS_IMETHODIMP +ContentPermissionType::GetType(nsACString& aType) { + aType = mType; + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionType::GetOptions(nsIArray** aOptions) { + NS_ENSURE_ARG_POINTER(aOptions); + + *aOptions = nullptr; + + nsresult rv; + nsCOMPtr options = + do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // copy options into JS array + for (uint32_t i = 0; i < mOptions.Length(); ++i) { + nsCOMPtr isupportsString = + do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = isupportsString->SetData(mOptions[i]); + NS_ENSURE_SUCCESS(rv, rv); + + rv = options->AppendElement(isupportsString); + NS_ENSURE_SUCCESS(rv, rv); + } + + options.forget(aOptions); + return NS_OK; +} + +// nsContentPermissionUtils + +/* static */ +uint32_t nsContentPermissionUtils::ConvertPermissionRequestToArray( + nsTArray& aSrcArray, nsIMutableArray* aDesArray) { + uint32_t len = aSrcArray.Length(); + for (uint32_t i = 0; i < len; i++) { + RefPtr cpt = + new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].options()); + aDesArray->AppendElement(cpt); + } + return len; +} + +/* static */ +void nsContentPermissionUtils::ConvertArrayToPermissionRequest( + nsIArray* aSrcArray, nsTArray& aDesArray) { + uint32_t len = 0; + aSrcArray->GetLength(&len); + for (uint32_t i = 0; i < len; i++) { + nsCOMPtr cpt = do_QueryElementAt(aSrcArray, i); + nsAutoCString type; + cpt->GetType(type); + + nsCOMPtr optionArray; + cpt->GetOptions(getter_AddRefs(optionArray)); + uint32_t optionsLength = 0; + if (optionArray) { + optionArray->GetLength(&optionsLength); + } + nsTArray options; + for (uint32_t j = 0; j < optionsLength; ++j) { + nsCOMPtr isupportsString = + do_QueryElementAt(optionArray, j); + if (isupportsString) { + nsString option; + isupportsString->GetData(option); + options.AppendElement(option); + } + } + + aDesArray.AppendElement(PermissionRequest(type, options)); + } +} + +static std::map& +ContentPermissionRequestParentMap() { + MOZ_ASSERT(NS_IsMainThread()); + static std::map + sPermissionRequestParentMap; + return sPermissionRequestParentMap; +} + +static std::map& +ContentPermissionRequestChildMap() { + MOZ_ASSERT(NS_IsMainThread()); + static std::map + sPermissionRequestChildMap; + return sPermissionRequestChildMap; +} + +/* static */ +nsresult nsContentPermissionUtils::CreatePermissionArray( + const nsACString& aType, const nsTArray& aOptions, + nsIArray** aTypesArray) { + nsCOMPtr types = do_CreateInstance(NS_ARRAY_CONTRACTID); + RefPtr permType = + new ContentPermissionType(aType, aOptions); + types->AppendElement(permType); + types.forget(aTypesArray); + + return NS_OK; +} + +/* static */ +PContentPermissionRequestParent* +nsContentPermissionUtils::CreateContentPermissionRequestParent( + const nsTArray& aRequests, Element* aElement, + nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal, + const bool aHasValidTransientUserGestureActivation, + const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId) { + PContentPermissionRequestParent* parent = new ContentPermissionRequestParent( + aRequests, aElement, aPrincipal, aTopLevelPrincipal, + aHasValidTransientUserGestureActivation, + aIsRequestDelegatedToUnsafeThirdParty); + ContentPermissionRequestParentMap()[parent] = aTabId; + + return parent; +} + +/* static */ +nsresult nsContentPermissionUtils::AskPermission( + nsIContentPermissionRequest* aRequest, nsPIDOMWindowInner* aWindow) { + NS_ENSURE_STATE(aWindow && aWindow->IsCurrentInnerWindow()); + + // for content process + if (XRE_IsContentProcess()) { + RefPtr req = + new RemotePermissionRequest(aRequest, aWindow); + + MOZ_ASSERT(NS_IsMainThread()); // IPC can only be execute on main thread. + + BrowserChild* child = BrowserChild::GetFrom(aWindow->GetDocShell()); + NS_ENSURE_TRUE(child, NS_ERROR_FAILURE); + + nsCOMPtr typeArray; + nsresult rv = aRequest->GetTypes(getter_AddRefs(typeArray)); + NS_ENSURE_SUCCESS(rv, rv); + + nsTArray permArray; + ConvertArrayToPermissionRequest(typeArray, permArray); + + nsCOMPtr principal; + rv = aRequest->GetPrincipal(getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr topLevelPrincipal; + rv = aRequest->GetTopLevelPrincipal(getter_AddRefs(topLevelPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasValidTransientUserGestureActivation; + rv = aRequest->GetHasValidTransientUserGestureActivation( + &hasValidTransientUserGestureActivation); + NS_ENSURE_SUCCESS(rv, rv); + + bool isRequestDelegatedToUnsafeThirdParty; + rv = aRequest->GetIsRequestDelegatedToUnsafeThirdParty( + &isRequestDelegatedToUnsafeThirdParty); + NS_ENSURE_SUCCESS(rv, rv); + + req->IPDLAddRef(); + if (!ContentChild::GetSingleton()->SendPContentPermissionRequestConstructor( + req, permArray, principal, topLevelPrincipal, + hasValidTransientUserGestureActivation, + isRequestDelegatedToUnsafeThirdParty, child->GetTabId())) { + return NS_ERROR_FAILURE; + } + ContentPermissionRequestChildMap()[req.get()] = child->GetTabId(); + + req->Sendprompt(); + return NS_OK; + } + + // for chrome process + nsCOMPtr prompt = + do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID); + if (prompt) { + if (NS_FAILED(prompt->Prompt(aRequest))) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +/* static */ +nsTArray +nsContentPermissionUtils::GetContentPermissionRequestParentById( + const TabId& aTabId) { + nsTArray parentArray; + for (auto& it : ContentPermissionRequestParentMap()) { + if (it.second == aTabId) { + parentArray.AppendElement(it.first); + } + } + + return parentArray; +} + +/* static */ +void nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent( + PContentPermissionRequestParent* aParent) { + auto it = ContentPermissionRequestParentMap().find(aParent); + MOZ_ASSERT(it != ContentPermissionRequestParentMap().end()); + + ContentPermissionRequestParentMap().erase(it); +} + +/* static */ +nsTArray +nsContentPermissionUtils::GetContentPermissionRequestChildById( + const TabId& aTabId) { + nsTArray childArray; + for (auto& it : ContentPermissionRequestChildMap()) { + if (it.second == aTabId) { + childArray.AppendElement(it.first); + } + } + + return childArray; +} + +/* static */ +void nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild( + PContentPermissionRequestChild* aChild) { + auto it = ContentPermissionRequestChildMap().find(aChild); + MOZ_ASSERT(it != ContentPermissionRequestChildMap().end()); + + ContentPermissionRequestChildMap().erase(it); +} + +static nsIPrincipal* GetTopLevelPrincipal(nsPIDOMWindowInner* aWindow) { + MOZ_ASSERT(aWindow); + + BrowsingContext* top = aWindow->GetBrowsingContext()->Top(); + MOZ_ASSERT(top); + + nsPIDOMWindowOuter* outer = top->GetDOMWindow(); + if (!outer) { + return nullptr; + } + + nsPIDOMWindowInner* inner = outer->GetCurrentInnerWindow(); + if (!inner) { + return nullptr; + } + + return nsGlobalWindowInner::Cast(inner)->GetPrincipal(); +} + +NS_IMPL_CYCLE_COLLECTION(ContentPermissionRequestBase, mPrincipal, + mTopLevelPrincipal, mWindow) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentPermissionRequestBase) + NS_INTERFACE_MAP_ENTRY_CONCRETE(nsISupports) + NS_INTERFACE_MAP_ENTRY_CONCRETE(nsIContentPermissionRequest) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentPermissionRequestBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentPermissionRequestBase) + +ContentPermissionRequestBase::ContentPermissionRequestBase( + nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow, + const nsACString& aPrefName, const nsACString& aType) + : mPrincipal(aPrincipal), + mTopLevelPrincipal(aWindow ? ::GetTopLevelPrincipal(aWindow) : nullptr), + mWindow(aWindow), + mPrefName(aPrefName), + mType(aType), + mHasValidTransientUserGestureActivation(false), + mIsRequestDelegatedToUnsafeThirdParty(false) { + if (!aWindow) { + return; + } + + Document* doc = aWindow->GetExtantDoc(); + if (!doc) { + return; + } + + mHasValidTransientUserGestureActivation = + doc->HasValidTransientUserGestureActivation(); + + mPermissionHandler = doc->GetPermissionDelegateHandler(); + if (mPermissionHandler) { + nsTArray types; + types.AppendElement(mType); + mPermissionHandler->MaybeUnsafePermissionDelegate( + types, &mIsRequestDelegatedToUnsafeThirdParty); + } +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetPrincipal( + nsIPrincipal** aRequestingPrincipal) { + NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetDelegatePrincipal( + const nsACString& aType, nsIPrincipal** aRequestingPrincipal) { + return PermissionDelegateHandler::GetDelegatePrincipal(aType, this, + aRequestingPrincipal); +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetIsRequestDelegatedToUnsafeThirdParty( + bool* aIsRequestDelegatedToUnsafeThirdParty) { + *aIsRequestDelegatedToUnsafeThirdParty = + mIsRequestDelegatedToUnsafeThirdParty; + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetTopLevelPrincipal( + nsIPrincipal** aRequestingPrincipal) { + if (!mTopLevelPrincipal) { + *aRequestingPrincipal = nullptr; + return NS_OK; + } + + NS_IF_ADDREF(*aRequestingPrincipal = mTopLevelPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetWindow(mozIDOMWindow** aRequestingWindow) { + NS_IF_ADDREF(*aRequestingWindow = mWindow); + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetElement(Element** aElement) { + NS_ENSURE_ARG_POINTER(aElement); + *aElement = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetHasValidTransientUserGestureActivation( + bool* aHasValidTransientUserGestureActivation) { + *aHasValidTransientUserGestureActivation = + mHasValidTransientUserGestureActivation; + return NS_OK; +} + +NS_IMETHODIMP +ContentPermissionRequestBase::GetTypes(nsIArray** aTypes) { + nsTArray emptyOptions; + return nsContentPermissionUtils::CreatePermissionArray(mType, emptyOptions, + aTypes); +} + +ContentPermissionRequestBase::PromptResult +ContentPermissionRequestBase::CheckPromptPrefs() const { + MOZ_ASSERT(!mPrefName.IsEmpty(), + "This derived class must support checking pref types"); + + nsAutoCString prefName(mPrefName); + prefName.AppendLiteral(".prompt.testing"); + if (Preferences::GetBool(PromiseFlatCString(prefName).get(), false)) { + prefName.AppendLiteral(".allow"); + if (Preferences::GetBool(PromiseFlatCString(prefName).get(), true)) { + return PromptResult::Granted; + } + return PromptResult::Denied; + } + + return PromptResult::Pending; +} + +bool ContentPermissionRequestBase::CheckPermissionDelegate() const { + // There is case that ContentPermissionRequestBase is constructed without + // window, then mPermissionHandler will be null. So we only check permission + // delegate if we have non-null mPermissionHandler + if (mPermissionHandler && + !mPermissionHandler->HasPermissionDelegated(mType)) { + return false; + } + + return true; +} + +nsresult ContentPermissionRequestBase::ShowPrompt( + ContentPermissionRequestBase::PromptResult& aResult) { + if (!CheckPermissionDelegate()) { + aResult = PromptResult::Denied; + return NS_OK; + } + + aResult = CheckPromptPrefs(); + + if (aResult != PromptResult::Pending) { + return NS_OK; + } + + return nsContentPermissionUtils::AskPermission(this, mWindow); +} + +class RequestPromptEvent : public Runnable { + public: + RequestPromptEvent(ContentPermissionRequestBase* aRequest, + nsPIDOMWindowInner* aWindow) + : mozilla::Runnable("RequestPromptEvent"), + mRequest(aRequest), + mWindow(aWindow) {} + + NS_IMETHOD Run() override { + nsContentPermissionUtils::AskPermission(mRequest, mWindow); + return NS_OK; + } + + private: + RefPtr mRequest; + nsCOMPtr mWindow; +}; + +class RequestAllowEvent : public Runnable { + public: + RequestAllowEvent(bool allow, ContentPermissionRequestBase* request) + : mozilla::Runnable("RequestAllowEvent"), + mAllow(allow), + mRequest(request) {} + + // Not MOZ_CAN_RUN_SCRIPT because we can't annotate the thing we override yet. + MOZ_CAN_RUN_SCRIPT_BOUNDARY + NS_IMETHOD Run() override { + // MOZ_KnownLive is OK, because we never drop the ref to mRequest. + if (mAllow) { + MOZ_KnownLive(mRequest)->Allow(JS::UndefinedHandleValue); + } else { + MOZ_KnownLive(mRequest)->Cancel(); + } + return NS_OK; + } + + private: + bool mAllow; + RefPtr mRequest; +}; + +void ContentPermissionRequestBase::RequestDelayedTask( + nsIEventTarget* aTarget, + ContentPermissionRequestBase::DelayedTaskType aType) { + nsCOMPtr r; + switch (aType) { + case DelayedTaskType::Allow: + r = new RequestAllowEvent(true, this); + break; + case DelayedTaskType::Deny: + r = new RequestAllowEvent(false, this); + break; + default: + r = new RequestPromptEvent(this, mWindow); + break; + } + + aTarget->Dispatch(r.forget()); +} + +nsresult TranslateChoices( + JS::Handle aChoices, + const nsTArray& aPermissionRequests, + nsTArray& aTranslatedChoices) { + if (aChoices.isNullOrUndefined()) { + // No choice is specified. + } else if (aChoices.isObject()) { + // Iterate through all permission types. + for (uint32_t i = 0; i < aPermissionRequests.Length(); ++i) { + nsCString type = aPermissionRequests[i].type(); + + JS::Rooted obj(RootingCx(), &aChoices.toObject()); + // People really shouldn't be passing WindowProxy or Location + // objects for the choices here. + obj = js::CheckedUnwrapStatic(obj); + if (!obj) { + return NS_ERROR_FAILURE; + } + + AutoJSAPI jsapi; + jsapi.Init(); + + JSContext* cx = jsapi.cx(); + JSAutoRealm ar(cx, obj); + + JS::Rooted val(cx); + + if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) || + !val.isString()) { + // no setting for the permission type, clear exception and skip it + jsapi.ClearException(); + } else { + nsAutoJSString choice; + if (!choice.init(cx, val)) { + jsapi.ClearException(); + return NS_ERROR_FAILURE; + } + aTranslatedChoices.AppendElement(PermissionChoice(type, choice)); + } + } + } else { + MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object"); + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +} // namespace mozilla::dom + +nsContentPermissionRequestProxy::nsContentPermissionRequestProxy( + ContentPermissionRequestParent* parent) + : mParent(parent) { + NS_ASSERTION(mParent, "null parent"); +} + +nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy() = default; + +nsresult nsContentPermissionRequestProxy::Init( + const nsTArray& requests) { + mPermissionRequests = requests.Clone(); + + nsCOMPtr prompt = + do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID); + if (!prompt) { + return NS_ERROR_FAILURE; + } + + prompt->Prompt(this); + return NS_OK; +} + +void nsContentPermissionRequestProxy::OnParentDestroyed() { mParent = nullptr; } + +NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy, nsIContentPermissionRequest) + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes) { + nsCOMPtr types = do_CreateInstance(NS_ARRAY_CONTRACTID); + if (mozilla::dom::nsContentPermissionUtils::ConvertPermissionRequestToArray( + mPermissionRequests, types)) { + types.forget(aTypes); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetWindow(mozIDOMWindow** aRequestingWindow) { + NS_ENSURE_ARG_POINTER(aRequestingWindow); + *aRequestingWindow = nullptr; // ipc doesn't have a window + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetPrincipal( + nsIPrincipal** aRequestingPrincipal) { + NS_ENSURE_ARG_POINTER(aRequestingPrincipal); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + NS_IF_ADDREF(*aRequestingPrincipal = mParent->mPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetTopLevelPrincipal( + nsIPrincipal** aRequestingPrincipal) { + NS_ENSURE_ARG_POINTER(aRequestingPrincipal); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + NS_IF_ADDREF(*aRequestingPrincipal = mParent->mTopLevelPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetDelegatePrincipal( + const nsACString& aType, nsIPrincipal** aRequestingPrincipal) { + NS_ENSURE_ARG_POINTER(aRequestingPrincipal); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + return PermissionDelegateHandler::GetDelegatePrincipal(aType, this, + aRequestingPrincipal); +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetElement(Element** aRequestingElement) { + NS_ENSURE_ARG_POINTER(aRequestingElement); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr elem = mParent->mElement; + elem.forget(aRequestingElement); + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetHasValidTransientUserGestureActivation( + bool* aHasValidTransientUserGestureActivation) { + NS_ENSURE_ARG_POINTER(aHasValidTransientUserGestureActivation); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + *aHasValidTransientUserGestureActivation = + mParent->mHasValidTransientUserGestureActivation; + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::GetIsRequestDelegatedToUnsafeThirdParty( + bool* aIsRequestDelegatedToUnsafeThirdParty) { + NS_ENSURE_ARG_POINTER(aIsRequestDelegatedToUnsafeThirdParty); + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + *aIsRequestDelegatedToUnsafeThirdParty = + mParent->mIsRequestDelegatedToUnsafeThirdParty; + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::Cancel() { + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + // Don't send out the delete message when the managing protocol (PBrowser) is + // being destroyed and PContentPermissionRequest will soon be. + if (mParent->IsBeingDestroyed()) { + return NS_ERROR_FAILURE; + } + + nsTArray emptyChoices; + + Unused << mParent->SendNotifyResult(false, emptyChoices); + return NS_OK; +} + +NS_IMETHODIMP +nsContentPermissionRequestProxy::Allow(JS::Handle aChoices) { + if (mParent == nullptr) { + return NS_ERROR_FAILURE; + } + + // Don't send out the delete message when the managing protocol (PBrowser) is + // being destroyed and PContentPermissionRequest will soon be. + if (mParent->IsBeingDestroyed()) { + return NS_ERROR_FAILURE; + } + + nsTArray choices; + nsresult rv = TranslateChoices(aChoices, mPermissionRequests, choices); + if (NS_FAILED(rv)) { + return rv; + } + + Unused << mParent->SendNotifyResult(true, choices); + return NS_OK; +} + +// RemotePermissionRequest + +RemotePermissionRequest::RemotePermissionRequest( + nsIContentPermissionRequest* aRequest, nsPIDOMWindowInner* aWindow) + : mRequest(aRequest), + mWindow(aWindow), + mIPCOpen(false), + mDestroyed(false) {} + +RemotePermissionRequest::~RemotePermissionRequest() { + MOZ_ASSERT( + !mIPCOpen, + "Protocol must not be open when RemotePermissionRequest is destroyed."); +} + +void RemotePermissionRequest::DoCancel() { + NS_ASSERTION(mRequest, "We need a request"); + nsCOMPtr request(mRequest); + request->Cancel(); +} + +void RemotePermissionRequest::DoAllow(JS::Handle aChoices) { + NS_ASSERTION(mRequest, "We need a request"); + nsCOMPtr request(mRequest); + request->Allow(aChoices); +} + +// PContentPermissionRequestChild +mozilla::ipc::IPCResult RemotePermissionRequest::RecvNotifyResult( + const bool& aAllow, nsTArray&& aChoices) { + Destroy(); + + if (aAllow && mWindow->IsCurrentInnerWindow()) { + // Use 'undefined' if no choice is provided. + if (aChoices.IsEmpty()) { + DoAllow(JS::UndefinedHandleValue); + return IPC_OK(); + } + + // Convert choices to a JS val if any. + // {"type1": "choice1", "type2": "choiceA"} + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mWindow))) { + return IPC_OK(); // This is not an IPC error. + } + + JSContext* cx = jsapi.cx(); + JS::Rooted obj(cx); + obj = JS_NewPlainObject(cx); + for (uint32_t i = 0; i < aChoices.Length(); ++i) { + const nsString& choice = aChoices[i].choice(); + const nsCString& type = aChoices[i].type(); + JS::Rooted jChoice( + cx, JS_NewUCStringCopyN(cx, choice.get(), choice.Length())); + JS::Rooted vChoice(cx, StringValue(jChoice)); + if (!JS_SetProperty(cx, obj, type.get(), vChoice)) { + return IPC_FAIL_NO_REASON(this); + } + } + JS::Rooted val(cx, JS::ObjectValue(*obj)); + DoAllow(val); + } else { + DoCancel(); + } + return IPC_OK(); +} + +void RemotePermissionRequest::Destroy() { + if (!IPCOpen()) { + return; + } + Unused << this->SendDestroy(); + mDestroyed = true; +} diff --git a/dom/base/nsContentPermissionHelper.h b/dom/base/nsContentPermissionHelper.h new file mode 100644 index 0000000000..18ce5c8f0f --- /dev/null +++ b/dom/base/nsContentPermissionHelper.h @@ -0,0 +1,232 @@ +/* -*- 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 nsContentPermissionHelper_h +#define nsContentPermissionHelper_h + +#include "nsIContentPermissionPrompt.h" +#include "nsTArray.h" +#include "nsIMutableArray.h" +#include "mozilla/dom/PContentPermissionRequestChild.h" +#include "mozilla/dom/ipc/IdType.h" +#include "mozilla/PermissionDelegateHandler.h" + +// Microsoft's API Name hackery sucks +// XXXbz Doing this in a header is a gigantic footgun. See +// https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why. +#undef LoadImage + +class nsPIDOMWindowInner; +class nsContentPermissionRequestProxy; + +namespace mozilla::dom { + +class Element; +class PermissionRequest; +class ContentPermissionRequestParent; +class PContentPermissionRequestParent; + +class ContentPermissionType : public nsIContentPermissionType { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSICONTENTPERMISSIONTYPE + + ContentPermissionType(const nsACString& aType, + const nsTArray& aOptions); + + protected: + virtual ~ContentPermissionType(); + + nsCString mType; + nsTArray mOptions; +}; + +class nsContentPermissionUtils { + public: + static uint32_t ConvertPermissionRequestToArray( + nsTArray& aSrcArray, nsIMutableArray* aDesArray); + + // Converts blindly, that is, strings are not matched against any list. + // + // @param aSrcArray needs to contain elements of type + // `nsIContentPermissionType`. + static void ConvertArrayToPermissionRequest( + nsIArray* aSrcArray, nsTArray& aDesArray); + + static nsresult CreatePermissionArray(const nsACString& aType, + const nsTArray& aOptions, + nsIArray** aTypesArray); + + // @param aIsRequestDelegatedToUnsafeThirdParty see + // ContentPermissionRequestParent. + static PContentPermissionRequestParent* CreateContentPermissionRequestParent( + const nsTArray& aRequests, Element* aElement, + nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal, + const bool aHasValidTransientUserGestureActivation, + const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId); + + static nsresult AskPermission(nsIContentPermissionRequest* aRequest, + nsPIDOMWindowInner* aWindow); + + static nsTArray + GetContentPermissionRequestParentById(const TabId& aTabId); + + static void NotifyRemoveContentPermissionRequestParent( + PContentPermissionRequestParent* aParent); + + static nsTArray + GetContentPermissionRequestChildById(const TabId& aTabId); + + static void NotifyRemoveContentPermissionRequestChild( + PContentPermissionRequestChild* aChild); +}; + +nsresult TranslateChoices( + JS::Handle aChoices, + const nsTArray& aPermissionRequests, + nsTArray& aTranslatedChoices); + +class ContentPermissionRequestBase : public nsIContentPermissionRequest { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(ContentPermissionRequestBase) + + NS_IMETHOD GetTypes(nsIArray** aTypes) override; + NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal) override; + NS_IMETHOD GetDelegatePrincipal(const nsACString& aType, + nsIPrincipal** aPrincipal) override; + NS_IMETHOD GetTopLevelPrincipal(nsIPrincipal** aTopLevelPrincipal) override; + NS_IMETHOD GetWindow(mozIDOMWindow** aWindow) override; + NS_IMETHOD GetElement(mozilla::dom::Element** aElement) override; + NS_IMETHOD GetHasValidTransientUserGestureActivation( + bool* aHasValidTransientUserGestureActivation) override; + NS_IMETHOD GetIsRequestDelegatedToUnsafeThirdParty( + bool* aIsRequestDelegatedToUnsafeThirdParty) override; + // Overrides for Allow() and Cancel() aren't provided by this class. + // That is the responsibility of the subclasses. + + enum class PromptResult { + Granted, + Denied, + Pending, + }; + nsresult ShowPrompt(PromptResult& aResult); + + PromptResult CheckPromptPrefs() const; + + // Check if the permission has an opportunity to request. + bool CheckPermissionDelegate() const; + + enum class DelayedTaskType { + Allow, + Deny, + Request, + }; + void RequestDelayedTask(nsIEventTarget* aTarget, DelayedTaskType aType); + + protected: + // @param aPrefName see `mPrefName`. + // @param aType see `mType`. + ContentPermissionRequestBase(nsIPrincipal* aPrincipal, + nsPIDOMWindowInner* aWindow, + const nsACString& aPrefName, + const nsACString& aType); + virtual ~ContentPermissionRequestBase() = default; + + nsCOMPtr mPrincipal; + nsCOMPtr mTopLevelPrincipal; + nsCOMPtr mWindow; + RefPtr mPermissionHandler; + + // The prefix of a pref which allows tests to bypass showing the prompt. + // Tests will have to set both of + // ${mPrefName}.prompt.testing and + // ${mPrefName}.prompt.testing.allow + // to either true or false. If no such testing is required, mPrefName may be + // empty. + const nsCString mPrefName; + + // The type of the request, such as "autoplay-media-audible". + const nsCString mType; + + bool mHasValidTransientUserGestureActivation; + + // See nsIPermissionDelegateHandler.maybeUnsafePermissionDelegate`. + bool mIsRequestDelegatedToUnsafeThirdParty; +}; + +} // namespace mozilla::dom + +using mozilla::dom::ContentPermissionRequestParent; + +class nsContentPermissionRequestProxy : public nsIContentPermissionRequest { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSICONTENTPERMISSIONREQUEST + + explicit nsContentPermissionRequestProxy( + ContentPermissionRequestParent* parent); + + nsresult Init(const nsTArray& requests); + + void OnParentDestroyed(); + + private: + virtual ~nsContentPermissionRequestProxy(); + + // Non-owning pointer to the ContentPermissionRequestParent object which owns + // this proxy. + ContentPermissionRequestParent* mParent; + nsTArray mPermissionRequests; +}; + +/** + * RemotePermissionRequest will send a prompt ipdl request to the chrome process + * (https://wiki.mozilla.org/Security/Sandbox/Process_model#Chrome_process_.28Parent.29). + */ +class RemotePermissionRequest final + : public mozilla::dom::PContentPermissionRequestChild { + public: + NS_INLINE_DECL_REFCOUNTING(RemotePermissionRequest) + + RemotePermissionRequest(nsIContentPermissionRequest* aRequest, + nsPIDOMWindowInner* aWindow); + + // It will be called when prompt dismissed. MOZ_CAN_RUN_SCRIPT_BOUNDARY + // because we don't have MOZ_CAN_RUN_SCRIPT bits in IPC code yet. + MOZ_CAN_RUN_SCRIPT_BOUNDARY + mozilla::ipc::IPCResult RecvNotifyResult( + const bool& aAllow, nsTArray&& aChoices); + + void IPDLAddRef() { + mIPCOpen = true; + AddRef(); + } + + void IPDLRelease() { + mIPCOpen = false; + Release(); + } + + void Destroy(); + + bool IPCOpen() const { return mIPCOpen && !mDestroyed; } + + private: + virtual ~RemotePermissionRequest(); + + MOZ_CAN_RUN_SCRIPT + void DoAllow(JS::Handle aChoices); + MOZ_CAN_RUN_SCRIPT + void DoCancel(); + + nsCOMPtr mRequest; + nsCOMPtr mWindow; + bool mIPCOpen; + bool mDestroyed; +}; + +#endif // nsContentPermissionHelper_h diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp new file mode 100644 index 0000000000..2c59d6fbf0 --- /dev/null +++ b/dom/base/nsContentPolicy.cpp @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim: ft=cpp tw=80 sw=2 et ts=8 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Implementation of the "@mozilla.org/layout/content-policy;1" contract. + */ + +#include "mozilla/Logging.h" + +#include "nsISupports.h" +#include "nsXPCOM.h" +#include "nsContentPolicyUtils.h" +#include "mozilla/dom/nsCSPService.h" +#include "nsContentPolicy.h" +#include "nsIURI.h" +#include "nsIBrowserChild.h" +#include "nsIContent.h" +#include "nsIImageLoadingContent.h" +#include "nsCOMArray.h" +#include "nsContentUtils.h" +#include "mozilla/dom/nsMixedContentBlocker.h" +#include "nsIContentSecurityPolicy.h" + +class nsIDOMWindow; + +using mozilla::LogLevel; + +NS_IMPL_ISUPPORTS(nsContentPolicy, nsIContentPolicy) + +static mozilla::LazyLogModule gConPolLog("nsContentPolicy"); + +nsresult NS_NewContentPolicy(nsIContentPolicy** aResult) { + *aResult = new nsContentPolicy; + NS_ADDREF(*aResult); + return NS_OK; +} + +nsContentPolicy::nsContentPolicy() : mPolicies(NS_CONTENTPOLICY_CATEGORY) {} + +nsContentPolicy::~nsContentPolicy() = default; + +#ifdef DEBUG +# define WARN_IF_URI_UNINITIALIZED(uri, name) \ + PR_BEGIN_MACRO \ + if ((uri)) { \ + nsAutoCString spec; \ + (uri)->GetAsciiSpec(spec); \ + if (spec.IsEmpty()) { \ + NS_WARNING(name " is uninitialized, fix caller"); \ + } \ + } \ + PR_END_MACRO + +#else // ! defined(DEBUG) + +# define WARN_IF_URI_UNINITIALIZED(uri, name) + +#endif // defined(DEBUG) + +inline nsresult nsContentPolicy::CheckPolicy(CPMethod policyMethod, + nsIURI* contentLocation, + nsILoadInfo* loadInfo, + int16_t* decision) { + nsCOMPtr requestingContext = loadInfo->GetLoadingContext(); + // sanity-check passed-through parameters + MOZ_ASSERT(decision, "Null out pointer"); + WARN_IF_URI_UNINITIALIZED(contentLocation, "Request URI"); + +#ifdef DEBUG + { + nsCOMPtr node(do_QueryInterface(requestingContext)); + nsCOMPtr window(do_QueryInterface(requestingContext)); + nsCOMPtr browserChild( + do_QueryInterface(requestingContext)); + NS_ASSERTION(!requestingContext || node || window || browserChild, + "Context should be a DOM node, DOM window or a browserChild!"); + } +#endif + + nsCOMPtr doc; + nsCOMPtr node = do_QueryInterface(requestingContext); + if (node) { + doc = node->OwnerDoc(); + } + if (!doc) { + doc = do_QueryInterface(requestingContext); + } + + /* + * Enumerate mPolicies and ask each of them, taking the logical AND of + * their permissions. + */ + nsresult rv; + const nsCOMArray& entries = mPolicies.GetCachedEntries(); + if (doc) { + if (nsCOMPtr csp = doc->GetCsp()) { + csp->EnsureEventTarget(mozilla::GetMainThreadSerialEventTarget()); + } + } + + int32_t count = entries.Count(); + for (int32_t i = 0; i < count; i++) { + /* check the appropriate policy */ + rv = (entries[i]->*policyMethod)(contentLocation, loadInfo, decision); + + if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) { + /* policy says no, no point continuing to check */ + return NS_OK; + } + } + + // everyone returned failure, or no policies: sanitize result + *decision = nsIContentPolicy::ACCEPT; + return NS_OK; +} + +// uses the parameters from ShouldXYZ to produce and log a message +// logType must be a literal string constant +#define LOG_CHECK(logType) \ + PR_BEGIN_MACRO \ + /* skip all this nonsense if the call failed or logging is disabled */ \ + if (NS_SUCCEEDED(rv) && MOZ_LOG_TEST(gConPolLog, LogLevel::Debug)) { \ + const char* resultName; \ + if (decision) { \ + resultName = NS_CP_ResponseName(*decision); \ + } else { \ + resultName = "(null ptr)"; \ + } \ + MOZ_LOG( \ + gConPolLog, LogLevel::Debug, \ + ("Content Policy: " logType ": <%s> result=%s", \ + contentLocation ? contentLocation->GetSpecOrDefault().get() : "None", \ + resultName)); \ + } \ + PR_END_MACRO + +NS_IMETHODIMP +nsContentPolicy::ShouldLoad(nsIURI* contentLocation, nsILoadInfo* loadInfo, + int16_t* decision) { + // ShouldProcess does not need a content location, but we do + MOZ_ASSERT(contentLocation, "Must provide request location"); + nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldLoad, contentLocation, + loadInfo, decision); + LOG_CHECK("ShouldLoad"); + + return rv; +} + +NS_IMETHODIMP +nsContentPolicy::ShouldProcess(nsIURI* contentLocation, nsILoadInfo* loadInfo, + int16_t* decision) { + nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldProcess, contentLocation, + loadInfo, decision); + LOG_CHECK("ShouldProcess"); + + return rv; +} diff --git a/dom/base/nsContentPolicy.h b/dom/base/nsContentPolicy.h new file mode 100644 index 0000000000..f30df27c48 --- /dev/null +++ b/dom/base/nsContentPolicy.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim: ft=cpp ts=8 sw=2 et 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 __nsContentPolicy_h__ +#define __nsContentPolicy_h__ + +#include "nsIContentPolicy.h" +#include "nsCategoryCache.h" + +/* + * Implementation of the "@mozilla.org/layout/content-policy;1" contract. + */ + +class nsContentPolicy : public nsIContentPolicy { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSICONTENTPOLICY + + nsContentPolicy(); + + protected: + virtual ~nsContentPolicy(); + + private: + // Array of policies + nsCategoryCache mPolicies; + + // Helper type for CheckPolicy + using CPMethod = decltype(&nsIContentPolicy::ShouldProcess); + + // Helper method that applies policyMethod across all policies in mPolicies + // with the given parameters + nsresult CheckPolicy(CPMethod policyMethod, nsIURI* aURI, + nsILoadInfo* aLoadInfo, int16_t* decision); +}; + +nsresult NS_NewContentPolicy(nsIContentPolicy** aResult); + +#endif /* __nsContentPolicy_h__ */ diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h new file mode 100644 index 0000000000..0581800966 --- /dev/null +++ b/dom/base/nsContentPolicyUtils.h @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; 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/. */ + +/* + * Utility routines for checking content load/process policy settings, + * and routines helpful for content policy implementors. + * + * XXXbz it would be nice if some of this stuff could be out-of-lined in + * nsContentUtils. That would work for almost all the callers... + */ + +#ifndef __nsContentPolicyUtils_h__ +#define __nsContentPolicyUtils_h__ + +#include "mozilla/BasePrincipal.h" + +#include "nsContentUtils.h" +#include "nsIContentPolicy.h" +#include "nsIContent.h" +#include "nsIURI.h" +#include "nsServiceManagerUtils.h" +#include "nsStringFwd.h" +#include "mozilla/dom/nsCSPService.h" + +// XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget +#include "mozilla/dom/Document.h" +#include "nsPIDOMWindow.h" + +#define NS_CONTENTPOLICY_CONTRACTID "@mozilla.org/layout/content-policy;1" +#define NS_CONTENTPOLICY_CATEGORY "content-policy" +#define NS_CONTENTPOLICY_CID \ + { \ + 0x0e3afd3d, 0xeb60, 0x4c2b, { \ + 0x96, 0x3b, 0x56, 0xd7, 0xc4, 0x39, 0xf1, 0x24 \ + } \ + } + +/** + * Evaluates to true if val is ACCEPT. + * + * @param val the status returned from shouldProcess/shouldLoad + */ +#define NS_CP_ACCEPTED(val) ((val) == nsIContentPolicy::ACCEPT) + +/** + * Evaluates to true if val is a REJECT_* status + * + * @param val the status returned from shouldProcess/shouldLoad + */ +#define NS_CP_REJECTED(val) ((val) != nsIContentPolicy::ACCEPT) + +// Offer convenient translations of constants -> const char* + +// convenience macro to reduce some repetative typing... +// name is the name of a constant from this interface +#define CASE_RETURN(name) \ + case nsIContentPolicy::name: \ + return #name + +/** + * Returns a string corresponding to the name of the response constant, or + * "" if an unknown response value is given. + * + * The return value is static and must not be freed. + * + * @param response the response code + * @return the name of the given response code + */ +inline const char* NS_CP_ResponseName(int16_t response) { + switch (response) { + CASE_RETURN(REJECT_REQUEST); + CASE_RETURN(REJECT_TYPE); + CASE_RETURN(REJECT_SERVER); + CASE_RETURN(REJECT_OTHER); + CASE_RETURN(ACCEPT); + default: + return ""; + } +} + +/** + * Returns a string corresponding to the name of the content type constant, or + * "" if an unknown content type value is given. + * + * The return value is static and must not be freed. + * + * @param contentType the content type code + * @return the name of the given content type code + */ +inline const char* NS_CP_ContentTypeName(nsContentPolicyType contentType) { + switch (contentType) { + CASE_RETURN(TYPE_OTHER); + CASE_RETURN(TYPE_SCRIPT); + CASE_RETURN(TYPE_IMAGE); + CASE_RETURN(TYPE_STYLESHEET); + CASE_RETURN(TYPE_OBJECT); + CASE_RETURN(TYPE_DOCUMENT); + CASE_RETURN(TYPE_SUBDOCUMENT); + CASE_RETURN(TYPE_PING); + CASE_RETURN(TYPE_XMLHTTPREQUEST); + CASE_RETURN(TYPE_OBJECT_SUBREQUEST); + CASE_RETURN(TYPE_DTD); + CASE_RETURN(TYPE_FONT); + CASE_RETURN(TYPE_MEDIA); + CASE_RETURN(TYPE_WEBSOCKET); + CASE_RETURN(TYPE_CSP_REPORT); + CASE_RETURN(TYPE_XSLT); + CASE_RETURN(TYPE_BEACON); + CASE_RETURN(TYPE_FETCH); + CASE_RETURN(TYPE_IMAGESET); + CASE_RETURN(TYPE_WEB_MANIFEST); + CASE_RETURN(TYPE_INTERNAL_SCRIPT); + CASE_RETURN(TYPE_INTERNAL_WORKER); + CASE_RETURN(TYPE_INTERNAL_SHARED_WORKER); + CASE_RETURN(TYPE_INTERNAL_EMBED); + CASE_RETURN(TYPE_INTERNAL_OBJECT); + CASE_RETURN(TYPE_INTERNAL_FRAME); + CASE_RETURN(TYPE_INTERNAL_IFRAME); + CASE_RETURN(TYPE_INTERNAL_AUDIO); + CASE_RETURN(TYPE_INTERNAL_VIDEO); + CASE_RETURN(TYPE_INTERNAL_TRACK); + CASE_RETURN(TYPE_INTERNAL_XMLHTTPREQUEST); + CASE_RETURN(TYPE_INTERNAL_EVENTSOURCE); + CASE_RETURN(TYPE_INTERNAL_SERVICE_WORKER); + CASE_RETURN(TYPE_INTERNAL_SCRIPT_PRELOAD); + CASE_RETURN(TYPE_INTERNAL_IMAGE); + CASE_RETURN(TYPE_INTERNAL_IMAGE_PRELOAD); + CASE_RETURN(TYPE_INTERNAL_IMAGE_FAVICON); + CASE_RETURN(TYPE_INTERNAL_STYLESHEET); + CASE_RETURN(TYPE_INTERNAL_STYLESHEET_PRELOAD); + CASE_RETURN(TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS); + CASE_RETURN(TYPE_SAVEAS_DOWNLOAD); + CASE_RETURN(TYPE_SPECULATIVE); + CASE_RETURN(TYPE_INTERNAL_MODULE); + CASE_RETURN(TYPE_INTERNAL_MODULE_PRELOAD); + CASE_RETURN(TYPE_INTERNAL_DTD); + CASE_RETURN(TYPE_INTERNAL_FORCE_ALLOWED_DTD); + CASE_RETURN(TYPE_INTERNAL_AUDIOWORKLET); + CASE_RETURN(TYPE_INTERNAL_PAINTWORKLET); + CASE_RETURN(TYPE_INTERNAL_FONT_PRELOAD); + CASE_RETURN(TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT); + CASE_RETURN(TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT); + CASE_RETURN(TYPE_INTERNAL_FETCH_PRELOAD); + CASE_RETURN(TYPE_UA_FONT); + CASE_RETURN(TYPE_INTERNAL_WORKER_STATIC_MODULE); + CASE_RETURN(TYPE_PROXIED_WEBRTC_MEDIA); + CASE_RETURN(TYPE_WEB_IDENTITY); + CASE_RETURN(TYPE_WEB_TRANSPORT); + CASE_RETURN(TYPE_END); + case nsIContentPolicy::TYPE_INVALID: + break; + // Do not add default: so that compilers can catch the missing case. + } + return ""; +} + +#undef CASE_RETURN + +inline const char* NS_CP_ContentTypeName(ExtContentPolicyType contentType) { + return NS_CP_ContentTypeName(static_cast(contentType)); +} + +/* Passes on parameters from its "caller"'s context. */ +#define CHECK_CONTENT_POLICY(action) \ + PR_BEGIN_MACRO \ + nsCOMPtr policy = \ + do_GetService(NS_CONTENTPOLICY_CONTRACTID); \ + if (!policy) return NS_ERROR_FAILURE; \ + \ + return policy->action(contentLocation, loadInfo, decision); \ + PR_END_MACRO + +/* Passes on parameters from its "caller"'s context. */ +#define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \ + PR_BEGIN_MACRO \ + return _policy->action(contentLocation, loadInfo, decision); \ + PR_END_MACRO + +/** + * Check whether we can short-circuit this check and bail out. If not, get the + * origin URI to use. + * + * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on + * purpose */ +#define CHECK_PRINCIPAL_CSP_AND_DATA(action) \ + PR_BEGIN_MACRO \ + if (loadingPrincipal && loadingPrincipal->IsSystemPrincipal()) { \ + /* We exempt most loads into any document with the system principal \ + * from content policy (except CSP) checks, mostly as an optimization. \ + * Which means that we need to apply this check to the loading principal, \ + * not the principal that triggered the load. */ \ + /* Check CSP for System Privileged pages */ \ + CSPService::ConsultCSP(contentLocation, loadInfo, decision); \ + if (NS_CP_REJECTED(*decision)) { \ + return NS_OK; \ + } \ + if (contentType != nsIContentPolicy::TYPE_DOCUMENT && \ + contentType != nsIContentPolicy::TYPE_UA_FONT) { \ + *decision = nsIContentPolicy::ACCEPT; \ + nsCOMPtr n = do_QueryInterface(context); \ + if (!n) { \ + nsCOMPtr win = do_QueryInterface(context); \ + n = win ? win->GetExtantDoc() : nullptr; \ + } \ + if (n) { \ + mozilla::dom::Document* d = n->OwnerDoc(); \ + if (d->IsLoadedAsData() || d->IsBeingUsedAsImage() || \ + d->IsResourceDoc()) { \ + nsCOMPtr dataPolicy = \ + do_GetService("@mozilla.org/data-document-content-policy;1"); \ + if (dataPolicy) { \ + dataPolicy->action(contentLocation, loadInfo, decision); \ + } \ + } \ + } \ + } \ + return NS_OK; \ + } \ + PR_END_MACRO + +/** + * Alias for calling ShouldLoad on the content policy service. Parameters are + * the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal + * and triggeringPrincipal parameters (which should be non-null if possible, + * and have the same semantics as in nsLoadInfo), and the last parameter, + * which can be used to pass in a pointer to a useful service if the caller + * already has it. The origin URI to pass to shouldLoad will be the URI of + * loadingPrincipal, unless loadingPrincipal is null (in which case a null + * origin URI will be passed). + */ +inline nsresult NS_CheckContentLoadPolicy( + nsIURI* contentLocation, nsILoadInfo* loadInfo, int16_t* decision, + nsIContentPolicy* policyService = nullptr) { + nsIPrincipal* loadingPrincipal = loadInfo->GetLoadingPrincipal(); + nsCOMPtr context = loadInfo->GetLoadingContext(); + nsContentPolicyType contentType = loadInfo->InternalContentPolicyType(); + CHECK_PRINCIPAL_CSP_AND_DATA(ShouldLoad); + if (policyService) { + CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService); + } + CHECK_CONTENT_POLICY(ShouldLoad); +} + +/** + * Alias for calling ShouldProcess on the content policy service. + */ +inline nsresult NS_CheckContentProcessPolicy( + nsIURI* contentLocation, nsILoadInfo* loadInfo, int16_t* decision, + nsIContentPolicy* policyService = nullptr) { + nsIPrincipal* loadingPrincipal = loadInfo->GetLoadingPrincipal(); + nsCOMPtr context = loadInfo->GetLoadingContext(); + nsContentPolicyType contentType = loadInfo->InternalContentPolicyType(); + CHECK_PRINCIPAL_CSP_AND_DATA(ShouldProcess); + if (policyService) { + CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldProcess, policyService); + } + CHECK_CONTENT_POLICY(ShouldProcess); +} + +#undef CHECK_CONTENT_POLICY +#undef CHECK_CONTENT_POLICY_WITH_SERVICE + +/** + * Helper function to get an nsIDocShell given a context. + * If the context is a document or window, the corresponding docshell will be + * returned. + * If the context is a non-document DOM node, the docshell of its ownerDocument + * will be returned. + * + * @param aContext the context to find a docshell for (can be null) + * + * @return a WEAK pointer to the docshell, or nullptr if it could + * not be obtained + * + * @note As of this writing, calls to nsIContentPolicy::Should{Load,Process} + * for TYPE_DOCUMENT and TYPE_SUBDOCUMENT pass in an aContext that either + * points to the frameElement of the window the load is happening in + * (in which case NS_CP_GetDocShellFromContext will return the parent of the + * docshell the load is happening in), or points to the window the load is + * happening in (in which case NS_CP_GetDocShellFromContext will return + * the docshell the load is happening in). It's up to callers to QI aContext + * and handle things accordingly if they want the docshell the load is + * happening in. These are somewhat odd semantics, and bug 466687 has been + * filed to consider improving them. + */ +inline nsIDocShell* NS_CP_GetDocShellFromContext(nsISupports* aContext) { + if (!aContext) { + return nullptr; + } + + nsCOMPtr window = do_QueryInterface(aContext); + + if (!window) { + // Our context might be a document. + nsCOMPtr doc = do_QueryInterface(aContext); + if (!doc) { + // we were not a document after all, get our ownerDocument, + // hopefully + nsCOMPtr content = do_QueryInterface(aContext); + if (content) { + doc = content->OwnerDoc(); + } + } + + if (doc) { + if (doc->GetDisplayDocument()) { + doc = doc->GetDisplayDocument(); + } + + window = doc->GetWindow(); + } + } + + if (!window) { + return nullptr; + } + + return window->GetDocShell(); +} + +#endif /* __nsContentPolicyUtils_h__ */ diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp new file mode 100644 index 0000000000..b7f13db239 --- /dev/null +++ b/dom/base/nsContentSink.cpp @@ -0,0 +1,971 @@ +/* -*- 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/. */ + +/* + * Base class for the XML and HTML content sinks, which construct a + * DOM based on information from the parser. + */ + +#include "nsContentSink.h" +#include "mozilla/Components.h" +#include "mozilla/PresShell.h" +#include "mozilla/StaticPrefs_browser.h" +#include "mozilla/StaticPrefs_content.h" +#include "mozilla/StaticPrefs_network.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/LinkStyle.h" +#include "mozilla/dom/ReferrerInfo.h" +#include "mozilla/css/Loader.h" +#include "mozilla/dom/MutationObservers.h" +#include "mozilla/dom/SRILogHelper.h" +#include "mozilla/StoragePrincipalHelper.h" +#include "mozilla/net/HttpBaseChannel.h" +#include "mozilla/net/NeckoChannelParams.h" +#include "nsIDocShell.h" +#include "nsILoadContext.h" +#include "nsIPrefetchService.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsIMIMEHeaderParam.h" +#include "nsIProtocolHandler.h" +#include "nsIHttpChannel.h" +#include "nsIContent.h" +#include "nsPresContext.h" +#include "nsViewManager.h" +#include "nsAtom.h" +#include "nsGkAtoms.h" +#include "nsGlobalWindowInner.h" +#include "nsNetCID.h" +#include "nsICookieService.h" +#include "nsContentUtils.h" +#include "nsNodeInfoManager.h" +#include "nsIAppShell.h" +#include "nsIWidget.h" +#include "nsWidgetsCID.h" +#include "mozAutoDocUpdate.h" +#include "nsIWebNavigation.h" +#include "nsGenericHTMLElement.h" +#include "nsIObserverService.h" +#include "mozilla/Preferences.h" +#include "mozilla/ProfilerLabels.h" +#include "mozilla/dom/HTMLDNSPrefetch.h" +#include "mozilla/dom/ServiceWorkerDescriptor.h" +#include "mozilla/dom/ScriptLoader.h" +#include "nsParserConstants.h" +#include "nsSandboxFlags.h" +#include "Link.h" +#include "HTMLLinkElement.h" +#include "MediaList.h" +#include "nsString.h" +#include "nsStringFwd.h" +#include +#include "mozilla/RefPtr.h" +#include "nsCOMPtr.h" +#include "nsLiteralString.h" +#include "nsIContentPolicy.h" +using namespace mozilla; +using namespace mozilla::css; +using namespace mozilla::dom; + +LazyLogModule gContentSinkLogModuleInfo("nscontentsink"); + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink) + NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver) + NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) + NS_INTERFACE_MAP_ENTRY(nsITimerCallback) + NS_INTERFACE_MAP_ENTRY(nsINamed) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink) + if (tmp->mDocument) { + tmp->mDocument->RemoveObserver(tmp); + } + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader) + NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +nsContentSink::nsContentSink() + : mBackoffCount(0), + mLastNotificationTime(0), + mLayoutStarted(0), + mDynamicLowerValue(0), + mParsing(0), + mDroppedTimer(0), + mDeferredLayoutStart(0), + mDeferredFlushTags(0), + mIsDocumentObserver(0), + mRunsToCompletion(0), + mIsBlockingOnload(false), + mDeflectedCount(0), + mHasPendingEvent(false), + mCurrentParseEndTime(0), + mBeginLoadTime(0), + mLastSampledUserEventTime(0), + mInMonolithicContainer(0), + mInNotification(0), + mUpdatesInNotification(0), + mPendingSheetCount(0) { + NS_ASSERTION(!mLayoutStarted, "What?"); + NS_ASSERTION(!mDynamicLowerValue, "What?"); + NS_ASSERTION(!mParsing, "What?"); + NS_ASSERTION(mLastSampledUserEventTime == 0, "What?"); + NS_ASSERTION(mDeflectedCount == 0, "What?"); + NS_ASSERTION(!mDroppedTimer, "What?"); + NS_ASSERTION(mInMonolithicContainer == 0, "What?"); + NS_ASSERTION(mInNotification == 0, "What?"); + NS_ASSERTION(!mDeferredLayoutStart, "What?"); +} + +nsContentSink::~nsContentSink() { + if (mDocument) { + // Remove ourselves just to be safe, though we really should have + // been removed in DidBuildModel if everything worked right. + mDocument->RemoveObserver(this); + } +} + +nsresult nsContentSink::Init(Document* aDoc, nsIURI* aURI, + nsISupports* aContainer, nsIChannel* aChannel) { + MOZ_ASSERT(aDoc, "null ptr"); + MOZ_ASSERT(aURI, "null ptr"); + + if (!aDoc || !aURI) { + return NS_ERROR_NULL_POINTER; + } + + mDocument = aDoc; + + mDocumentURI = aURI; + mDocShell = do_QueryInterface(aContainer); + mScriptLoader = mDocument->ScriptLoader(); + + if (!mRunsToCompletion) { + if (mDocShell) { + uint32_t loadType = 0; + mDocShell->GetLoadType(&loadType); + mDocument->SetChangeScrollPosWhenScrollingToRef( + (loadType & nsIDocShell::LOAD_CMD_HISTORY) == 0); + } + + ProcessHTTPHeaders(aChannel); + } + + mCSSLoader = aDoc->CSSLoader(); + + mNodeInfoManager = aDoc->NodeInfoManager(); + + mBackoffCount = StaticPrefs::content_notify_backoffcount(); + + if (StaticPrefs::content_sink_enable_perf_mode() != 0) { + mDynamicLowerValue = StaticPrefs::content_sink_enable_perf_mode() == 1; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsContentSink::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred, + nsresult aStatus) { + MOZ_ASSERT(!mRunsToCompletion, "How come a fragment parser observed sheets?"); + if (aWasDeferred) { + return NS_OK; + } + MOZ_ASSERT(mPendingSheetCount > 0, "How'd that happen?"); + --mPendingSheetCount; + + const bool loadedAllSheets = !mPendingSheetCount; + if (loadedAllSheets && (mDeferredLayoutStart || mDeferredFlushTags)) { + if (mDeferredFlushTags) { + FlushTags(); + } + if (mDeferredLayoutStart) { + // We might not have really started layout, since this sheet was still + // loading. Do it now. Probably doesn't matter whether we do this + // before or after we unblock scripts, but before feels saner. Note + // that if mDeferredLayoutStart is true, that means any subclass + // StartLayout() stuff that needs to happen has already happened, so + // we don't need to worry about it. + StartLayout(false); + } + + // Go ahead and try to scroll to our ref if we have one + ScrollToRef(); + } + + mScriptLoader->RemoveParserBlockingScriptExecutionBlocker(); + + if (loadedAllSheets && + mDocument->GetReadyStateEnum() >= Document::READYSTATE_INTERACTIVE) { + mScriptLoader->DeferCheckpointReached(); + } + + return NS_OK; +} + +nsresult nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel) { + nsCOMPtr httpchannel(do_QueryInterface(aChannel)); + + if (!httpchannel) { + return NS_OK; + } + + bool gotEarlyHints = false; + if (nsCOMPtr baseChannel = + do_QueryInterface(aChannel)) { + nsTArray earlyHints = + baseChannel->TakeEarlyHints(); + gotEarlyHints = !earlyHints.IsEmpty(); + mDocument->SetEarlyHints(std::move(earlyHints)); + } + + // Note that the only header we care about is the "link" header, since we + // have all the infrastructure for kicking off stylesheet loads. + + nsAutoCString linkHeader; + + nsresult rv = httpchannel->GetResponseHeader("link"_ns, linkHeader); + bool gotLinkHeader = NS_SUCCEEDED(rv) && !linkHeader.IsEmpty(); + if (gotLinkHeader) { + mDocument->SetHeaderData(nsGkAtoms::link, + NS_ConvertASCIItoUTF16(linkHeader)); + } + if (gotLinkHeader || gotEarlyHints) { + NS_ASSERTION(!mProcessLinkHeaderEvent.get(), + "Already dispatched an event?"); + + mProcessLinkHeaderEvent = + NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader", this, + &nsContentSink::DoProcessLinkHeader); + rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get()); + if (NS_FAILED(rv)) { + mProcessLinkHeaderEvent.Forget(); + } + } + + return NS_OK; +} + +void nsContentSink::DoProcessLinkHeader() { + for (const auto& earlyHint : mDocument->GetEarlyHints()) { + ProcessLinkFromHeader(earlyHint.link(), earlyHint.earlyHintPreloaderId()); + } + + nsAutoString value; + + // Getting the header data and parsing the link header together roughly + // implement . + mDocument->GetHeaderData(nsGkAtoms::link, value); + auto linkHeaders = net::ParseLinkHeader(value); + + for (const auto& linkHeader : linkHeaders) { + ProcessLinkFromHeader(linkHeader, 0); + } +} + +nsresult nsContentSink::ProcessLinkFromHeader(const net::LinkHeader& aHeader, + uint64_t aEarlyHintPreloaderId) { + uint32_t linkTypes = LinkStyle::ParseLinkTypes(aHeader.mRel); + + // The link relation may apply to a different resource, specified + // in the anchor parameter. For the link relations supported so far, + // we simply abort if the link applies to a resource different to the + // one we've loaded + if (!nsContentUtils::LinkContextIsURI(aHeader.mAnchor, + mDocument->GetDocumentURI())) { + return NS_OK; + } + + if (nsContentUtils::PrefetchPreloadEnabled(mDocShell)) { + // prefetch href if relation is "next" or "prefetch" + if ((linkTypes & LinkStyle::eNEXT) || (linkTypes & LinkStyle::ePREFETCH)) { + PrefetchHref(aHeader.mHref, aHeader.mAs, aHeader.mType, aHeader.mMedia); + } + + if (!aHeader.mHref.IsEmpty() && (linkTypes & LinkStyle::eDNS_PREFETCH)) { + PrefetchDNS(aHeader.mHref); + } + + if (!aHeader.mHref.IsEmpty() && (linkTypes & LinkStyle::ePRECONNECT)) { + Preconnect(aHeader.mHref, aHeader.mCrossOrigin); + } + + if (linkTypes & LinkStyle::ePRELOAD) { + PreloadHref(aHeader.mHref, aHeader.mAs, aHeader.mType, aHeader.mMedia, + aHeader.mNonce, aHeader.mIntegrity, aHeader.mSrcset, + aHeader.mSizes, aHeader.mCrossOrigin, aHeader.mReferrerPolicy, + aEarlyHintPreloaderId, aHeader.mFetchPriority); + } + + if ((linkTypes & LinkStyle::eMODULE_PRELOAD) && + mDocument->ScriptLoader()->GetModuleLoader()) { + PreloadModule(aHeader.mHref, aHeader.mAs, aHeader.mMedia, aHeader.mNonce, + aHeader.mIntegrity, aHeader.mCrossOrigin, + aHeader.mReferrerPolicy, aEarlyHintPreloaderId, + aHeader.mFetchPriority); + } + } + + // is it a stylesheet link? + if (!(linkTypes & LinkStyle::eSTYLESHEET)) { + return NS_OK; + } + + bool isAlternate = linkTypes & LinkStyle::eALTERNATE; + return ProcessStyleLinkFromHeader(aHeader.mHref, isAlternate, aHeader.mTitle, + aHeader.mIntegrity, aHeader.mType, + aHeader.mMedia, aHeader.mReferrerPolicy, + aHeader.mFetchPriority); +} + +nsresult nsContentSink::ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy, + const nsAString& aFetchPriority) { + if (aAlternate && aTitle.IsEmpty()) { + // alternates must have title return without error, for now + return NS_OK; + } + + nsAutoString mimeType; + nsAutoString params; + nsContentUtils::SplitMimeType(aType, mimeType, params); + + // see bug 18817 + if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) { + // Unknown stylesheet language + return NS_OK; + } + + nsCOMPtr url; + nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr, + mDocument->GetDocBaseURI()); + + if (NS_FAILED(rv)) { + // The URI is bad, move along, don't propagate the error (for now) + return NS_OK; + } + + // Link header is working like a node, so referrerPolicy attr should + // have higher priority than referrer policy from document. + ReferrerPolicy policy = + ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy); + nsCOMPtr referrerInfo = + ReferrerInfo::CreateFromDocumentAndPolicyOverride(mDocument, policy); + + const FetchPriority fetchPriority = + nsGenericHTMLElement::ToFetchPriority(aFetchPriority); + + Loader::SheetInfo info{ + *mDocument, + nullptr, + url.forget(), + nullptr, + referrerInfo.forget(), + CORS_NONE, + aTitle, + aMedia, + aIntegrity, + /* nonce = */ u""_ns, + aAlternate ? Loader::HasAlternateRel::Yes : Loader::HasAlternateRel::No, + Loader::IsInline::No, + Loader::IsExplicitlyEnabled::No, + fetchPriority, + }; + + auto loadResultOrErr = + mCSSLoader->LoadStyleLink(info, mRunsToCompletion ? nullptr : this); + if (loadResultOrErr.isErr()) { + return loadResultOrErr.unwrapErr(); + } + + if (loadResultOrErr.inspect().ShouldBlock() && !mRunsToCompletion) { + ++mPendingSheetCount; + mScriptLoader->AddParserBlockingScriptExecutionBlocker(); + } + + return NS_OK; +} + +void nsContentSink::PrefetchHref(const nsAString& aHref, const nsAString& aAs, + const nsAString& aType, + const nsAString& aMedia) { + nsCOMPtr prefetchService(components::Prefetch::Service()); + if (prefetchService) { + // construct URI using document charset + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI()); + if (uri) { + auto referrerInfo = MakeRefPtr(*mDocument); + referrerInfo = referrerInfo->CloneWithNewOriginalReferrer(mDocumentURI); + + prefetchService->PrefetchURI(uri, referrerInfo, mDocument, true); + } + } +} + +void nsContentSink::PreloadHref(const nsAString& aHref, const nsAString& aAs, + const nsAString& aType, const nsAString& aMedia, + const nsAString& aNonce, + const nsAString& aIntegrity, + const nsAString& aSrcset, + const nsAString& aSizes, const nsAString& aCORS, + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId, + const nsAString& aFetchPriority) { + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI()); + if (!uri) { + // URL parsing failed. + return; + } + + nsAttrValue asAttr; + mozilla::net::ParseAsValue(aAs, asAttr); + + nsAutoString mimeType; + nsAutoString notUsed; + nsContentUtils::SplitMimeType(aType, mimeType, notUsed); + + auto policyType = mozilla::net::AsValueToContentPolicy(asAttr); + if (policyType == nsIContentPolicy::TYPE_INVALID || + !mozilla::net::CheckPreloadAttrs(asAttr, mimeType, aMedia, mDocument)) { + // Ignore preload wrong or empty attributes. + mozilla::net::WarnIgnoredPreload(*mDocument, *uri); + return; + } + + mDocument->Preloads().PreloadLinkHeader( + uri, aHref, policyType, aAs, aType, aNonce, aIntegrity, aSrcset, aSizes, + aCORS, aReferrerPolicy, aEarlyHintPreloaderId, aFetchPriority); +} + +void nsContentSink::PreloadModule( + const nsAString& aHref, const nsAString& aAs, const nsAString& aMedia, + const nsAString& aNonce, const nsAString& aIntegrity, + const nsAString& aCORS, const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId, const nsAString& aFetchPriority) { + ModuleLoader* moduleLoader = mDocument->ScriptLoader()->GetModuleLoader(); + + if (!StaticPrefs::network_modulepreload()) { + // Keep behavior from https://phabricator.services.mozilla.com/D149371, + // prior to main implementation of modulepreload + moduleLoader->DisallowImportMaps(); + return; + } + + RefPtr mediaList = + mozilla::dom::MediaList::Create(NS_ConvertUTF16toUTF8(aMedia)); + if (!mediaList->Matches(*mDocument)) { + return; + } + + if (aHref.IsEmpty()) { + return; + } + + if (!net::IsScriptLikeOrInvalid(aAs)) { + return; + } + + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI()); + if (!uri) { + return; + } + + moduleLoader->DisallowImportMaps(); + + mDocument->Preloads().PreloadLinkHeader( + uri, aHref, nsIContentPolicy::TYPE_SCRIPT, u"script"_ns, u"module"_ns, + aNonce, aIntegrity, u""_ns, u""_ns, aCORS, aReferrerPolicy, + aEarlyHintPreloaderId, aFetchPriority); +} + +void nsContentSink::PrefetchDNS(const nsAString& aHref) { + nsAutoString hostname; + bool isHttps = false; + + if (StringBeginsWith(aHref, u"//"_ns)) { + hostname = Substring(aHref, 2); + } else { + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aHref); + if (!uri) { + return; + } + nsresult rv; + bool isLocalResource = false; + rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, + &isLocalResource); + if (NS_SUCCEEDED(rv) && !isLocalResource) { + nsAutoCString host; + uri->GetHost(host); + CopyUTF8toUTF16(host, hostname); + } + isHttps = uri->SchemeIs("https"); + } + + if (!hostname.IsEmpty() && HTMLDNSPrefetch::IsAllowed(mDocument)) { + OriginAttributes oa; + StoragePrincipalHelper::GetOriginAttributesForNetworkState(mDocument, oa); + + HTMLDNSPrefetch::Prefetch(hostname, isHttps, oa, + mDocument->GetChannel()->GetTRRMode(), + HTMLDNSPrefetch::Priority::Low); + } +} + +void nsContentSink::Preconnect(const nsAString& aHref, + const nsAString& aCrossOrigin) { + // construct URI using document charset + auto encoding = mDocument->GetDocumentCharacterSet(); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI()); + + if (uri && mDocument) { + mDocument->MaybePreconnect(uri, + dom::Element::StringToCORSMode(aCrossOrigin)); + } +} + +void nsContentSink::ScrollToRef() { + RefPtr document = mDocument; + document->ScrollToRef(); +} + +void nsContentSink::StartLayout(bool aIgnorePendingSheets) { + if (mLayoutStarted) { + // Nothing to do here + return; + } + + mDeferredLayoutStart = true; + + if (!aIgnorePendingSheets && + (WaitForPendingSheets() || mDocument->HasPendingInitialTranslation())) { + // Bail out; we'll start layout when the sheets and l10n load + return; + } + + AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_RELEVANT_FOR_JS( + "Layout", LAYOUT, mDocumentURI->GetSpecOrDefault()); + + mDeferredLayoutStart = false; + + if (aIgnorePendingSheets) { + nsContentUtils::ReportToConsole( + nsIScriptError::warningFlag, "Layout"_ns, mDocument, + nsContentUtils::eLAYOUT_PROPERTIES, "ForcedLayoutStart"); + } + + // Notify on all our content. If none of our presshells have started layout + // yet it'll be a no-op except for updating our data structures, a la + // UpdateChildCounts() (because we don't want to double-notify on whatever we + // have right now). If some of them _have_ started layout, we want to make + // sure to flush tags instead of just calling UpdateChildCounts() after we + // loop over the shells. + FlushTags(); + + mLayoutStarted = true; + mLastNotificationTime = PR_Now(); + + mDocument->SetMayStartLayout(true); + RefPtr presShell = mDocument->GetPresShell(); + // Make sure we don't call Initialize() for a shell that has + // already called it. This can happen when the layout frame for + // an iframe is constructed *between* the Embed() call for the + // docshell in the iframe, and the content sink's call to OpenBody(). + // (Bug 153815) + if (presShell && !presShell->DidInitialize()) { + nsresult rv = presShell->Initialize(); + if (NS_FAILED(rv)) { + return; + } + } + + // If the document we are loading has a reference or it is a + // frameset document, disable the scroll bars on the views. + + mDocument->SetScrollToRef(mDocument->GetDocumentURI()); +} + +void nsContentSink::NotifyAppend(nsIContent* aContainer, uint32_t aStartIndex) { + mInNotification++; + + { + // Scope so we call EndUpdate before we decrease mInNotification + // + // Note that aContainer->OwnerDoc() may not be mDocument. + MOZ_AUTO_DOC_UPDATE(aContainer->OwnerDoc(), true); + MutationObservers::NotifyContentAppended( + aContainer, aContainer->GetChildAt_Deprecated(aStartIndex)); + mLastNotificationTime = PR_Now(); + } + + mInNotification--; +} + +NS_IMETHODIMP +nsContentSink::Notify(nsITimer* timer) { + if (mParsing) { + // We shouldn't interfere with our normal DidProcessAToken logic + mDroppedTimer = true; + return NS_OK; + } + + if (WaitForPendingSheets()) { + mDeferredFlushTags = true; + } else { + FlushTags(); + + // Now try and scroll to the reference + // XXX Should we scroll unconditionally for history loads?? + ScrollToRef(); + } + + mNotificationTimer = nullptr; + return NS_OK; +} + +bool nsContentSink::IsTimeToNotify() { + if (!StaticPrefs::content_notify_ontimer() || !mLayoutStarted || + !mBackoffCount || mInMonolithicContainer) { + return false; + } + + if (WaitForPendingSheets()) { + mDeferredFlushTags = true; + return false; + } + + PRTime now = PR_Now(); + + int64_t interval = GetNotificationInterval(); + int64_t diff = now - mLastNotificationTime; + + if (diff > interval) { + mBackoffCount--; + return true; + } + + return false; +} + +nsresult nsContentSink::WillInterruptImpl() { + nsresult result = NS_OK; + + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_CALLS, ("nsContentSink::WillInterrupt: this=%p", this)); +#ifndef SINK_NO_INCREMENTAL + if (WaitForPendingSheets()) { + mDeferredFlushTags = true; + } else if (StaticPrefs::content_notify_ontimer() && mLayoutStarted) { + if (mBackoffCount && !mInMonolithicContainer) { + int64_t now = PR_Now(); + int64_t interval = GetNotificationInterval(); + int64_t diff = now - mLastNotificationTime; + + // If it's already time for us to have a notification + if (diff > interval || mDroppedTimer) { + mBackoffCount--; + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_REFLOW, + ("nsContentSink::WillInterrupt: flushing tags since we've " + "run out time; backoff count: %d", + mBackoffCount)); + result = FlushTags(); + if (mDroppedTimer) { + ScrollToRef(); + mDroppedTimer = false; + } + } else if (!mNotificationTimer) { + interval -= diff; + int32_t delay = interval; + + // Convert to milliseconds + delay /= PR_USEC_PER_MSEC; + + NS_NewTimerWithCallback(getter_AddRefs(mNotificationTimer), this, delay, + nsITimer::TYPE_ONE_SHOT); + if (mNotificationTimer) { + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_REFLOW, + ("nsContentSink::WillInterrupt: setting up timer with " + "delay %d", + delay)); + } + } + } + } else { + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_REFLOW, + ("nsContentSink::WillInterrupt: flushing tags " + "unconditionally")); + result = FlushTags(); + } +#endif + + mParsing = false; + + return result; +} + +void nsContentSink::WillResumeImpl() { + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_CALLS, ("nsContentSink::WillResume: this=%p", this)); + + mParsing = true; +} + +nsresult nsContentSink::DidProcessATokenImpl() { + if (mRunsToCompletion || !mParser) { + return NS_OK; + } + + // Get the current user event time + PresShell* presShell = mDocument->GetPresShell(); + if (!presShell) { + // If there's no pres shell in the document, return early since + // we're not laying anything out here. + return NS_OK; + } + + // Increase before comparing to gEventProbeRate + ++mDeflectedCount; + + // Check if there's a pending event + if (StaticPrefs::content_sink_pending_event_mode() != 0 && + !mHasPendingEvent && + (mDeflectedCount % StaticPrefs::content_sink_event_probe_rate()) == 0) { + nsViewManager* vm = presShell->GetViewManager(); + NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE); + nsCOMPtr widget = vm->GetRootWidget(); + mHasPendingEvent = widget && widget->HasPendingInputEvent(); + } + + if (mHasPendingEvent && StaticPrefs::content_sink_pending_event_mode() == 2) { + return NS_ERROR_HTMLPARSER_INTERRUPTED; + } + + // Have we processed enough tokens to check time? + if (!mHasPendingEvent && + mDeflectedCount < + uint32_t(mDynamicLowerValue + ? StaticPrefs::content_sink_interactive_deflect_count() + : StaticPrefs::content_sink_perf_deflect_count())) { + return NS_OK; + } + + mDeflectedCount = 0; + + // Check if it's time to return to the main event loop + if (PR_IntervalToMicroseconds(PR_IntervalNow()) > mCurrentParseEndTime) { + return NS_ERROR_HTMLPARSER_INTERRUPTED; + } + + return NS_OK; +} + +//---------------------------------------------------------------------- + +void nsContentSink::BeginUpdate(Document* aDocument) { + // Remember nested updates from updates that we started. + if (mInNotification > 0 && mUpdatesInNotification < 2) { + ++mUpdatesInNotification; + } + + // If we're in a script and we didn't do the notification, + // something else in the script processing caused the + // notification to occur. Since this could result in frame + // creation, make sure we've flushed everything before we + // continue. + + if (!mInNotification++) { + FlushTags(); + } +} + +void nsContentSink::EndUpdate(Document* aDocument) { + // If we're in a script and we didn't do the notification, + // something else in the script processing caused the + // notification to occur. Update our notion of how much + // has been flushed to include any new content if ending + // this update leaves us not inside a notification. + if (!--mInNotification) { + UpdateChildCounts(); + } +} + +void nsContentSink::DidBuildModelImpl(bool aTerminated) { + MOZ_ASSERT(aTerminated || (mParser && mParser->IsParserClosed()) || + mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING, + "Bad readyState"); + mDocument->SetReadyStateInternal(Document::READYSTATE_INTERACTIVE); + + if (mScriptLoader) { + mScriptLoader->ParsingComplete(aTerminated); + if (!mPendingSheetCount) { + mScriptLoader->DeferCheckpointReached(); + } + } + + if (!mDocument->HaveFiredDOMTitleChange()) { + mDocument->NotifyPossibleTitleChange(false); + } + + // Cancel a timer if we had one out there + if (mNotificationTimer) { + SINK_TRACE(static_cast(gContentSinkLogModuleInfo), + SINK_TRACE_REFLOW, + ("nsContentSink::DidBuildModel: canceling notification " + "timeout")); + mNotificationTimer->Cancel(); + mNotificationTimer = nullptr; + } +} + +void nsContentSink::DropParserAndPerfHint(void) { + if (!mParser) { + // Make sure we don't unblock unload too many times + return; + } + + // Ref. Bug 49115 + // Do this hack to make sure that the parser + // doesn't get destroyed, accidently, before + // the circularity, between sink & parser, is + // actually broken. + // Drop our reference to the parser to get rid of a circular + // reference. + RefPtr kungFuDeathGrip = std::move(mParser); + mozilla::Unused << kungFuDeathGrip; + + // Call UnblockOnload only if mRunsToComletion is false and if + // we have already started loading because it's possible that this function + // is called (i.e. the parser is terminated) before we start loading due to + // destroying the window inside unload event callbacks for the previous + // document. + if (!mRunsToCompletion && mIsBlockingOnload) { + mDocument->UnblockOnload(true); + mIsBlockingOnload = false; + } +} + +bool nsContentSink::IsScriptExecutingImpl() { + return !!mScriptLoader->GetCurrentScript(); +} + +nsresult nsContentSink::WillParseImpl(void) { + if (mRunsToCompletion || !mDocument) { + return NS_OK; + } + + PresShell* presShell = mDocument->GetPresShell(); + if (!presShell) { + return NS_OK; + } + + uint32_t currentTime = PR_IntervalToMicroseconds(PR_IntervalNow()); + + if (StaticPrefs::content_sink_enable_perf_mode() == 0) { + nsViewManager* vm = presShell->GetViewManager(); + NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE); + uint32_t lastEventTime; + vm->GetLastUserEventTime(lastEventTime); + + bool newDynLower = mDocument->IsInBackgroundWindow() || + ((currentTime - mBeginLoadTime) > + StaticPrefs::content_sink_initial_perf_time() && + (currentTime - lastEventTime) < + StaticPrefs::content_sink_interactive_time()); + + if (mDynamicLowerValue != newDynLower) { + mDynamicLowerValue = newDynLower; + } + } + + mDeflectedCount = 0; + mHasPendingEvent = false; + + mCurrentParseEndTime = + currentTime + (mDynamicLowerValue + ? StaticPrefs::content_sink_interactive_parse_time() + : StaticPrefs::content_sink_perf_parse_time()); + + return NS_OK; +} + +void nsContentSink::WillBuildModelImpl() { + if (!mRunsToCompletion) { + mDocument->BlockOnload(); + mIsBlockingOnload = true; + + mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow()); + } + + mDocument->ResetScrolledToRefAlready(); + + if (mProcessLinkHeaderEvent.get()) { + mProcessLinkHeaderEvent.Revoke(); + + DoProcessLinkHeader(); + } +} + +/* static */ +void nsContentSink::NotifyDocElementCreated(Document* aDoc) { + MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + + nsCOMPtr observerService = + mozilla::services::GetObserverService(); + MOZ_ASSERT(observerService); + + auto* win = nsGlobalWindowInner::Cast(aDoc->GetInnerWindow()); + bool fireInitialInsertion = !win || !win->DidFireDocElemInserted(); + if (win) { + win->SetDidFireDocElemInserted(); + } + if (fireInitialInsertion) { + observerService->NotifyObservers(ToSupports(aDoc), + "initial-document-element-inserted", u""); + } + observerService->NotifyObservers(ToSupports(aDoc), + "document-element-inserted", u""); + + nsContentUtils::DispatchChromeEvent(aDoc, aDoc, u"DOMDocElementInserted"_ns, + CanBubble::eYes, Cancelable::eNo); +} + +NS_IMETHODIMP +nsContentSink::GetName(nsACString& aName) { + aName.AssignLiteral("nsContentSink_timer"); + return NS_OK; +} diff --git a/dom/base/nsContentSink.h b/dom/base/nsContentSink.h new file mode 100644 index 0000000000..e9a2166dcd --- /dev/null +++ b/dom/base/nsContentSink.h @@ -0,0 +1,273 @@ +/* -*- 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/. */ + +/* + * Base class for the XML and HTML content sinks, which construct a + * DOM based on information from the parser. + */ + +#ifndef _nsContentSink_h_ +#define _nsContentSink_h_ + +// Base class for contentsink implementations. + +#include "mozilla/Attributes.h" +#include "nsICSSLoaderObserver.h" +#include "nsWeakReference.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsGkAtoms.h" +#include "nsITimer.h" +#include "nsStubDocumentObserver.h" +#include "nsIContentSink.h" +#include "mozilla/Logging.h" +#include "nsCycleCollectionParticipant.h" +#include "nsThreadUtils.h" +#include "mozilla/StaticPrefs_content.h" + +class nsIURI; +class nsIChannel; +class nsIDocShell; +class nsAtom; +class nsIChannel; +class nsIContent; +class nsNodeInfoManager; + +namespace mozilla { +namespace css { +class Loader; +} // namespace css + +namespace dom { +class Document; +class ScriptLoader; +} // namespace dom + +namespace net { +struct LinkHeader; +}; +} // namespace mozilla + +#ifdef DEBUG + +extern mozilla::LazyLogModule gContentSinkLogModuleInfo; + +# define SINK_TRACE_CALLS 0x1 +# define SINK_TRACE_REFLOW 0x2 +# define SINK_ALWAYS_REFLOW 0x4 + +# define SINK_LOG_TEST(_lm, _bit) (int((_lm)->Level()) & (_bit)) + +# define SINK_TRACE(_lm, _bit, _args) \ + do { \ + if (SINK_LOG_TEST(_lm, _bit)) { \ + printf_stderr _args; \ + } \ + } while (0) + +#else +# define SINK_TRACE(_lm, _bit, _args) +#endif + +#undef SINK_NO_INCREMENTAL + +//---------------------------------------------------------------------- + +class nsContentSink : public nsICSSLoaderObserver, + public nsSupportsWeakReference, + public nsStubDocumentObserver, + public nsITimerCallback, + public nsINamed { + protected: + using Document = mozilla::dom::Document; + + private: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink, nsICSSLoaderObserver) + // nsITimerCallback + NS_DECL_NSITIMERCALLBACK + + NS_DECL_NSINAMED + + // nsICSSLoaderObserver + NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred, + nsresult aStatus) override; + + // nsIContentSink implementation helpers + nsresult WillParseImpl(void); + nsresult WillInterruptImpl(void); + void WillResumeImpl(); + nsresult DidProcessATokenImpl(void); + void WillBuildModelImpl(void); + void DidBuildModelImpl(bool aTerminated); + void DropParserAndPerfHint(void); + bool IsScriptExecutingImpl(); + + void NotifyAppend(nsIContent* aContent, uint32_t aStartIndex); + + // nsIDocumentObserver + NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE + NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE + + virtual void UpdateChildCounts() = 0; + + bool IsTimeToNotify(); + + protected: + nsContentSink(); + virtual ~nsContentSink(); + + nsresult Init(Document* aDoc, nsIURI* aURI, nsISupports* aContainer, + nsIChannel* aChannel); + + nsresult ProcessHTTPHeaders(nsIChannel* aChannel); + // aEarlyHintPreloaderId zero means no early hint channel to connect back + nsresult ProcessLinkFromHeader(const mozilla::net::LinkHeader& aHeader, + uint64_t aEarlyHintPreloaderId); + + // @param aFetchPriority Accepts a case-insensitive fetch priority keyword and + // other values too, see + // . + virtual nsresult ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy, + const nsAString& aFetchPriority); + + void PrefetchHref(const nsAString& aHref, const nsAString& aAs, + const nsAString& aType, const nsAString& aMedia); + void PreloadHref(const nsAString& aHref, const nsAString& aAs, + const nsAString& aType, const nsAString& aMedia, + const nsAString& aNonce, const nsAString& aIntegrity, + const nsAString& aSrcset, const nsAString& aSizes, + const nsAString& aCORS, const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId, + const nsAString& aFetchPriority); + + void PreloadModule(const nsAString& aHref, const nsAString& aAs, + const nsAString& aMedia, const nsAString& aNonce, + const nsAString& aIntegrity, const nsAString& aCORS, + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId, + const nsAString& aFetchPriority); + + // For PrefetchDNS() aHref can either be the usual + // URI format or of the form "//www.hostname.com" without a scheme. + void PrefetchDNS(const nsAString& aHref); + + // Gets the cache key (used to identify items in a cache) of the channel. + nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey); + + public: + // For Preconnect() aHref can either be the usual + // URI format or of the form "//www.hostname.com" without a scheme. + void Preconnect(const nsAString& aHref, const nsAString& aCrossOrigin); + + protected: + // Tries to scroll to the URI's named anchor. Once we've successfully + // done that, further calls to this method will be ignored. + MOZ_CAN_RUN_SCRIPT_BOUNDARY void ScrollToRef(); + + // Start layout. If aIgnorePendingSheets is true, this will happen even if + // we still have stylesheet loads pending. Otherwise, we'll wait until the + // stylesheets are all done loading. + public: + void StartLayout(bool aIgnorePendingSheets); + + static void NotifyDocElementCreated(Document* aDoc); + + Document* GetDocument() { return mDocument; } + + // Later on we might want to make this more involved somehow + // (e.g. stop waiting after some timeout or whatnot). + bool WaitForPendingSheets() { return mPendingSheetCount > 0; } + + protected: + inline int32_t GetNotificationInterval() { + if (mDynamicLowerValue) { + return 1000; + } + + return mozilla::StaticPrefs::content_notify_interval(); + } + + virtual nsresult FlushTags() = 0; + + void DoProcessLinkHeader(); + + void StopDeflecting() { + mDeflectedCount = mozilla::StaticPrefs::content_sink_perf_deflect_count(); + } + + protected: + RefPtr mDocument; + RefPtr mParser; + nsCOMPtr mDocumentURI; + nsCOMPtr mDocShell; + RefPtr mCSSLoader; + RefPtr mNodeInfoManager; + RefPtr mScriptLoader; + + // back off timer notification after count + int32_t mBackoffCount; + + // Time of last notification + // Note: mLastNotificationTime is only valid once mLayoutStarted is true. + PRTime mLastNotificationTime; + + // Timer used for notification + nsCOMPtr mNotificationTimer; + + uint8_t mLayoutStarted : 1; + uint8_t mDynamicLowerValue : 1; + uint8_t mParsing : 1; + uint8_t mDroppedTimer : 1; + // If true, we deferred starting layout until sheets load + uint8_t mDeferredLayoutStart : 1; + // If true, we deferred notifications until sheets load + uint8_t mDeferredFlushTags : 1; + // If false, we're not ourselves a document observer; that means we + // shouldn't be performing any more content model notifications, + // since we're not longer updating our child counts. + uint8_t mIsDocumentObserver : 1; + // True if this is parser is a fragment parser or an HTML DOMParser. + // XML DOMParser leaves this to false for now! + uint8_t mRunsToCompletion : 1; + // True if we are blocking load event. + bool mIsBlockingOnload : 1; + + // + // -- Can interrupt parsing members -- + // + + // The number of tokens that have been processed since we measured + // if it's time to return to the main event loop. + uint32_t mDeflectedCount; + + // Is there currently a pending event? + bool mHasPendingEvent; + + // When to return to the main event loop + uint32_t mCurrentParseEndTime; + + int32_t mBeginLoadTime; + + // Last mouse event or keyboard event time sampled by the content + // sink + uint32_t mLastSampledUserEventTime; + + int32_t mInMonolithicContainer; + + int32_t mInNotification; + uint32_t mUpdatesInNotification; + + uint32_t mPendingSheetCount; + + nsRevocableEventPtr > + mProcessLinkHeaderEvent; +}; + +#endif // _nsContentSink_h_ diff --git a/dom/base/nsContentTypeParser.cpp b/dom/base/nsContentTypeParser.cpp new file mode 100644 index 0000000000..14d07fc038 --- /dev/null +++ b/dom/base/nsContentTypeParser.cpp @@ -0,0 +1,28 @@ +/* -*- 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 "nsContentTypeParser.h" +#include "nsContentUtils.h" +#include "nsNetUtil.h" + +using namespace mozilla; + +nsContentTypeParser::nsContentTypeParser(const nsAString& aString) + : mString(aString) {} + +nsresult nsContentTypeParser::GetParameter(const char* aParameterName, + nsAString& aResult) const { + return net::GetParameterHTTP(mString, aParameterName, aResult); +} + +nsresult nsContentTypeParser::GetType(nsAString& aResult) const { + nsresult rv = GetParameter(nullptr, aResult); + if (NS_FAILED(rv)) { + return rv; + } + nsContentUtils::ASCIIToLower(aResult); + return NS_OK; +} diff --git a/dom/base/nsContentTypeParser.h b/dom/base/nsContentTypeParser.h new file mode 100644 index 0000000000..27184ad2ee --- /dev/null +++ b/dom/base/nsContentTypeParser.h @@ -0,0 +1,23 @@ +/* -*- 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 nsContentTypeParser_h +#define nsContentTypeParser_h + +#include "nsString.h" + +class nsContentTypeParser { + public: + explicit nsContentTypeParser(const nsAString& aString); + + nsresult GetParameter(const char* aParameterName, nsAString& aResult) const; + nsresult GetType(nsAString& aResult) const; + + private: + NS_ConvertUTF16toUTF8 mString; +}; + +#endif diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp new file mode 100644 index 0000000000..d849b13927 --- /dev/null +++ b/dom/base/nsContentUtils.cpp @@ -0,0 +1,11471 @@ +/* -*- 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/. */ + +/* A namespace class for static layout utilities. */ + +#include "nsContentUtils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "BrowserChild.h" +#include "DecoderTraits.h" +#include "ErrorList.h" +#include "HTMLSplitOnSpacesTokenizer.h" +#include "ImageOps.h" +#include "InProcessBrowserChildMessageManager.h" +#include "MainThreadUtils.h" +#include "PLDHashTable.h" +#include "ReferrerInfo.h" +#include "ScopedNSSTypes.h" +#include "ThirdPartyUtil.h" +#include "Units.h" +#include "chrome/common/ipc_message.h" +#include "gfxDrawable.h" +#include "harfbuzz/hb.h" +#include "imgICache.h" +#include "imgIContainer.h" +#include "imgILoader.h" +#include "imgIRequest.h" +#include "imgLoader.h" +#include "js/Array.h" +#include "js/ArrayBuffer.h" +#include "js/BuildId.h" +#include "js/GCAPI.h" +#include "js/Id.h" +#include "js/JSON.h" +#include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty +#include "js/PropertyDescriptor.h" +#include "js/Realm.h" +#include "js/RegExp.h" +#include "js/RegExpFlags.h" +#include "js/RootingAPI.h" +#include "js/TypeDecls.h" +#include "js/Value.h" +#include "js/Wrapper.h" +#include "jsapi.h" +#include "jsfriendapi.h" +#include "mozAutoDocUpdate.h" +#include "mozIDOMWindow.h" +#include "nsIOService.h" +#include "nsObjectLoadingContent.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/ArrayIterator.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/AsyncEventDispatcher.h" +#include "mozilla/AtomArray.h" +#include "mozilla/Atomics.h" +#include "mozilla/Attributes.h" +#include "mozilla/AutoRestore.h" +#include "mozilla/BackgroundHangMonitor.h" +#include "mozilla/Base64.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/BloomFilter.h" +#include "mozilla/CORSMode.h" +#include "mozilla/CallState.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Components.h" +#include "mozilla/ContentBlockingAllowList.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/EventQueue.h" +#include "mozilla/EventStateManager.h" +#include "mozilla/FlushType.h" +#include "mozilla/FOGIPC.h" +#include "mozilla/HTMLEditor.h" +#include "mozilla/HangAnnotations.h" +#include "mozilla/IMEStateManager.h" +#include "mozilla/InputEventOptions.h" +#include "mozilla/InternalMutationEvent.h" +#include "mozilla/Latin1.h" +#include "mozilla/Likely.h" +#include "mozilla/LoadInfo.h" +#include "mozilla/Logging.h" +#include "mozilla/MacroForEach.h" +#include "mozilla/ManualNAC.h" +#include "mozilla/Maybe.h" +#include "mozilla/MediaFeatureChange.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/NotNull.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/OriginAttributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/PresShell.h" +#include "mozilla/ProfilerRunnable.h" +#include "mozilla/RangeBoundary.h" +#include "mozilla/RefPtr.h" +#include "mozilla/Result.h" +#include "mozilla/ResultExtensions.h" +#include "mozilla/ScrollbarPreferences.h" +#include "mozilla/ShutdownPhase.h" +#include "mozilla/Span.h" +#include "mozilla/StaticAnalysisFunctions.h" +#include "mozilla/StaticPrefs_browser.h" +#include "mozilla/StaticPrefs_dom.h" +#ifdef FUZZING +# include "mozilla/StaticPrefs_fuzzing.h" +#endif +#include "mozilla/StaticPrefs_nglayout.h" +#include "mozilla/StaticPrefs_privacy.h" +#include "mozilla/StaticPrefs_test.h" +#include "mozilla/StaticPrefs_ui.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/TextControlState.h" +#include "mozilla/TextEditor.h" +#include "mozilla/TextEvents.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/Unused.h" +#include "mozilla/Variant.h" +#include "mozilla/ViewportUtils.h" +#include "mozilla/dom/AncestorIterator.h" +#include "mozilla/dom/AutoEntryScript.h" +#include "mozilla/dom/AutocompleteInfoBinding.h" +#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/BlobImpl.h" +#include "mozilla/dom/BlobURLProtocolHandler.h" +#include "mozilla/dom/BorrowedAttrInfo.h" +#include "mozilla/dom/BrowserBridgeParent.h" +#include "mozilla/dom/BrowserParent.h" +#include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/BrowsingContextGroup.h" +#include "mozilla/dom/CallbackFunction.h" +#include "mozilla/dom/CallbackObject.h" +#include "mozilla/dom/ChromeMessageBroadcaster.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/ContentFrameMessageManager.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/CustomElementRegistry.h" +#include "mozilla/dom/CustomElementRegistryBinding.h" +#include "mozilla/dom/CustomElementTypes.h" +#include "mozilla/dom/DOMArena.h" +#include "mozilla/dom/DOMException.h" +#include "mozilla/dom/DOMExceptionBinding.h" +#include "mozilla/dom/DOMSecurityMonitor.h" +#include "mozilla/dom/DOMTypes.h" +#include "mozilla/dom/DataTransfer.h" +#include "mozilla/dom/DocGroup.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DocumentInlines.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/ElementInlines.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/EventTarget.h" +#include "mozilla/dom/FileBlobImpl.h" +#include "mozilla/dom/FileSystemSecurity.h" +#include "mozilla/dom/FilteredNodeIterator.h" +#include "mozilla/dom/FormData.h" +#include "mozilla/dom/FragmentOrElement.h" +#include "mozilla/dom/FromParser.h" +#include "mozilla/dom/HTMLElement.h" +#include "mozilla/dom/HTMLFormElement.h" +#include "mozilla/dom/HTMLImageElement.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/HTMLTextAreaElement.h" +#include "mozilla/dom/IPCBlob.h" +#include "mozilla/dom/IPCBlobUtils.h" +#include "mozilla/dom/MessageBroadcaster.h" +#include "mozilla/dom/MessageListenerManager.h" +#include "mozilla/dom/MessagePort.h" +#include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/dom/NameSpaceConstants.h" +#include "mozilla/dom/NodeBinding.h" +#include "mozilla/dom/NodeInfo.h" +#include "mozilla/dom/PBrowser.h" +#include "mozilla/dom/PContentChild.h" +#include "mozilla/dom/PrototypeList.h" +#include "mozilla/dom/ReferrerPolicyBinding.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/Selection.h" +#include "mozilla/dom/ShadowRoot.h" +#include "mozilla/dom/Text.h" +#include "mozilla/dom/UserActivation.h" +#include "mozilla/dom/WindowContext.h" +#include "mozilla/dom/WorkerCommon.h" +#include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/dom/WorkerRunnable.h" +#include "mozilla/dom/XULCommandEvent.h" +#include "mozilla/glean/GleanPings.h" +#include "mozilla/fallible.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/BaseMargin.h" +#include "mozilla/gfx/BasePoint.h" +#include "mozilla/gfx/BaseSize.h" +#include "mozilla/gfx/DataSurfaceHelpers.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/gfx/Types.h" +#include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/net/UrlClassifierCommon.h" +#include "mozilla/Tokenizer.h" +#include "mozilla/widget/IMEData.h" +#include "nsAboutProtocolUtils.h" +#include "nsAlgorithm.h" +#include "nsArrayUtils.h" +#include "nsAtomHashKeys.h" +#include "nsAttrName.h" +#include "nsAttrValue.h" +#include "nsAttrValueInlines.h" +#include "nsBaseHashtable.h" +#include "nsCCUncollectableMarker.h" +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include "nsCRTGlue.h" +#include "nsCanvasFrame.h" +#include "nsCaseTreatment.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsCharTraits.h" +#include "nsCompatibility.h" +#include "nsComponentManagerUtils.h" +#include "nsContainerFrame.h" +#include "nsContentCreatorFunctions.h" +#include "nsContentDLF.h" +#include "nsContentList.h" +#include "nsContentListDeclarations.h" +#include "nsContentPolicyUtils.h" +#include "nsCoord.h" +#include "nsCycleCollectionNoteChild.h" +#include "nsDOMMutationObserver.h" +#include "nsDOMString.h" +#include "nsTHashMap.h" +#include "nsDebug.h" +#include "nsDocShell.h" +#include "nsDocShellCID.h" +#include "nsError.h" +#include "nsFocusManager.h" +#include "nsFrameList.h" +#include "nsFrameLoader.h" +#include "nsFrameLoaderOwner.h" +#include "nsGenericHTMLElement.h" +#include "nsGkAtoms.h" +#include "nsGlobalWindowInner.h" +#include "nsGlobalWindowOuter.h" +#include "nsHTMLDocument.h" +#include "nsHTMLTags.h" +#include "nsHashKeys.h" +#include "nsHtml5StringParser.h" +#include "nsIAboutModule.h" +#include "nsIAnonymousContentCreator.h" +#include "nsIAppShell.h" +#include "nsIArray.h" +#include "nsIAsyncVerifyRedirectCallback.h" +#include "nsIBidiKeyboard.h" +#include "nsIBrowser.h" +#include "nsICacheInfoChannel.h" +#include "nsICategoryManager.h" +#include "nsIChannel.h" +#include "nsIChannelEventSink.h" +#include "nsIClassifiedChannel.h" +#include "nsIConsoleService.h" +#include "nsIContent.h" +#include "nsIContentInlines.h" +#include "nsIContentPolicy.h" +#include "nsIContentSecurityPolicy.h" +#include "nsIContentSink.h" +#include "nsIDOMWindowUtils.h" +#include "nsIDocShell.h" +#include "nsIDocShellTreeItem.h" +#include "nsIDocumentEncoder.h" +#include "nsIDocumentLoaderFactory.h" +#include "nsIDocumentViewer.h" +#include "nsIDragService.h" +#include "nsIDragSession.h" +#include "nsIFile.h" +#include "nsIFocusManager.h" +#include "nsIFormControl.h" +#include "nsIFragmentContentSink.h" +#include "nsIFrame.h" +#include "nsIGlobalObject.h" +#include "nsIHttpChannel.h" +#include "nsIHttpChannelInternal.h" +#include "nsIIOService.h" +#include "nsIImageLoadingContent.h" +#include "nsIInputStream.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsILoadContext.h" +#include "nsILoadGroup.h" +#include "nsILoadInfo.h" +#include "nsIMIMEService.h" +#include "nsIMemoryReporter.h" +#include "nsINetUtil.h" +#include "nsINode.h" +#include "nsIObjectLoadingContent.h" +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsIParserUtils.h" +#include "nsIPermissionManager.h" +#include "nsIPrincipal.h" +#include "nsIProperties.h" +#include "nsIProtocolHandler.h" +#include "nsIRequest.h" +#include "nsIRunnable.h" +#include "nsIScreen.h" +#include "nsIScriptError.h" +#include "nsIScriptGlobalObject.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIScriptSecurityManager.h" +#include "nsISerialEventTarget.h" +#include "nsIStreamConverter.h" +#include "nsIStreamConverterService.h" +#include "nsIStringBundle.h" +#include "nsISupports.h" +#include "nsISupportsPrimitives.h" +#include "nsISupportsUtils.h" +#include "nsITransferable.h" +#include "nsIURI.h" +#include "nsIURIMutator.h" +#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) +# include "nsIURIWithSpecialOrigin.h" +#endif +#include "nsIUserIdleServiceInternal.h" +#include "nsIWeakReferenceUtils.h" +#include "nsIWebNavigation.h" +#include "nsIWebNavigationInfo.h" +#include "nsIWidget.h" +#include "nsIWindowMediator.h" +#include "nsIXPConnect.h" +#include "nsJSPrincipals.h" +#include "nsJSUtils.h" +#include "nsLayoutUtils.h" +#include "nsLiteralString.h" +#include "nsMargin.h" +#include "nsMimeTypes.h" +#include "nsNameSpaceManager.h" +#include "nsNetCID.h" +#include "nsNetUtil.h" +#include "nsNodeInfoManager.h" +#include "nsPIDOMWindow.h" +#include "nsPIDOMWindowInlines.h" +#include "nsParser.h" +#include "nsParserConstants.h" +#include "nsPoint.h" +#include "nsPointerHashKeys.h" +#include "nsPresContext.h" +#include "nsQueryFrame.h" +#include "nsQueryObject.h" +#include "nsRange.h" +#include "nsRefPtrHashtable.h" +#include "nsSandboxFlags.h" +#include "nsScriptSecurityManager.h" +#include "nsServiceManagerUtils.h" +#include "nsStreamUtils.h" +#include "nsString.h" +#include "nsStringBuffer.h" +#include "nsStringBundle.h" +#include "nsStringFlags.h" +#include "nsStringFwd.h" +#include "nsStringIterator.h" +#include "nsStringStream.h" +#include "nsTArray.h" +#include "nsTLiteralString.h" +#include "nsTPromiseFlatString.h" +#include "nsTStringRepr.h" +#include "nsTextFragment.h" +#include "nsTextNode.h" +#include "nsThreadManager.h" +#include "nsThreadUtils.h" +#include "nsTreeSanitizer.h" +#include "nsUGenCategory.h" +#include "nsURLHelper.h" +#include "nsUnicodeProperties.h" +#include "nsVariant.h" +#include "nsWidgetsCID.h" +#include "nsView.h" +#include "nsViewManager.h" +#include "nsXPCOM.h" +#include "nsXPCOMCID.h" +#include "nsXULAppAPI.h" +#include "nsXULElement.h" +#include "nsXULPopupManager.h" +#include "nscore.h" +#include "prinrval.h" +#include "xpcprivate.h" +#include "xpcpublic.h" + +#if defined(XP_WIN) +// Undefine LoadImage to prevent naming conflict with Windows. +# undef LoadImage +#endif + +extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end, + const char** next, char16_t* result); +extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware, + const char** colon); + +using namespace mozilla::dom; +using namespace mozilla::ipc; +using namespace mozilla::gfx; +using namespace mozilla::layers; +using namespace mozilla::widget; +using namespace mozilla; + +const char kLoadAsData[] = "loadAsData"; + +nsIXPConnect* nsContentUtils::sXPConnect; +nsIScriptSecurityManager* nsContentUtils::sSecurityManager; +nsIPrincipal* nsContentUtils::sSystemPrincipal; +nsIPrincipal* nsContentUtils::sNullSubjectPrincipal; +nsIConsoleService* nsContentUtils::sConsoleService; + +static nsTHashMap, EventNameMapping>* sAtomEventTable; +static nsTHashMap* sStringEventTable; +static nsTArray>* sUserDefinedEvents; +nsIStringBundleService* nsContentUtils::sStringBundleService; + +static StaticRefPtr + sStringBundles[nsContentUtils::PropertiesFile_COUNT]; + +nsIContentPolicy* nsContentUtils::sContentPolicyService; +bool nsContentUtils::sTriedToGetContentPolicy = false; +StaticRefPtr nsContentUtils::sBidiKeyboard; +uint32_t nsContentUtils::sScriptBlockerCount = 0; +uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0; +AutoTArray, 8>* nsContentUtils::sBlockedScriptRunners = + nullptr; +uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0; +nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr; + +bool nsContentUtils::sIsHandlingKeyBoardEvent = false; + +nsString* nsContentUtils::sShiftText = nullptr; +nsString* nsContentUtils::sControlText = nullptr; +nsString* nsContentUtils::sCommandOrWinText = nullptr; +nsString* nsContentUtils::sAltText = nullptr; +nsString* nsContentUtils::sModifierSeparator = nullptr; + +bool nsContentUtils::sInitialized = false; +#ifndef RELEASE_OR_BETA +bool nsContentUtils::sBypassCSSOMOriginCheck = false; +#endif + +nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr; +nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr; + +nsContentUtils::UserInteractionObserver* + nsContentUtils::sUserInteractionObserver = nullptr; + +nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr; +nsParser* nsContentUtils::sXMLFragmentParser = nullptr; +nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr; +bool nsContentUtils::sFragmentParsingActive = false; + +bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false; +bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false; + +mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog( + "nsResistFingerprinting"); +mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump"); + +int32_t nsContentUtils::sInnerOrOuterWindowCount = 0; +uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0; + +template Maybe nsContentUtils::ComparePoints( + const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary); +template Maybe nsContentUtils::ComparePoints( + const RangeBoundary& aFirstBoundary, + const RawRangeBoundary& aSecondBoundary); +template Maybe nsContentUtils::ComparePoints( + const RawRangeBoundary& aFirstBoundary, + const RangeBoundary& aSecondBoundary); +template Maybe nsContentUtils::ComparePoints( + const RawRangeBoundary& aFirstBoundary, + const RawRangeBoundary& aSecondBoundary); + +template int32_t nsContentUtils::ComparePoints_Deprecated( + const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary, + bool* aDisconnected); +template int32_t nsContentUtils::ComparePoints_Deprecated( + const RangeBoundary& aFirstBoundary, + const RawRangeBoundary& aSecondBoundary, bool* aDisconnected); +template int32_t nsContentUtils::ComparePoints_Deprecated( + const RawRangeBoundary& aFirstBoundary, + const RangeBoundary& aSecondBoundary, bool* aDisconnected); +template int32_t nsContentUtils::ComparePoints_Deprecated( + const RawRangeBoundary& aFirstBoundary, + const RawRangeBoundary& aSecondBoundary, bool* aDisconnected); + +// Subset of +// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name +enum AutocompleteUnsupportedFieldName : uint8_t { +#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ + eAutocompleteUnsupportedFieldName_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME +}; + +enum AutocompleteNoPersistFieldName : uint8_t { +#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ + eAutocompleteNoPersistFieldName_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME +}; + +enum AutocompleteUnsupportFieldContactHint : uint8_t { +#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ + eAutocompleteUnsupportedFieldContactHint_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT +}; + +enum AutocompleteFieldName : uint8_t { +#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_, +#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ + AUTOCOMPLETE_FIELD_NAME(name_, value_) +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_NAME +#undef AUTOCOMPLETE_CONTACT_FIELD_NAME +}; + +enum AutocompleteFieldHint : uint8_t { +#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_HINT +}; + +enum AutocompleteFieldContactHint : uint8_t { +#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ + eAutocompleteFieldContactHint_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_CONTACT_HINT +}; + +enum AutocompleteCredentialType : uint8_t { +#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ + eAutocompleteCredentialType_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_CREDENTIAL_TYPE +}; + +enum AutocompleteCategory { +#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_CATEGORY +}; + +static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = { +#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ + {value_, eAutocompleteUnsupportedFieldName_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = { +#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ + {value_, eAutocompleteNoPersistFieldName_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME + {nullptr, 0}}; + +static const nsAttrValue::EnumTable + kAutocompleteUnsupportedContactFieldHintTable[] = { +#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ + {value_, eAutocompleteUnsupportedFieldContactHint_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = { +#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \ + {value_, eAutocompleteFieldName_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_NAME + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = { +#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ + {value_, eAutocompleteFieldName_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_CONTACT_FIELD_NAME + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = { +#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \ + {value_, eAutocompleteFieldHint_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_HINT + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = { +#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ + {value_, eAutocompleteFieldContactHint_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_FIELD_CONTACT_HINT + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = { +#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ + {value_, eAutocompleteCredentialType_##name_}, +#include "AutocompleteFieldList.h" +#undef AUTOCOMPLETE_CREDENTIAL_TYPE + {nullptr, 0}}; + +namespace { + +static PLDHashTable* sEventListenerManagersHash; + +// A global hashtable to for keeping the arena alive for cross docGroup node +// adoption. +static nsRefPtrHashtable, mozilla::dom::DOMArena>* + sDOMArenaHashtable; + +class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter { + MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) + + ~DOMEventListenerManagersHashReporter() = default; + + public: + NS_DECL_ISUPPORTS + + NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, bool aAnonymize) override { + // We don't measure the |EventListenerManager| objects pointed to by the + // entries because those references are non-owning. + int64_t amount = + sEventListenerManagersHash + ? sEventListenerManagersHash->ShallowSizeOfIncludingThis( + MallocSizeOf) + : 0; + + MOZ_COLLECT_REPORT( + "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES, + amount, "Memory used by the event listener manager's hash table."); + + return NS_OK; + } +}; + +NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter) + +class EventListenerManagerMapEntry : public PLDHashEntryHdr { + public: + explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {} + + ~EventListenerManagerMapEntry() { + NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM"); + } + + protected: // declared protected to silence clang warnings + const void* mKey; // must be first, to look like PLDHashEntryStub + + public: + RefPtr mListenerManager; +}; + +static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry, + const void* key) { + // Initialize the entry with placement new + new (entry) EventListenerManagerMapEntry(key); +} + +static void EventListenerManagerHashClearEntry(PLDHashTable* table, + PLDHashEntryHdr* entry) { + EventListenerManagerMapEntry* lm = + static_cast(entry); + + // Let the EventListenerManagerMapEntry clean itself up... + lm->~EventListenerManagerMapEntry(); +} + +class SameOriginCheckerImpl final : public nsIChannelEventSink, + public nsIInterfaceRequestor { + ~SameOriginCheckerImpl() = default; + + NS_DECL_ISUPPORTS + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIINTERFACEREQUESTOR +}; + +} // namespace + +void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) { + // Note: Document::SuppressEventHandling will also automatically suppress + // event handling for any in-process sub-documents. However, since we need + // to deal with cases where remote BrowsingContexts may be interleaved + // with in-process ones, we still need to walk the entire tree ourselves. + // This may be slightly redundant in some cases, but since event handling + // suppressions maintain a count of current blockers, it does not cause + // any problems. + aDoc->SuppressEventHandling(); +} + +void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) { + aDoc->UnsuppressEventHandlingAndFireEvents(true); +} + +AutoSuppressEventHandling::~AutoSuppressEventHandling() { + UnsuppressDocuments(); +} + +void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) { + AutoSuppressEventHandling::SuppressDocument(aDoc); + if (nsCOMPtr win = aDoc->GetInnerWindow()) { + win->Suspend(); + mWindows.AppendElement(win); + } +} + +AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() { + for (const auto& win : mWindows) { + win->Resume(); + } +} + +/** + * This class is used to determine whether or not the user is currently + * interacting with the browser. It listens to observer events to toggle the + * value of the sUserActive static. + * + * This class is an internal implementation detail. + * nsContentUtils::GetUserIsInteracting() should be used to access current + * user interaction status. + */ +class nsContentUtils::UserInteractionObserver final + : public nsIObserver, + public BackgroundHangAnnotator { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + void Init(); + void Shutdown(); + void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override; + + static Atomic sUserActive; + + private: + ~UserInteractionObserver() = default; +}; + +static constexpr nsLiteralCString kRfpPrefs[] = { + "privacy.resistFingerprinting"_ns, + "privacy.resistFingerprinting.pbmode"_ns, + "privacy.fingerprintingProtection"_ns, + "privacy.fingerprintingProtection.pbmode"_ns, + "privacy.fingerprintingProtection.overrides"_ns, +}; + +static void RecomputeResistFingerprintingAllDocs(const char*, void*) { + AutoTArray, 5> bcGroups; + BrowsingContextGroup::GetAllGroups(bcGroups); + for (auto& bcGroup : bcGroups) { + AutoTArray docGroups; + bcGroup->GetDocGroups(docGroups); + for (auto* docGroup : docGroups) { + for (Document* doc : *docGroup) { + if (doc->RecomputeResistFingerprinting()) { + if (auto* pc = doc->GetPresContext()) { + pc->MediaFeatureValuesChanged( + {MediaFeatureChangeReason::PreferenceChange}, + MediaFeatureChangePropagation::JustThisDocument); + } + } + } + } + } +} + +// static +nsresult nsContentUtils::Init() { + if (sInitialized) { + NS_WARNING("Init() called twice"); + + return NS_OK; + } + + nsHTMLTags::AddRefTable(); + + sXPConnect = nsXPConnect::XPConnect(); + // We hold a strong ref to sXPConnect to ensure that it does not go away until + // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be + // triggered by xpcModuleDtor late in shutdown and cause crashes due to + // various stuff already being torn down by then. Note that this means that + // we are effectively making sure that if we leak nsLayoutStatics then we also + // leak nsXPConnect. + NS_ADDREF(sXPConnect); + + sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager(); + if (!sSecurityManager) return NS_ERROR_FAILURE; + NS_ADDREF(sSecurityManager); + + sSecurityManager->GetSystemPrincipal(&sSystemPrincipal); + MOZ_ASSERT(sSystemPrincipal); + + RefPtr nullPrincipal = + NullPrincipal::CreateWithoutOriginAttributes(); + if (!nullPrincipal) { + return NS_ERROR_FAILURE; + } + + nullPrincipal.forget(&sNullSubjectPrincipal); + + if (!InitializeEventTable()) return NS_ERROR_FAILURE; + + if (!sEventListenerManagersHash) { + static const PLDHashTableOps hash_table_ops = { + PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub, + PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry, + EventListenerManagerHashInitEntry}; + + sEventListenerManagersHash = + new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry)); + + RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter()); + } + + sBlockedScriptRunners = new AutoTArray, 8>; + +#ifndef RELEASE_OR_BETA + sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK"); +#endif + + Element::InitCCCallbacks(); + + RefPtr rfpService = nsRFPService::GetOrCreate(); + MOZ_ASSERT(rfpService); + + if (XRE_IsParentProcess()) { + AsyncPrecreateStringBundles(); + +#if defined(MOZ_WIDGET_ANDROID) + // On Android, at-shutdown ping submission isn't reliable + // (( because, on Android, we usually get killed, not shut down )). + // To have a chance at submitting the ping, aim for idle after startup. + nsresult rv = NS_DispatchToCurrentThreadQueue( + NS_NewRunnableFunction( + "AndroidUseCounterPingSubmitter", + []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }), + EventQueuePriority::Idle); + // This is mostly best-effort, so if it goes awry, just log. + Unused << NS_WARN_IF(NS_FAILED(rv)); +#endif // defined(MOZ_WIDGET_ANDROID) + + RunOnShutdown( + [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); }, + ShutdownPhase::AppShutdownConfirmed); + } + + RefPtr uio = new UserInteractionObserver(); + uio->Init(); + uio.forget(&sUserInteractionObserver); + + for (const auto& pref : kRfpPrefs) { + Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref); + } + + sInitialized = true; + + return NS_OK; +} + +bool nsContentUtils::InitJSBytecodeMimeType() { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!sJSScriptBytecodeMimeType); + MOZ_ASSERT(!sJSModuleBytecodeMimeType); + + JS::BuildIdCharVector jsBuildId; + if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) { + return false; + } + + nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length()); + sJSScriptBytecodeMimeType = + new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr); + sJSModuleBytecodeMimeType = + new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr); + return true; +} + +void nsContentUtils::GetShiftText(nsAString& text) { + if (!sShiftText) InitializeModifierStrings(); + text.Assign(*sShiftText); +} + +void nsContentUtils::GetControlText(nsAString& text) { + if (!sControlText) InitializeModifierStrings(); + text.Assign(*sControlText); +} + +void nsContentUtils::GetCommandOrWinText(nsAString& text) { + if (!sCommandOrWinText) { + InitializeModifierStrings(); + } + text.Assign(*sCommandOrWinText); +} + +void nsContentUtils::GetAltText(nsAString& text) { + if (!sAltText) InitializeModifierStrings(); + text.Assign(*sAltText); +} + +void nsContentUtils::GetModifierSeparatorText(nsAString& text) { + if (!sModifierSeparator) InitializeModifierStrings(); + text.Assign(*sModifierSeparator); +} + +void nsContentUtils::InitializeModifierStrings() { + // load the display strings for the keyboard accelerators + nsCOMPtr bundleService = + mozilla::components::StringBundle::Service(); + nsCOMPtr bundle; + DebugOnly rv = NS_OK; + if (bundleService) { + rv = bundleService->CreateBundle( + "chrome://global-platform/locale/platformKeys.properties", + getter_AddRefs(bundle)); + } + + NS_ASSERTION( + NS_SUCCEEDED(rv) && bundle, + "chrome://global/locale/platformKeys.properties could not be loaded"); + nsAutoString shiftModifier; + nsAutoString commandOrWinModifier; + nsAutoString altModifier; + nsAutoString controlModifier; + nsAutoString modifierSeparator; + if (bundle) { + // macs use symbols for each modifier key, so fetch each from the bundle, + // which also covers i18n + bundle->GetStringFromName("VK_SHIFT", shiftModifier); + bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier); + bundle->GetStringFromName("VK_ALT", altModifier); + bundle->GetStringFromName("VK_CONTROL", controlModifier); + bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator); + } + // if any of these don't exist, we get an empty string + sShiftText = new nsString(shiftModifier); + sCommandOrWinText = new nsString(commandOrWinModifier); + sAltText = new nsString(altModifier); + sControlText = new nsString(controlModifier); + sModifierSeparator = new nsString(modifierSeparator); +} + +mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage( + EventMessage aEventMessage) { + switch (aEventMessage) { +#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ + case message_: \ + return struct_; +#include "mozilla/EventNameList.h" +#undef MESSAGE_TO_EVENT + default: + MOZ_ASSERT_UNREACHABLE("Invalid event message?"); + return eBasicEventClass; + } +} + +bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) { + bool doesNotReturnData = false; + nsresult rv = NS_URIChainHasFlags( + aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData); + return NS_SUCCEEDED(rv) && doesNotReturnData; +} + +/* static */ +nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) { + switch (aEventMessage) { +#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ + case message_: \ + return nsGkAtoms::on##name_; +#include "mozilla/EventNameList.h" +#undef MESSAGE_TO_EVENT + default: + return nullptr; + } +} + +bool nsContentUtils::InitializeEventTable() { + NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!"); + NS_ASSERTION(!sStringEventTable, "EventTable already initialized!"); + + static const EventNameMapping eventArray[] = { +#define EVENT(name_, _message, _type, _class) \ + {nsGkAtoms::on##name_, _type, _message, _class}, +#define WINDOW_ONLY_EVENT EVENT +#define DOCUMENT_ONLY_EVENT EVENT +#define NON_IDL_EVENT EVENT +#include "mozilla/EventNameList.h" +#undef WINDOW_ONLY_EVENT +#undef NON_IDL_EVENT +#undef EVENT + {nullptr}}; + + sAtomEventTable = + new nsTHashMap, EventNameMapping>(ArrayLength(eventArray)); + sStringEventTable = new nsTHashMap( + ArrayLength(eventArray)); + sUserDefinedEvents = new nsTArray>(64); + + // Subtract one from the length because of the trailing null + for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) { + MOZ_ASSERT(!sAtomEventTable->Contains(eventArray[i].mAtom), + "Double-defining event name; fix your EventNameList.h"); + sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]); + sStringEventTable->InsertOrUpdate( + Substring(nsDependentAtomString(eventArray[i].mAtom), 2), + eventArray[i]); + } + + return true; +} + +void nsContentUtils::InitializeTouchEventTable() { + static bool sEventTableInitialized = false; + if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) { + sEventTableInitialized = true; + static const EventNameMapping touchEventArray[] = { +#define EVENT(name_, _message, _type, _class) +#define TOUCH_EVENT(name_, _message, _type, _class) \ + {nsGkAtoms::on##name_, _type, _message, _class}, +#include "mozilla/EventNameList.h" +#undef TOUCH_EVENT +#undef EVENT + {nullptr}}; + // Subtract one from the length because of the trailing null + for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) { + sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom, + touchEventArray[i]); + sStringEventTable->InsertOrUpdate( + Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2), + touchEventArray[i]); + } + } +} + +static bool Is8bit(const nsAString& aString) { + static const char16_t EIGHT_BIT = char16_t(~0x00FF); + + for (nsAString::const_char_iterator start = aString.BeginReading(), + end = aString.EndReading(); + start != end; ++start) { + if (*start & EIGHT_BIT) { + return false; + } + } + + return true; +} + +nsresult nsContentUtils::Btoa(const nsAString& aBinaryData, + nsAString& aAsciiBase64String) { + if (!Is8bit(aBinaryData)) { + aAsciiBase64String.Truncate(); + return NS_ERROR_DOM_INVALID_CHARACTER_ERR; + } + + return Base64Encode(aBinaryData, aAsciiBase64String); +} + +nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String, + nsAString& aBinaryData) { + if (!Is8bit(aAsciiBase64String)) { + aBinaryData.Truncate(); + return NS_ERROR_DOM_INVALID_CHARACTER_ERR; + } + + const char16_t* start = aAsciiBase64String.BeginReading(); + const char16_t* cur = start; + const char16_t* end = aAsciiBase64String.EndReading(); + bool hasWhitespace = false; + + while (cur < end) { + if (nsContentUtils::IsHTMLWhitespace(*cur)) { + hasWhitespace = true; + break; + } + cur++; + } + + nsresult rv; + + if (hasWhitespace) { + nsString trimmedString; + + if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) { + return NS_ERROR_DOM_INVALID_CHARACTER_ERR; + } + + trimmedString.Append(start, cur - start); + + while (cur < end) { + if (!nsContentUtils::IsHTMLWhitespace(*cur)) { + trimmedString.Append(*cur); + } + cur++; + } + rv = Base64Decode(trimmedString, aBinaryData); + } else { + rv = Base64Decode(aAsciiBase64String, aBinaryData); + } + + if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) { + return NS_ERROR_DOM_INVALID_CHARACTER_ERR; + } + return rv; +} + +bool nsContentUtils::IsAutocompleteEnabled( + mozilla::dom::HTMLInputElement* aInput) { + MOZ_ASSERT(aInput, "aInput should not be null!"); + + nsAutoString autocomplete; + aInput->GetAutocomplete(autocomplete); + + if (autocomplete.IsEmpty()) { + auto* form = aInput->GetForm(); + if (!form) { + return true; + } + + form->GetAutocomplete(autocomplete); + } + + return !autocomplete.EqualsLiteral("off"); +} + +nsContentUtils::AutocompleteAttrState +nsContentUtils::SerializeAutocompleteAttribute( + const nsAttrValue* aAttr, nsAString& aResult, + AutocompleteAttrState aCachedState) { + if (!aAttr || + aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { + return aCachedState; + } + + if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) { + uint32_t atomCount = aAttr->GetAtomCount(); + for (uint32_t i = 0; i < atomCount; i++) { + if (i != 0) { + aResult.Append(' '); + } + aResult.Append(nsDependentAtomString(aAttr->AtomAt(i))); + } + nsContentUtils::ASCIIToLower(aResult); + return aCachedState; + } + + aResult.Truncate(); + + mozilla::dom::AutocompleteInfo info; + AutocompleteAttrState state = + InternalSerializeAutocompleteAttribute(aAttr, info); + if (state == eAutocompleteAttrState_Valid) { + // Concatenate the info fields. + aResult = info.mSection; + + if (!info.mAddressType.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mAddressType; + } + + if (!info.mContactType.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mContactType; + } + + if (!info.mFieldName.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mFieldName; + } + + // The autocomplete attribute value "webauthn" is interpreted as both a + // field name and a credential type. The corresponding IDL-exposed autofill + // value is "webauthn", not "webauthn webauthn". + if (!info.mCredentialType.IsEmpty() && + !(info.mCredentialType.Equals(u"webauthn"_ns) && + info.mCredentialType.Equals(aResult))) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mCredentialType; + } + } + + return state; +} + +nsContentUtils::AutocompleteAttrState +nsContentUtils::SerializeAutocompleteAttribute( + const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo, + AutocompleteAttrState aCachedState, bool aGrantAllValidValue) { + if (!aAttr || + aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { + return aCachedState; + } + + return InternalSerializeAutocompleteAttribute(aAttr, aInfo, + aGrantAllValidValue); +} + +/** + * Helper to validate the @autocomplete tokens. + * + * @return {AutocompleteAttrState} The state of the attribute (invalid/valid). + */ +nsContentUtils::AutocompleteAttrState +nsContentUtils::InternalSerializeAutocompleteAttribute( + const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo, + bool aGrantAllValidValue) { + // No autocomplete attribute so we are done + if (!aAttrVal) { + return eAutocompleteAttrState_Invalid; + } + + uint32_t numTokens = aAttrVal->GetAtomCount(); + if (!numTokens || numTokens > INT32_MAX) { + return eAutocompleteAttrState_Invalid; + } + + uint32_t index = numTokens - 1; + nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); + AutocompleteCategory category; + nsAttrValue enumValue; + nsAutoString credentialTypeStr; + + bool result = enumValue.ParseEnumValue( + tokenString, kAutocompleteCredentialTypeTable, false); + if (result) { + if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) { + return eAutocompleteAttrState_Invalid; + } + enumValue.ToString(credentialTypeStr); + ASCIIToLower(credentialTypeStr); + // category is Credential and the indexth token is "webauthn" + if (index == 0) { + aInfo.mFieldName.Assign(credentialTypeStr); + aInfo.mCredentialType.Assign(credentialTypeStr); + return eAutocompleteAttrState_Valid; + } + + --index; + tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); + + // Only the Normal and Contact categories are allowed with webauthn + // - disallow Credential + if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable, + false)) { + return eAutocompleteAttrState_Invalid; + } + // - disallow Off and Automatic + if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, + false)) { + if (enumValue.Equals(u"off"_ns, eIgnoreCase) || + enumValue.Equals(u"on"_ns, eIgnoreCase)) { + return eAutocompleteAttrState_Invalid; + } + } + + // Proceed to process the remaining tokens as if "webauthn" was not present. + // We need to decrement numTokens to enforce the correct per-category limits + // on the maximum number of tokens. + --numTokens; + } + + bool unsupported = false; + if (!aGrantAllValidValue) { + unsupported = enumValue.ParseEnumValue( + tokenString, kAutocompleteUnsupportedFieldNameTable, false); + if (unsupported) { + return eAutocompleteAttrState_Invalid; + } + } + + nsAutoString fieldNameStr; + result = + enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false); + + if (result) { + // Off/Automatic/Normal categories. + if (enumValue.Equals(u"off"_ns, eIgnoreCase) || + enumValue.Equals(u"on"_ns, eIgnoreCase)) { + if (numTokens > 1) { + return eAutocompleteAttrState_Invalid; + } + enumValue.ToString(fieldNameStr); + ASCIIToLower(fieldNameStr); + aInfo.mFieldName.Assign(fieldNameStr); + aInfo.mCredentialType.Assign(credentialTypeStr); + aInfo.mCanAutomaticallyPersist = + !enumValue.Equals(u"off"_ns, eIgnoreCase); + return eAutocompleteAttrState_Valid; + } + + // Only allow on/off if form autofill @autocomplete values aren't enabled + // and it doesn't grant all valid values. + if (!StaticPrefs::dom_forms_autocomplete_formautofill() && + !aGrantAllValidValue) { + return eAutocompleteAttrState_Invalid; + } + + // Normal category + if (numTokens > 3) { + return eAutocompleteAttrState_Invalid; + } + category = eAutocompleteCategory_NORMAL; + } else { // Check if the last token is of the contact category instead. + // Only allow on/off if form autofill @autocomplete values aren't enabled + // and it doesn't grant all valid values. + if (!StaticPrefs::dom_forms_autocomplete_formautofill() && + !aGrantAllValidValue) { + return eAutocompleteAttrState_Invalid; + } + + result = enumValue.ParseEnumValue( + tokenString, kAutocompleteContactFieldNameTable, false); + if (!result || numTokens > 4) { + return eAutocompleteAttrState_Invalid; + } + + category = eAutocompleteCategory_CONTACT; + } + + enumValue.ToString(fieldNameStr); + ASCIIToLower(fieldNameStr); + + aInfo.mFieldName.Assign(fieldNameStr); + aInfo.mCredentialType.Assign(credentialTypeStr); + aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue( + tokenString, kAutocompleteNoPersistFieldNameTable, false); + + // We are done if this was the only token. + if (numTokens == 1) { + return eAutocompleteAttrState_Valid; + } + + --index; + tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); + + if (category == eAutocompleteCategory_CONTACT) { + if (!aGrantAllValidValue) { + unsupported = enumValue.ParseEnumValue( + tokenString, kAutocompleteUnsupportedContactFieldHintTable, false); + if (unsupported) { + return eAutocompleteAttrState_Invalid; + } + } + + nsAttrValue contactFieldHint; + result = contactFieldHint.ParseEnumValue( + tokenString, kAutocompleteContactFieldHintTable, false); + if (result) { + nsAutoString contactFieldHintString; + contactFieldHint.ToString(contactFieldHintString); + ASCIIToLower(contactFieldHintString); + aInfo.mContactType.Assign(contactFieldHintString); + if (index == 0) { + return eAutocompleteAttrState_Valid; + } + --index; + tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); + } + } + + // Check for billing/shipping tokens + nsAttrValue fieldHint; + if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, + false)) { + nsString fieldHintString; + fieldHint.ToString(fieldHintString); + ASCIIToLower(fieldHintString); + aInfo.mAddressType.Assign(fieldHintString); + if (index == 0) { + return eAutocompleteAttrState_Valid; + } + --index; + tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); + } + + // Check for section-* token + const nsDependentSubstring& section = Substring(tokenString, 0, 8); + if (section.LowerCaseEqualsASCII("section-")) { + ASCIIToLower(tokenString); + aInfo.mSection.Assign(tokenString); + if (index == 0) { + return eAutocompleteAttrState_Valid; + } + } + + // Clear the fields as the autocomplete attribute is invalid. + aInfo.mSection.Truncate(); + aInfo.mAddressType.Truncate(); + aInfo.mContactType.Truncate(); + aInfo.mFieldName.Truncate(); + aInfo.mCredentialType.Truncate(); + + return eAutocompleteAttrState_Invalid; +} + +// Parse an integer according to HTML spec +template +int32_t nsContentUtils::ParseHTMLIntegerImpl( + const CharT* aStart, const CharT* aEnd, + ParseHTMLIntegerResultFlags* aResult) { + int result = eParseHTMLInteger_NoFlags; + + const CharT* iter = aStart; + + while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) { + result |= eParseHTMLInteger_NonStandard; + ++iter; + } + + if (iter == aEnd) { + result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; + *aResult = (ParseHTMLIntegerResultFlags)result; + return 0; + } + + int sign = 1; + if (*iter == CharT('-')) { + sign = -1; + result |= eParseHTMLInteger_Negative; + ++iter; + } else if (*iter == CharT('+')) { + result |= eParseHTMLInteger_NonStandard; + ++iter; + } + + bool foundValue = false; + CheckedInt32 value = 0; + + // Check for leading zeros first. + uint64_t leadingZeros = 0; + while (iter != aEnd) { + if (*iter != CharT('0')) { + break; + } + + ++leadingZeros; + foundValue = true; + ++iter; + } + + while (iter != aEnd) { + if (*iter >= CharT('0') && *iter <= CharT('9')) { + value = (value * 10) + (*iter - CharT('0')) * sign; + ++iter; + if (!value.isValid()) { + result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow; + break; + } + foundValue = true; + } else { + break; + } + } + + if (!foundValue) { + result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; + } + + if (value.isValid() && + ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) || + (sign == -1 && value == 0))) { + result |= eParseHTMLInteger_NonStandard; + } + + if (iter != aEnd) { + result |= eParseHTMLInteger_DidNotConsumeAllInput; + } + + *aResult = (ParseHTMLIntegerResultFlags)result; + return value.isValid() ? value.value() : 0; +} + +// Parse an integer according to HTML spec +int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart, + const char16_t* aEnd, + ParseHTMLIntegerResultFlags* aResult) { + return ParseHTMLIntegerImpl(aStart, aEnd, aResult); +} + +int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd, + ParseHTMLIntegerResultFlags* aResult) { + return ParseHTMLIntegerImpl(aStart, aEnd, aResult); +} + +#define SKIP_WHITESPACE(iter, end_iter, end_res) \ + while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \ + ++(iter); \ + } \ + if ((iter) == (end_iter)) { \ + return (end_res); \ + } + +#define SKIP_ATTR_NAME(iter, end_iter) \ + while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \ + *(iter) != '=') { \ + ++(iter); \ + } + +bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, + nsAtom* aName, nsAString& aValue) { + aValue.Truncate(); + + const char16_t* start = aSource.get(); + const char16_t* end = start + aSource.Length(); + const char16_t* iter; + + while (start != end) { + SKIP_WHITESPACE(start, end, false) + iter = start; + SKIP_ATTR_NAME(iter, end) + + if (start == iter) { + return false; + } + + // Remember the attr name. + const nsDependentSubstring& attrName = Substring(start, iter); + + // Now check whether this is a valid name="value" pair. + start = iter; + SKIP_WHITESPACE(start, end, false) + if (*start != '=') { + // No '=', so this is not a name="value" pair. We don't know + // what it is, and we have no way to handle it. + return false; + } + + // Have to skip the value. + ++start; + SKIP_WHITESPACE(start, end, false) + char16_t q = *start; + if (q != kQuote && q != kApostrophe) { + // Not a valid quoted value, so bail. + return false; + } + + ++start; // Point to the first char of the value. + iter = start; + + while (iter != end && *iter != q) { + ++iter; + } + + if (iter == end) { + // Oops, unterminated quoted string. + return false; + } + + // At this point attrName holds the name of the "attribute" and + // the value is between start and iter. + + if (aName->Equals(attrName)) { + // We'll accumulate as many characters as possible (until we hit either + // the end of the string or the beginning of an entity). Chunks will be + // delimited by start and chunkEnd. + const char16_t* chunkEnd = start; + while (chunkEnd != iter) { + if (*chunkEnd == kLessThan) { + aValue.Truncate(); + + return false; + } + + if (*chunkEnd == kAmpersand) { + aValue.Append(start, chunkEnd - start); + + const char16_t* afterEntity = nullptr; + char16_t result[2]; + uint32_t count = MOZ_XMLTranslateEntity( + reinterpret_cast(chunkEnd), + reinterpret_cast(iter), + reinterpret_cast(&afterEntity), result); + if (count == 0) { + aValue.Truncate(); + + return false; + } + + aValue.Append(result, count); + + // Advance to after the entity and begin a new chunk. + start = chunkEnd = afterEntity; + } else { + ++chunkEnd; + } + } + + // Append remainder. + aValue.Append(start, iter - start); + + return true; + } + + // Resume scanning after the end of the attribute value (past the quote + // char). + start = iter + 1; + } + + return false; +} + +bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) { + // Create MIME type as "text/" + given input + nsAutoString mimeType(u"text/"); + mimeType.Append(aName); + + return IsJavascriptMIMEType(mimeType); +} + +void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType, + nsString& aParams) { + aType.Truncate(); + aParams.Truncate(); + int32_t semiIndex = aValue.FindChar(char16_t(';')); + if (-1 != semiIndex) { + aType = Substring(aValue, 0, semiIndex); + aParams = + Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1)); + aParams.StripWhitespace(); + } else { + aType = aValue; + } + aType.StripWhitespace(); +} + +/** + * A helper function that parses a sandbox attribute (of an + + ` + ); + + await BrowserTestUtils.reloadTab(tab); + + let iframeFocused = SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + let iframe = content.document.querySelector("iframe"); + await ContentTaskUtils.waitForCondition(function () { + return content.document.activeElement == iframe; + }); + } + ); + + // Now the focus moves to the cross origin iframe + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + content.document.querySelector("iframe").focus(); + }); + + await iframeFocused; + + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, 1000)); + + const inputGetFocused = SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + await ContentTaskUtils.waitForEvent( + content.document.querySelector("input"), + "focus" + ); + } + ).then(function () { + Assert.ok( + true, + "Invisible OOP iframe shouldn't prevent user input event handling" + ); + }); + + let iframeBC = tab.linkedBrowser.browsingContext.children[0]; + // Next tab key should move the focus from the iframe to link + await BrowserTestUtils.synthesizeKey("KEY_Tab", {}, iframeBC); + + await inputGetFocused; + + BrowserTestUtils.removeTab(tab); +} + +add_task(async function test_InvisibleIframe() { + const prefs = [ + ["dom.input_events.security.minNumTicks", 3], + ["dom.input_events.security.minTimeElapsedInMS", 0], + ["dom.input_events.security.isUserInputHandlingDelayTest", true], + ]; + + await test_user_input_handling_delay_helper(prefs); +}); diff --git a/dom/base/test/browser_user_input_handling_delay_reload_ticks.js b/dom/base/test/browser_user_input_handling_delay_reload_ticks.js new file mode 100644 index 0000000000..8afc7f16bb --- /dev/null +++ b/dom/base/test/browser_user_input_handling_delay_reload_ticks.js @@ -0,0 +1,54 @@ +/* -*- Mode: JavaScript; 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/. */ + +async function test_user_input_handling_delay_helper(prefs) { + await SpecialPowers.pushPrefEnv({ + set: prefs, + }); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + `data:text/html,` + ); + + await BrowserTestUtils.reloadTab(tab); + + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, 5000)); + + const userInputHappend = SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + await ContentTaskUtils.waitForEvent(content, "keydown"); + } + ).then(function () { + Assert.ok( + true, + "User input event should be able to work after 5 seconds of an reload" + ); + }); + + // In the buggy build, the following tab key doesn't work + await BrowserTestUtils.synthesizeKey("KEY_Tab", {}, tab.linkedBrowser); + await BrowserTestUtils.synthesizeKey("KEY_Tab", {}, tab.linkedBrowser); + await BrowserTestUtils.synthesizeKey("KEY_Tab", {}, tab.linkedBrowser); + await BrowserTestUtils.synthesizeKey("KEY_Tab", {}, tab.linkedBrowser); + + await userInputHappend; + + BrowserTestUtils.removeTab(tab); +} + +add_task(async function test_MinTick() { + const prefs = [ + ["dom.input_events.security.minNumTicks", 10], + ["dom.input_events.security.minTimeElapsedInMS", 0], + ["dom.input_events.security.isUserInputHandlingDelayTest", true], + ]; + + await test_user_input_handling_delay_helper(prefs); +}); diff --git a/dom/base/test/browser_xml_toggle.js b/dom/base/test/browser_xml_toggle.js new file mode 100644 index 0000000000..477db038b1 --- /dev/null +++ b/dom/base/test/browser_xml_toggle.js @@ -0,0 +1,24 @@ +const URL = `data:text/xml, + + + Tove + Jani + Reminder + Don't forget me this weekend! + +`; + +add_task(async function xml_pretty_print_toggle() { + await BrowserTestUtils.withNewTab(URL, async function (browser) { + await SpecialPowers.spawn(browser, [], () => { + let summary = + content.document.documentElement.openOrClosedShadowRoot.querySelector( + "summary" + ); + let details = summary.parentNode; + ok(details.open, "Should be open"); + summary.click(); + ok(!details.open, "Should be closed"); + }); + }); +}); diff --git a/dom/base/test/bug1576154.sjs b/dom/base/test/bug1576154.sjs new file mode 100644 index 0000000000..d18151a8b4 --- /dev/null +++ b/dom/base/test/bug1576154.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) { + response.setStatusLine("1.1", 500, "Internal Server Error"); + response.setHeader("Content-Type", "image/svg+xml", false); + + let body = + ""; + response.bodyOutputStream.write(body, body.length); +} diff --git a/dom/base/test/bug1739957.sjs b/dom/base/test/bug1739957.sjs new file mode 100644 index 0000000000..38f5e72040 --- /dev/null +++ b/dom/base/test/bug1739957.sjs @@ -0,0 +1,10 @@ +function handleRequest(request, response) { + if (request.queryString == "loaded") { + response.write(getState("loaded") || "false"); + return; + } + + setState("loaded", "true"); + response.setHeader("Content-Type", "image/svg+xml", false); + response.write(``); +} diff --git a/dom/base/test/bug282547.sjs b/dom/base/test/bug282547.sjs new file mode 100644 index 0000000000..a57a176038 --- /dev/null +++ b/dom/base/test/bug282547.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) { + response.setStatusLine(null, 401, "Unauthorized"); + + response.setHeader("WWW-Authenticate", 'basic realm="restricted"', false); + + response.setHeader("Access-Control-Allow-Origin", "*", false); + response.setHeader("Access-Control-Allow-Credentials", "true", false); +} diff --git a/dom/base/test/bug298064-subframe.html b/dom/base/test/bug298064-subframe.html new file mode 100644 index 0000000000..af497f5905 --- /dev/null +++ b/dom/base/test/bug298064-subframe.html @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/dom/base/test/bug313646.txt b/dom/base/test/bug313646.txt new file mode 100644 index 0000000000..150f5ea6d1 --- /dev/null +++ b/dom/base/test/bug313646.txt @@ -0,0 +1 @@ +Nothing to see here. Just need to request this file via XHR. diff --git a/dom/base/test/bug382113_object.html b/dom/base/test/bug382113_object.html new file mode 100644 index 0000000000..935f00afd1 --- /dev/null +++ b/dom/base/test/bug382113_object.html @@ -0,0 +1,6 @@ + + + +

    A Document in an <object>

    + + diff --git a/dom/base/test/bug403852_fileOpener.js b/dom/base/test/bug403852_fileOpener.js new file mode 100644 index 0000000000..d3366cfe0c --- /dev/null +++ b/dom/base/test/bug403852_fileOpener.js @@ -0,0 +1,25 @@ +/* eslint-env mozilla/chrome-script */ + +// eslint-disable-next-line mozilla/reject-importGlobalProperties +Cu.importGlobalProperties(["File"]); + +var testFile = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIDirectoryService) + .QueryInterface(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); +testFile.append("prefs.js"); + +addMessageListener("file.open", function () { + File.createFromNsIFile(testFile).then(function (file) { + File.createFromNsIFile(testFile, { lastModified: 123 }).then(function ( + fileWithDate + ) { + sendAsyncMessage("file.opened", { + file, + mtime: testFile.lastModifiedTime, + fileWithDate, + fileDate: 123, + }); + }); + }); +}); diff --git a/dom/base/test/bug419132.html b/dom/base/test/bug419132.html new file mode 100644 index 0000000000..ab2934c2d4 --- /dev/null +++ b/dom/base/test/bug419132.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/dom/base/test/bug426308-redirect.sjs b/dom/base/test/bug426308-redirect.sjs new file mode 100644 index 0000000000..331f31d96a --- /dev/null +++ b/dom/base/test/bug426308-redirect.sjs @@ -0,0 +1,4 @@ +function handleRequest(request, response) { + response.setStatusLine(null, 302, "Found"); + response.setHeader("Location", request.queryString, false); +} diff --git a/dom/base/test/bug435425.sjs b/dom/base/test/bug435425.sjs new file mode 100644 index 0000000000..0e3ef38419 --- /dev/null +++ b/dom/base/test/bug435425.sjs @@ -0,0 +1,25 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + if (request.method == "GET") { + response.write(request.queryString); + } else { + var body = new BinaryInputStream(request.bodyInputStream); + + var avail; + var bytes = []; + + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + var data = String.fromCharCode.apply(null, bytes); + response.bodyOutputStream.write(data, data.length); + } +} diff --git a/dom/base/test/bug435425_redirect.sjs b/dom/base/test/bug435425_redirect.sjs new file mode 100644 index 0000000000..14fec62331 --- /dev/null +++ b/dom/base/test/bug435425_redirect.sjs @@ -0,0 +1,4 @@ +function handleRequest(request, response) { + response.setStatusLine(null, 302, "Moved"); + response.setHeader("Location", "http://nosuchdomain.localhost", false); +} diff --git a/dom/base/test/bug444322.js b/dom/base/test/bug444322.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/base/test/bug444322.txt b/dom/base/test/bug444322.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/base/test/bug444546.sjs b/dom/base/test/bug444546.sjs new file mode 100644 index 0000000000..5861eeb25c --- /dev/null +++ b/dom/base/test/bug444546.sjs @@ -0,0 +1,21 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + + var body = new BinaryInputStream(request.bodyInputStream); + + var avail; + var bytes = []; + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + var data = String.fromCharCode.apply(null, bytes); + response.bodyOutputStream.write(data, data.length); +} diff --git a/dom/base/test/bug455629-helper.svg b/dom/base/test/bug455629-helper.svg new file mode 100644 index 0000000000..38098585ed --- /dev/null +++ b/dom/base/test/bug455629-helper.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/base/test/bug457746.sjs b/dom/base/test/bug457746.sjs new file mode 100644 index 0000000000..e93e7e4f8d --- /dev/null +++ b/dom/base/test/bug457746.sjs @@ -0,0 +1,10 @@ +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain; charset=ISO-8859-1", false); + const body = [0xc1]; + var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance( + Ci.nsIBinaryOutputStream + ); + bos.setOutputStream(response.bodyOutputStream); + + bos.writeByteArray(body); +} diff --git a/dom/base/test/bug461735-post-redirect.js b/dom/base/test/bug461735-post-redirect.js new file mode 100644 index 0000000000..950948e4c9 --- /dev/null +++ b/dom/base/test/bug461735-post-redirect.js @@ -0,0 +1,3 @@ +var a = 0; +var b = 0; +c(); diff --git a/dom/base/test/bug461735-redirect1.sjs b/dom/base/test/bug461735-redirect1.sjs new file mode 100644 index 0000000000..cf00e8b8c4 --- /dev/null +++ b/dom/base/test/bug461735-redirect1.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) { + response.setStatusLine(null, 302, "Found"); + response.setHeader( + "Location", + "http://example.com/tests/dom/base/test/bug461735-post-redirect.js", + false + ); +} diff --git a/dom/base/test/bug461735-redirect2.sjs b/dom/base/test/bug461735-redirect2.sjs new file mode 100644 index 0000000000..416882003c --- /dev/null +++ b/dom/base/test/bug461735-redirect2.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) { + response.setStatusLine(null, 302, "Found"); + response.setHeader( + "Location", + "http://mochi.test:8888/tests/dom/base/test/bug461735-post-redirect.js", + false + ); +} diff --git a/dom/base/test/bug466080.sjs b/dom/base/test/bug466080.sjs new file mode 100644 index 0000000000..df3687000b --- /dev/null +++ b/dom/base/test/bug466080.sjs @@ -0,0 +1,14 @@ +function handleRequest(request, response) { + var body = "loaded"; + var origin = "localhost"; + try { + var origin = request.getHeader("Origin"); + } catch (e) {} + + response.setHeader("Access-Control-Allow-Origin", origin, false); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + response.setHeader("Access-Control-Allow-Methods", "XMETHOD", false); + response.setHeader("Connection", "Keep-alive", false); + + response.bodyOutputStream.write(body, body.length); +} diff --git a/dom/base/test/bug466409-empty.css b/dom/base/test/bug466409-empty.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/base/test/bug466409-page.html b/dom/base/test/bug466409-page.html new file mode 100644 index 0000000000..69ce7c2272 --- /dev/null +++ b/dom/base/test/bug466409-page.html @@ -0,0 +1,12 @@ + + + + Bug + + + +© + + diff --git a/dom/base/test/bug475156.sjs b/dom/base/test/bug475156.sjs new file mode 100644 index 0000000000..9c54b69f65 --- /dev/null +++ b/dom/base/test/bug475156.sjs @@ -0,0 +1,23 @@ +function handleRequest(request, response) { + if (request.queryString == "") { + var etag = request.hasHeader("If-Match") + ? request.getHeader("If-Match") + : null; + if (!etag || etag == getState("etag")) { + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("ETag", getState("etag")); + response.setHeader("Cache-control", "max-age=36000"); + response.write(getState("etag")); + } else if (etag) { + response.setStatusLine(request.httpVersion, 412, "Precondition Failed"); + } + } else { + var etag = request.queryString.match(/^etag=(.*)$/); + if (etag) { + setState("etag", etag[1]); + } + + response.setStatusLine(request.httpVersion, 204, "No content"); + } +} diff --git a/dom/base/test/bug482935.sjs b/dom/base/test/bug482935.sjs new file mode 100644 index 0000000000..b480c40e41 --- /dev/null +++ b/dom/base/test/bug482935.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) { + var body = "initial"; + + try { + body = request.getHeader("X-Request"); + } catch (e) { + body = "request.getHeader() failed! Exception: " + e; + } + + response.setHeader("Cache-Control", "max-age=3600"); + response.bodyOutputStream.write(body, body.length); +} diff --git a/dom/base/test/bug540854.sjs b/dom/base/test/bug540854.sjs new file mode 100644 index 0000000000..5861eeb25c --- /dev/null +++ b/dom/base/test/bug540854.sjs @@ -0,0 +1,21 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + + var body = new BinaryInputStream(request.bodyInputStream); + + var avail; + var bytes = []; + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + var data = String.fromCharCode.apply(null, bytes); + response.bodyOutputStream.write(data, data.length); +} diff --git a/dom/base/test/bug578096LoadChromeScript.js b/dom/base/test/bug578096LoadChromeScript.js new file mode 100644 index 0000000000..837c137f80 --- /dev/null +++ b/dom/base/test/bug578096LoadChromeScript.js @@ -0,0 +1,21 @@ +/* eslint-env mozilla/chrome-script */ + +var file; +// eslint-disable-next-line mozilla/reject-importGlobalProperties +Cu.importGlobalProperties(["File"]); + +addMessageListener("file.create", function (message) { + file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + file.append("foo.txt"); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + File.createFromNsIFile(file).then(function (domFile) { + sendAsyncMessage("file.created", domFile); + }); +}); + +addMessageListener("file.remove", function (message) { + file.remove(false); + sendAsyncMessage("file.removed", {}); +}); diff --git a/dom/base/test/bug638112-response.txt b/dom/base/test/bug638112-response.txt new file mode 100644 index 0000000000..9ce788da79 Binary files /dev/null and b/dom/base/test/bug638112-response.txt differ diff --git a/dom/base/test/bug638112.sjs b/dom/base/test/bug638112.sjs new file mode 100644 index 0000000000..883f3078a5 --- /dev/null +++ b/dom/base/test/bug638112.sjs @@ -0,0 +1,24 @@ +function getInputStream(path) { + var file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("CurWorkD", Ci.nsIFile); + var fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( + Ci.nsIFileInputStream + ); + var split = path.split("/"); + for (var i = 0; i < split.length; ++i) { + file.append(split[i]); + } + fis.init(file, -1, -1, false); + return fis; +} + +function handleRequest(request, response) { + var inputStream = getInputStream( + "tests/dom/base/test/bug638112-response.txt" + ); + response.seizePower(); + response.bodyOutputStream.writeFrom(inputStream, inputStream.available()); + response.finish(); + inputStream.close(); +} diff --git a/dom/base/test/bug696301-script-1.js b/dom/base/test/bug696301-script-1.js new file mode 100644 index 0000000000..98577364df --- /dev/null +++ b/dom/base/test/bug696301-script-1.js @@ -0,0 +1,3 @@ +var a = 0; +var global = "ran"; +c(); diff --git a/dom/base/test/bug696301-script-1.js^headers^ b/dom/base/test/bug696301-script-1.js^headers^ new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/dom/base/test/bug696301-script-1.js^headers^ @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/dom/base/test/bug696301-script-2.js b/dom/base/test/bug696301-script-2.js new file mode 100644 index 0000000000..98577364df --- /dev/null +++ b/dom/base/test/bug696301-script-2.js @@ -0,0 +1,3 @@ +var a = 0; +var global = "ran"; +c(); diff --git a/dom/base/test/bug704320.sjs b/dom/base/test/bug704320.sjs new file mode 100644 index 0000000000..f63b5d3a7e --- /dev/null +++ b/dom/base/test/bug704320.sjs @@ -0,0 +1,396 @@ +var BASE_URL = "example.com/tests/dom/base/test/bug704320.sjs"; + +function createTestUrl(schemeFrom, schemeTo, policy, action, type) { + return ( + schemeTo + + "://" + + BASE_URL + + "?" + + "action=" + + action + + "&" + + "scheme=" + + schemeFrom + + "-to-" + + schemeTo + + "&" + + "policy=" + + policy + + "&" + + "type=" + + type + ); +} + +function create2ndLevelIframeUrl(schemeFrom, schemeTo, policy, type) { + return ( + schemeFrom + + "://" + + BASE_URL + + "?" + + "action=create-2nd-level-iframe&" + + "scheme-from=" + + schemeFrom + + "&" + + "scheme-to=" + + schemeTo + + "&" + + "policy=" + + policy + + "&" + + "type=" + + type + ); +} + +// Creates the following test cases for the specified scheme and referrer +// policy combination: +// +// @import +// font-face +// bg-url +// \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ' + ); +} + +function createIframedFormTest(schemeFrom, schemeTo, policy) { + var actionUrl = schemeTo + "://" + BASE_URL; + + return ( + '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ +
    \n\ + \n\ + \n\ + \n\ + \n\ +
    \n\ + \n\ + \n\ + ' + ); +} + +function createIframedWindowLocationTest(schemeFrom, schemeTo, policy) { + var url = createTestUrl( + schemeFrom, + schemeTo, + policy, + "test", + "window.location" + ); + + return ( + '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ' + ); +} + +function createPolicyTest(policy, optionalEarlierPolicy) { + var metaReferrerPolicyString = ""; + if (optionalEarlierPolicy && optionalEarlierPolicy != "") { + metaReferrerPolicyString += + '\n'; + } + metaReferrerPolicyString += ''; + + return ( + "\n\ + \n\ + \n\ + " + + metaReferrerPolicyString + + '\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ' + ); +} + +function handleRequest(request, response) { + var sharedKey = "bug704320.sjs"; + var params = request.queryString.split("&"); + var action = params[0].split("=")[1]; + + if (action === "create-1st-level-iframe") { + // ?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin + var schemeFrom = params[1].split("=")[1]; + var schemeTo = params[2].split("=")[1]; + var policy = params[3].split("=")[1]; + var optionalEarlierPolicy = ""; + if (params[4]) { + optionalEarlierPolicy = params[4].split("=")[1]; + } + + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + response.write( + createTest(schemeFrom, schemeTo, policy, optionalEarlierPolicy) + ); + } else if (action === "create-2nd-level-iframe") { + // ?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=origin&type=form" + var schemeFrom = params[1].split("=")[1]; + var schemeTo = params[2].split("=")[1]; + var policy = params[3].split("=")[1]; + var type = params[4].split("=")[1]; + + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + + if (type === "form") { + response.write(createIframedFormTest(schemeFrom, schemeTo, policy)); + } else if (type === "window.location") { + response.write( + createIframedWindowLocationTest(schemeFrom, schemeTo, policy) + ); + } + } else if (action === "test") { + // ?action=test&scheme=http-to-https&policy=origin&type=img + var scheme = params[1].split("=")[1]; + var policy = params[2].split("=")[1]; + var type = params[3].split("=")[1]; + var result = getSharedState(sharedKey); + + if (result === "") { + result = {}; + } else { + result = JSON.parse(result); + } + + if (!result[type]) { + result[type] = {}; + } + + if (!result[type][scheme]) { + result[type][scheme] = {}; + } + + if (request.hasHeader("Referer")) { + result[type][scheme][policy] = request.getHeader("Referer"); + } else { + result[type][scheme][policy] = ""; + } + + setSharedState(sharedKey, JSON.stringify(result)); + + if (type === "link") { + var loc = + "https://example.com/tests/dom/base/test/file_bug704320_redirect.html"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + } + + if (type === "window.open") { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + response.write( + "" + ); + } + } else if (action === "get-test-results") { + // ?action=get-result + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(getSharedState(sharedKey)); + } else if (action === "generate-policy-test") { + // ?action=generate-policy-test&policy=b64-encoded-string + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + var policy = unescape(params[1].split("=")[1]); + var optionalEarlierPolicy = ""; + if (params[2]) { + optionalEarlierPolicy = params[2].split("=")[1]; + } + + response.write(createPolicyTest(policy, optionalEarlierPolicy)); + } +} diff --git a/dom/base/test/bug704320_counter.sjs b/dom/base/test/bug704320_counter.sjs new file mode 100644 index 0000000000..27b0becdc9 --- /dev/null +++ b/dom/base/test/bug704320_counter.sjs @@ -0,0 +1,95 @@ +// Handle counting loads for bug 704320. + +const SHARED_KEY = "bug704320_counter"; +const DEFAULT_STATE = { + css: { count: 0, referrers: [] }, + img: { count: 0, referrers: [] }, + js: { count: 0, referrers: [] }, +}; +const TYPE_MAP = { + css: "text/css", + js: "application/javascript", + img: "image/png", + html: "text/html", +}; + +// Writes an image to the response +function WriteOutImage(response) { + var file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("CurWorkD", Ci.nsIFile); + + file.append("tests"); + file.append("image"); + file.append("test"); + file.append("mochitest"); + file.append("blue.png"); + + var fileStream = Cc[ + "@mozilla.org/network/file-input-stream;1" + ].createInstance(Ci.nsIFileInputStream); + fileStream.init(file, 1, 0, false); + response.bodyOutputStream.writeFrom(fileStream, fileStream.available()); +} + +function handleRequest(request, response) { + var query = {}; + request.queryString.split("&").forEach(function (val) { + var [name, value] = val.split("="); + query[name] = unescape(value); + }); + + var referrerLevel = "none"; + if (request.hasHeader("Referer")) { + let referrer = request.getHeader("Referer"); + if (referrer.indexOf("bug704320") > 0) { + referrerLevel = "full"; + } else if (referrer == "http://mochi.test:8888/") { + referrerLevel = "origin"; + } + } + + var state = getSharedState(SHARED_KEY); + if (state === "") { + state = DEFAULT_STATE; + } else { + state = JSON.parse(state); + } + + response.setStatusLine(request.httpVersion, 200, "OK"); + + //avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + if ("reset" in query) { + //reset server state + setSharedState(SHARED_KEY, JSON.stringify(DEFAULT_STATE)); + //serve any CSS that we want to use. + response.write(""); + return; + } + + if ("results" in query) { + response.setHeader("Content-Type", "text/javascript", false); + response.write(JSON.stringify(state)); + return; + } + + if ("type" in query) { + state[query.type].count++; + response.setHeader("Content-Type", TYPE_MAP[query.type], false); + if (state[query.type].referrers.indexOf(referrerLevel) < 0) { + state[query.type].referrers.push(referrerLevel); + } + + if (query.type == "img") { + WriteOutImage(response); + } + } + + if ("content" in query) { + response.write(unescape(query.content)); + } + + setSharedState(SHARED_KEY, JSON.stringify(state)); +} diff --git a/dom/base/test/bug819051.sjs b/dom/base/test/bug819051.sjs new file mode 100644 index 0000000000..b880d4efe3 --- /dev/null +++ b/dom/base/test/bug819051.sjs @@ -0,0 +1,9 @@ +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader( + "X-appended-result", + request.getHeader("X-appended-to-this") + ); + response.setHeader("X-Accept-Result", request.getHeader("Accept")); + response.write(""); +} diff --git a/dom/base/test/chrome.toml b/dom/base/test/chrome.toml new file mode 100644 index 0000000000..687d778cac --- /dev/null +++ b/dom/base/test/chrome.toml @@ -0,0 +1,69 @@ +[DEFAULT] +skip-if = ["os == 'android'"] +prefs = ["dom.domrequest.enabled=true"] +support-files = [ + "file_empty.html", + "file_blocking_image.html", + "file_bug945152.jar", + "file_bug945152_worker.js", + "file_bug1008126_worker.js", + "file_inline_script.html", + "file_inline_script.xhtml", + "file_external_script.html", + "file_external_script.xhtml", + "file_script.js", + "file_serializer_noscript.html", + "referrer_helper.js", + "referrer_testserver.sjs", + "!/image/test/mochitest/shaver.png", +] + +["test_anchor_target_blank_referrer.html"] + +["test_anonymousContent_xul_window.xhtml"] + +["test_blockParsing.html"] + +["test_blocking_image.html"] + +["test_bug419527.xhtml"] + +["test_bug564863-2.xhtml"] + +["test_bug945152.html"] + +["test_bug1008126.html"] + +["test_bug1016960.html"] + +["test_bug1120222.html"] + +["test_domrequesthelper.xhtml"] + +["test_fragment_sanitization.xhtml"] + +["test_getLastOverWindowPointerLocationInCSSPixels.html"] +support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_utils.js"] + +["test_messagemanager_send_principal.html"] + +["test_navigator_resolve_identity_xrays.xhtml"] +support-files = ["file_navigator_resolve_identity_xrays.xhtml"] + +["test_sandbox_structuredclone.html"] + +["test_sandboxed_blob_uri.html"] + +["test_sanitize_xhr.html"] + +["test_sendQueryContentAndSelectionSetEvent.html"] + +["test_sendSelectionSetEvent_with_same_range.html"] + +["test_serializer_noscript.html"] + +["test_urgent_start.html"] +skip-if = [ #leaks Bug 1571583 + "os == 'win' && debug", + "os == 'mac' && debug", +] diff --git a/dom/base/test/chrome/bug418986-1.js b/dom/base/test/chrome/bug418986-1.js new file mode 100644 index 0000000000..7c39df0c13 --- /dev/null +++ b/dom/base/test/chrome/bug418986-1.js @@ -0,0 +1,88 @@ +/* globals chromeWindow */ +// The main test function. +var test = function (isContent) { + SimpleTest.waitForExplicitFinish(); + + SpecialPowers.pushPrefEnv({ + set: [["security.allow_eval_with_system_principal", true]], + }); + + if (!isContent) { + let { ww } = SpecialPowers.Services; + window.chromeWindow = ww.activeWindow; + } + + // The pairs of values expected to be the same when + // fingerprinting resistance is enabled. + let pairs = [ + ["screenX", 0], + ["screenY", 0], + ["mozInnerScreenX", 0], + ["mozInnerScreenY", 0], + ["screen.pixelDepth", 24], + ["screen.colorDepth", 24], + ["screen.availWidth", "innerWidth"], + ["screen.availHeight", "innerHeight"], + ["screen.left", 0], + ["screen.top", 0], + ["screen.availLeft", 0], + ["screen.availTop", 0], + ["screen.width", "innerWidth"], + ["screen.height", "innerHeight"], + ["screen.orientation.type", "'landscape-primary'"], + ["screen.orientation.angle", 0], + ["screen.mozOrientation", "'landscape-primary'"], + ["devicePixelRatio", 1], + ]; + + // checkPair: tests if members of pair [a, b] are equal when evaluated. + let checkPair = function (a, b) { + // eslint-disable-next-line no-eval + is(eval(a), eval(b), a + " should be equal to " + b); + }; + + // Returns generator object that iterates through pref values. + let prefVals = (function* () { + yield false; + yield true; + })(); + + // The main test function, runs until all pref values are exhausted. + let nextTest = function () { + let { value: prefValue, done } = prefVals.next(); + if (done) { + SimpleTest.finish(); + return; + } + SpecialPowers.pushPrefEnv( + { set: [["privacy.resistFingerprinting", prefValue]] }, + function () { + // We will be resisting fingerprinting if the pref is enabled, + // and we are in a content script (not chrome). + let resisting = prefValue && isContent; + // Check each of the pairs. + pairs.map(function ([item, onVal]) { + if (resisting) { + checkPair("window." + item, onVal); + } else if (!isContent && !item.startsWith("moz")) { + checkPair("window." + item, "chromeWindow." + item); + } + }); + if (!isContent && !resisting) { + // Hard to predict these values, but we can enforce constraints: + ok( + window.mozInnerScreenX >= chromeWindow.mozInnerScreenX, + "mozInnerScreenX" + ); + ok( + window.mozInnerScreenY >= chromeWindow.mozInnerScreenY, + "mozInnerScreenY" + ); + } + nextTest(); + } + ); + }; + + nextTest(); +}; diff --git a/dom/base/test/chrome/bug421622-referer.sjs b/dom/base/test/chrome/bug421622-referer.sjs new file mode 100644 index 0000000000..14cab00de4 --- /dev/null +++ b/dom/base/test/chrome/bug421622-referer.sjs @@ -0,0 +1,9 @@ +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + response.setHeader("Cache-Control", "no-cache", false); + + var referer = request.hasHeader("Referer") + ? request.getHeader("Referer") + : ""; + response.write("Referer: " + referer); +} diff --git a/dom/base/test/chrome/bug884693.sjs b/dom/base/test/chrome/bug884693.sjs new file mode 100644 index 0000000000..f2650753f2 --- /dev/null +++ b/dom/base/test/chrome/bug884693.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) { + let [status, statusText, encodedBody] = request.queryString.split("&"); + let body = decodeURIComponent(encodedBody); + response.setStatusLine(request.httpVersion, status, statusText); + response.setHeader("Content-Type", "text/xml", false); + response.setHeader("Content-Length", "" + body.length, false); + response.write(body); +} diff --git a/dom/base/test/chrome/chrome.toml b/dom/base/test/chrome/chrome.toml new file mode 100644 index 0000000000..b8439a2d2e --- /dev/null +++ b/dom/base/test/chrome/chrome.toml @@ -0,0 +1,135 @@ +[DEFAULT] +skip-if = ["os == 'android'"] +support-files = [ + "bug418986-1.js", + "clonedoc/**", + "file_bug549682.xhtml", + "file_bug616841.xhtml", + "file_bug816340.xhtml", + "file_bug990812-1.xhtml", + "file_bug990812-2.xhtml", + "file_bug990812-3.xhtml", + "file_bug990812-4.xhtml", + "file_bug990812-5.xhtml", + "file_bug1139964.xhtml", + "file_bug1209621.xhtml", + "fileconstructor_file.png", + "frame_custom_element_content.html", + "custom_element_ep.js", + "window_nsITextInputProcessor.xhtml", + "title_window.xhtml", + "window_swapFrameLoaders.xhtml", +] +prefs = ["gfx.font_rendering.fallback.async=false"] + +["test_bug120684.xhtml"] + +["test_bug206691.xhtml"] + +["test_bug289714.xhtml"] + +["test_bug339494.xhtml"] + +["test_bug357450.xhtml"] +support-files = ["../file_bug357450.js"] + +["test_bug380418.html"] + +["test_bug383430.html"] + +["test_bug418986-1.xhtml"] + +["test_bug421622.xhtml"] + +["test_bug429785.xhtml"] + +["test_bug430050.xhtml"] + +["test_bug467123.xhtml"] + +["test_bug473284.xhtml"] + +["test_bug549682.xhtml"] +skip-if = ["verify"] + +["test_bug571390.xhtml"] + +["test_bug616841.xhtml"] + +["test_bug635835.xhtml"] + +["test_bug682305.html"] + +["test_bug683852.xhtml"] + +["test_bug752226-3.xhtml"] + +["test_bug752226-4.xhtml"] + +["test_bug765993.html"] + +["test_bug780199.xhtml"] + +["test_bug780529.xhtml"] + +["test_bug800386.xhtml"] + +["test_bug816340.xhtml"] + +["test_bug884693.xhtml"] + +["test_bug914381.html"] + +["test_bug990812.xhtml"] + +["test_bug1063837.xhtml"] + +["test_bug1098074_throw_from_ReceiveMessage.xhtml"] + +["test_bug1139964.xhtml"] + +["test_bug1209621.xhtml"] + +["test_bug1339722.html"] + +["test_bug1346936.html"] + +["test_bug380418.html^headers^"] + +["test_chromeOuterWindowID.xhtml"] +support-files = ["window_chromeOuterWindowID.xhtml"] + +["test_custom_element_content.xhtml"] + +["test_custom_element_ep.xhtml"] + +["test_document-element-inserted.xhtml"] +support-files = [ + "file_document-element-inserted.xhtml", + "file_document-element-inserted-inner.xhtml", +] + +["test_domparsing.xhtml"] + +["test_fileconstructor.xhtml"] + +["test_getElementsWithGrid.html"] + +["test_input_value_set_preserve_undo.xhtml"] + +["test_nsITextInputProcessor.xhtml"] + +["test_nsITextInputProcessorCallback_at_changing_default_value_of_textarea.html"] + +["test_permission_hasValidTransientUserActivation.xhtml"] +support-files = ["../dummy.html"] + +["test_range_getClientRectsAndTexts.html"] + +["test_swapFrameLoaders.xhtml"] +skip-if = ["os == 'mac'"] # bug 1674413 + +["test_title.xhtml"] +support-files = ["file_title.xhtml"] + +["test_windowroot.xhtml"] diff --git a/dom/base/test/chrome/clonedoc/chrome.manifest b/dom/base/test/chrome/clonedoc/chrome.manifest new file mode 100644 index 0000000000..5d7e720416 --- /dev/null +++ b/dom/base/test/chrome/clonedoc/chrome.manifest @@ -0,0 +1 @@ +content clonedoc content/ diff --git a/dom/base/test/chrome/clonedoc/content/doc.xml b/dom/base/test/chrome/clonedoc/content/doc.xml new file mode 100644 index 0000000000..fdd7e7c6e0 --- /dev/null +++ b/dom/base/test/chrome/clonedoc/content/doc.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dom/base/test/chrome/custom_element_ep.js b/dom/base/test/chrome/custom_element_ep.js new file mode 100644 index 0000000000..d933ecbbab --- /dev/null +++ b/dom/base/test/chrome/custom_element_ep.js @@ -0,0 +1,14 @@ +/* globals finishTest */ +class XFoo extends HTMLElement { + constructor() { + super(); + this.magicNumber = 42; + } + + connectedCallback() { + finishTest(this.magicNumber === 42); + } +} +customElements.define("x-foo", XFoo); + +document.firstChild.appendChild(document.createElement("x-foo")); diff --git a/dom/base/test/chrome/file_bug1139964.xhtml b/dom/base/test/chrome/file_bug1139964.xhtml new file mode 100644 index 0000000000..8bf7f27e0b --- /dev/null +++ b/dom/base/test/chrome/file_bug1139964.xhtml @@ -0,0 +1,60 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug1209621.xhtml b/dom/base/test/chrome/file_bug1209621.xhtml new file mode 100644 index 0000000000..3ba58975bd --- /dev/null +++ b/dom/base/test/chrome/file_bug1209621.xhtml @@ -0,0 +1,85 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug549682.xhtml b/dom/base/test/chrome/file_bug549682.xhtml new file mode 100644 index 0000000000..8ae05d38d8 --- /dev/null +++ b/dom/base/test/chrome/file_bug549682.xhtml @@ -0,0 +1,214 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug616841.xhtml b/dom/base/test/chrome/file_bug616841.xhtml new file mode 100644 index 0000000000..b0512d162c --- /dev/null +++ b/dom/base/test/chrome/file_bug616841.xhtml @@ -0,0 +1,63 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug816340.xhtml b/dom/base/test/chrome/file_bug816340.xhtml new file mode 100644 index 0000000000..0b1a9adcab --- /dev/null +++ b/dom/base/test/chrome/file_bug816340.xhtml @@ -0,0 +1,69 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812-1.xhtml b/dom/base/test/chrome/file_bug990812-1.xhtml new file mode 100644 index 0000000000..8b8da3d136 --- /dev/null +++ b/dom/base/test/chrome/file_bug990812-1.xhtml @@ -0,0 +1,61 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812-2.xhtml b/dom/base/test/chrome/file_bug990812-2.xhtml new file mode 100644 index 0000000000..e13b47f589 --- /dev/null +++ b/dom/base/test/chrome/file_bug990812-2.xhtml @@ -0,0 +1,56 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812-3.xhtml b/dom/base/test/chrome/file_bug990812-3.xhtml new file mode 100644 index 0000000000..1f3e1d69f2 --- /dev/null +++ b/dom/base/test/chrome/file_bug990812-3.xhtml @@ -0,0 +1,68 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812-4.xhtml b/dom/base/test/chrome/file_bug990812-4.xhtml new file mode 100644 index 0000000000..1c16ceb02c --- /dev/null +++ b/dom/base/test/chrome/file_bug990812-4.xhtml @@ -0,0 +1,63 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812-5.xhtml b/dom/base/test/chrome/file_bug990812-5.xhtml new file mode 100644 index 0000000000..8c418492a1 --- /dev/null +++ b/dom/base/test/chrome/file_bug990812-5.xhtml @@ -0,0 +1,74 @@ + + + + + + diff --git a/dom/base/test/chrome/file_bug990812.xhtml b/dom/base/test/chrome/file_bug990812.xhtml new file mode 100644 index 0000000000..02662d5749 --- /dev/null +++ b/dom/base/test/chrome/file_bug990812.xhtml @@ -0,0 +1,55 @@ + + + + + + diff --git a/dom/base/test/chrome/file_document-element-inserted-inner.xhtml b/dom/base/test/chrome/file_document-element-inserted-inner.xhtml new file mode 100644 index 0000000000..2088e2789a --- /dev/null +++ b/dom/base/test/chrome/file_document-element-inserted-inner.xhtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dom/base/test/chrome/file_document-element-inserted.xhtml b/dom/base/test/chrome/file_document-element-inserted.xhtml new file mode 100644 index 0000000000..d67df13df7 --- /dev/null +++ b/dom/base/test/chrome/file_document-element-inserted.xhtml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dom/base/test/chrome/file_title.xhtml b/dom/base/test/chrome/file_title.xhtml new file mode 100644 index 0000000000..d1b04418aa --- /dev/null +++ b/dom/base/test/chrome/file_title.xhtml @@ -0,0 +1 @@ + diff --git a/dom/base/test/chrome/fileconstructor_file.png b/dom/base/test/chrome/fileconstructor_file.png new file mode 100644 index 0000000000..51e8aaf38c Binary files /dev/null and b/dom/base/test/chrome/fileconstructor_file.png differ diff --git a/dom/base/test/chrome/frame_custom_element_content.html b/dom/base/test/chrome/frame_custom_element_content.html new file mode 100644 index 0000000000..aa1d75863d --- /dev/null +++ b/dom/base/test/chrome/frame_custom_element_content.html @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/base/test/chrome/nochrome_bug1346936.html b/dom/base/test/chrome/nochrome_bug1346936.html new file mode 100644 index 0000000000..158b20c884 --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug1346936.html @@ -0,0 +1,3 @@ + + + diff --git a/dom/base/test/chrome/nochrome_bug1346936.js b/dom/base/test/chrome/nochrome_bug1346936.js new file mode 100644 index 0000000000..a84113e1e1 --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug1346936.js @@ -0,0 +1,4 @@ +//# sourceMappingURL=bar.js.map + +// Define a single function to prevent script source from being gc'd +function foo() {} diff --git a/dom/base/test/chrome/nochrome_bug1346936.js^headers^ b/dom/base/test/chrome/nochrome_bug1346936.js^headers^ new file mode 100644 index 0000000000..812264590d --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug1346936.js^headers^ @@ -0,0 +1 @@ +SourceMap: foo.js.map diff --git a/dom/base/test/chrome/nochrome_bug765993.html b/dom/base/test/chrome/nochrome_bug765993.html new file mode 100644 index 0000000000..158b20c884 --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug765993.html @@ -0,0 +1,3 @@ + + + diff --git a/dom/base/test/chrome/nochrome_bug765993.js b/dom/base/test/chrome/nochrome_bug765993.js new file mode 100644 index 0000000000..a84113e1e1 --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug765993.js @@ -0,0 +1,4 @@ +//# sourceMappingURL=bar.js.map + +// Define a single function to prevent script source from being gc'd +function foo() {} diff --git a/dom/base/test/chrome/nochrome_bug765993.js^headers^ b/dom/base/test/chrome/nochrome_bug765993.js^headers^ new file mode 100644 index 0000000000..8efacff3c8 --- /dev/null +++ b/dom/base/test/chrome/nochrome_bug765993.js^headers^ @@ -0,0 +1 @@ +X-SourceMap: foo.js.map diff --git a/dom/base/test/chrome/test_bug1063837.xhtml b/dom/base/test/chrome/test_bug1063837.xhtml new file mode 100644 index 0000000000..794cf1c72c --- /dev/null +++ b/dom/base/test/chrome/test_bug1063837.xhtml @@ -0,0 +1,36 @@ + + + + + + + + + + Mozilla Bug 1063837 + + + + + diff --git a/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xhtml b/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xhtml new file mode 100644 index 0000000000..769c10b370 --- /dev/null +++ b/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xhtml @@ -0,0 +1,47 @@ + + + + + + + + + + Mozilla Bug 1098074 + + diff --git a/dom/base/test/chrome/test_bug1139964.xhtml b/dom/base/test/chrome/test_bug1139964.xhtml new file mode 100644 index 0000000000..8b1b36fa64 --- /dev/null +++ b/dom/base/test/chrome/test_bug1139964.xhtml @@ -0,0 +1,32 @@ + + + + + + + + + + Mozilla Bug 1139964 + + + + + diff --git a/dom/base/test/chrome/test_bug120684.xhtml b/dom/base/test/chrome/test_bug120684.xhtml new file mode 100644 index 0000000000..08e9b28cfe --- /dev/null +++ b/dom/base/test/chrome/test_bug120684.xhtml @@ -0,0 +1,80 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug1209621.xhtml b/dom/base/test/chrome/test_bug1209621.xhtml new file mode 100644 index 0000000000..947606b638 --- /dev/null +++ b/dom/base/test/chrome/test_bug1209621.xhtml @@ -0,0 +1,34 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug1339722.html b/dom/base/test/chrome/test_bug1339722.html new file mode 100644 index 0000000000..d8d95f1faa --- /dev/null +++ b/dom/base/test/chrome/test_bug1339722.html @@ -0,0 +1,86 @@ + + + + + + Test for Bug 1339722 + + + + + + + Mozilla Bug 1339722 +

    + +
    +  
    + +
    +
    + + diff --git a/dom/base/test/chrome/test_bug1346936.html b/dom/base/test/chrome/test_bug1346936.html new file mode 100644 index 0000000000..2c61c65237 --- /dev/null +++ b/dom/base/test/chrome/test_bug1346936.html @@ -0,0 +1,61 @@ + + + + + Test for Bug 1346936 + + + + + +Mozilla Bug 1346936 + + + +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug206691.xhtml b/dom/base/test/chrome/test_bug206691.xhtml new file mode 100644 index 0000000000..16a27762ac --- /dev/null +++ b/dom/base/test/chrome/test_bug206691.xhtml @@ -0,0 +1,32 @@ + + + + + + + + + + Mozilla Bug 206691 + + + + + diff --git a/dom/base/test/chrome/test_bug289714.xhtml b/dom/base/test/chrome/test_bug289714.xhtml new file mode 100644 index 0000000000..4b4cc6fb84 --- /dev/null +++ b/dom/base/test/chrome/test_bug289714.xhtml @@ -0,0 +1,33 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug339494.xhtml b/dom/base/test/chrome/test_bug339494.xhtml new file mode 100644 index 0000000000..203f6e644d --- /dev/null +++ b/dom/base/test/chrome/test_bug339494.xhtml @@ -0,0 +1,73 @@ + + + + + + + + + +Mozilla Bug 339494 +

    + +
    +
    + + + + +
    diff --git a/dom/base/test/chrome/test_bug357450.xhtml b/dom/base/test/chrome/test_bug357450.xhtml new file mode 100644 index 0000000000..7723364ecc --- /dev/null +++ b/dom/base/test/chrome/test_bug357450.xhtml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + +Mozilla Bug 357450 + +

    + +
    + hmm + hmm + hmm + hmm + hmm +
    +

    +

    +

    +

    +
    +
    +
    + + + + + + + + + + + + hmm + + + +
    diff --git a/dom/base/test/chrome/test_bug380418.html b/dom/base/test/chrome/test_bug380418.html new file mode 100644 index 0000000000..eb3f8d3042 --- /dev/null +++ b/dom/base/test/chrome/test_bug380418.html @@ -0,0 +1,37 @@ + + + + + Test for Bug 380418 + + + + +Mozilla Bug 380418 +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug380418.html^headers^ b/dom/base/test/chrome/test_bug380418.html^headers^ new file mode 100644 index 0000000000..5f8d4969c0 --- /dev/null +++ b/dom/base/test/chrome/test_bug380418.html^headers^ @@ -0,0 +1,4 @@ +Set-Cookie: test +Set-Cookie2: test2 +X-Dummy: test +Cache-Control: max-age=0 diff --git a/dom/base/test/chrome/test_bug383430.html b/dom/base/test/chrome/test_bug383430.html new file mode 100644 index 0000000000..ce526ef281 --- /dev/null +++ b/dom/base/test/chrome/test_bug383430.html @@ -0,0 +1,38 @@ + + + + + Test for Bug 383430 + + + + +Mozilla Bug 383430 +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug418986-1.xhtml b/dom/base/test/chrome/test_bug418986-1.xhtml new file mode 100644 index 0000000000..7d3add900a --- /dev/null +++ b/dom/base/test/chrome/test_bug418986-1.xhtml @@ -0,0 +1,25 @@ + + + + + + + + + + Mozilla Bug 418986 (Part 1) + + + + + + diff --git a/dom/base/test/chrome/test_bug421622.xhtml b/dom/base/test/chrome/test_bug421622.xhtml new file mode 100644 index 0000000000..236c42dd34 --- /dev/null +++ b/dom/base/test/chrome/test_bug421622.xhtml @@ -0,0 +1,34 @@ + + + + + + + + + + Mozilla Bug 421622 + + + + + diff --git a/dom/base/test/chrome/test_bug429785.xhtml b/dom/base/test/chrome/test_bug429785.xhtml new file mode 100644 index 0000000000..fb51634fab --- /dev/null +++ b/dom/base/test/chrome/test_bug429785.xhtml @@ -0,0 +1,53 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug430050.xhtml b/dom/base/test/chrome/test_bug430050.xhtml new file mode 100644 index 0000000000..d7d6cf656c --- /dev/null +++ b/dom/base/test/chrome/test_bug430050.xhtml @@ -0,0 +1,48 @@ + + + + + + + + + + Mozilla Bug 430050 + + + + + + diff --git a/dom/base/test/chrome/test_bug467123.xhtml b/dom/base/test/chrome/test_bug467123.xhtml new file mode 100644 index 0000000000..0811aba051 --- /dev/null +++ b/dom/base/test/chrome/test_bug467123.xhtml @@ -0,0 +1,42 @@ + + + + + + + + + + Mozilla Bug 467123 + + + + + diff --git a/dom/base/test/chrome/test_bug473284.xhtml b/dom/base/test/chrome/test_bug473284.xhtml new file mode 100644 index 0000000000..87c778a615 --- /dev/null +++ b/dom/base/test/chrome/test_bug473284.xhtml @@ -0,0 +1,83 @@ + + + + + + + + + + Mozilla Bug 473284 + + diff --git a/dom/base/test/chrome/test_bug549682.xhtml b/dom/base/test/chrome/test_bug549682.xhtml new file mode 100644 index 0000000000..0f1ecf646a --- /dev/null +++ b/dom/base/test/chrome/test_bug549682.xhtml @@ -0,0 +1,32 @@ + + + + + + + + + + Mozilla Bug 549682 + + + + + diff --git a/dom/base/test/chrome/test_bug571390.xhtml b/dom/base/test/chrome/test_bug571390.xhtml new file mode 100644 index 0000000000..ea1f357a5d --- /dev/null +++ b/dom/base/test/chrome/test_bug571390.xhtml @@ -0,0 +1,42 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug616841.xhtml b/dom/base/test/chrome/test_bug616841.xhtml new file mode 100644 index 0000000000..f5907f0b0b --- /dev/null +++ b/dom/base/test/chrome/test_bug616841.xhtml @@ -0,0 +1,30 @@ + + + + + + + + + + Mozilla Bug 616841 + + + + + diff --git a/dom/base/test/chrome/test_bug635835.xhtml b/dom/base/test/chrome/test_bug635835.xhtml new file mode 100644 index 0000000000..69bb3ae68b --- /dev/null +++ b/dom/base/test/chrome/test_bug635835.xhtml @@ -0,0 +1,36 @@ + + + + + + + + + + Mozilla Bug 635835 + + + + + diff --git a/dom/base/test/chrome/test_bug682305.html b/dom/base/test/chrome/test_bug682305.html new file mode 100644 index 0000000000..d500dc91d5 --- /dev/null +++ b/dom/base/test/chrome/test_bug682305.html @@ -0,0 +1,150 @@ + + + + + XMLHttpRequest send and channel implemented in JS + + + + + +Mozilla Bug 682305 +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug683852.xhtml b/dom/base/test/chrome/test_bug683852.xhtml new file mode 100644 index 0000000000..1f9e0d9472 --- /dev/null +++ b/dom/base/test/chrome/test_bug683852.xhtml @@ -0,0 +1,87 @@ + + + + + + + Anonymous + + + + + Mozilla Bug 683852 + + + + + diff --git a/dom/base/test/chrome/test_bug752226-3.xhtml b/dom/base/test/chrome/test_bug752226-3.xhtml new file mode 100644 index 0000000000..747fb29c4e --- /dev/null +++ b/dom/base/test/chrome/test_bug752226-3.xhtml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug752226-4.xhtml b/dom/base/test/chrome/test_bug752226-4.xhtml new file mode 100644 index 0000000000..242e231a2e --- /dev/null +++ b/dom/base/test/chrome/test_bug752226-4.xhtml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug765993.html b/dom/base/test/chrome/test_bug765993.html new file mode 100644 index 0000000000..3325c3713d --- /dev/null +++ b/dom/base/test/chrome/test_bug765993.html @@ -0,0 +1,61 @@ + + + + + Test for Bug 765993 + + + + + +Mozilla Bug 765993 + + + +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug780199.xhtml b/dom/base/test/chrome/test_bug780199.xhtml new file mode 100644 index 0000000000..e27afb72fa --- /dev/null +++ b/dom/base/test/chrome/test_bug780199.xhtml @@ -0,0 +1,51 @@ + + + + + + + + diff --git a/dom/base/test/chrome/test_bug780529.xhtml b/dom/base/test/chrome/test_bug780529.xhtml new file mode 100644 index 0000000000..bf8b8b2981 --- /dev/null +++ b/dom/base/test/chrome/test_bug780529.xhtml @@ -0,0 +1,36 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug800386.xhtml b/dom/base/test/chrome/test_bug800386.xhtml new file mode 100644 index 0000000000..c176bd9b8e --- /dev/null +++ b/dom/base/test/chrome/test_bug800386.xhtml @@ -0,0 +1,65 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug816340.xhtml b/dom/base/test/chrome/test_bug816340.xhtml new file mode 100644 index 0000000000..3e45fd7245 --- /dev/null +++ b/dom/base/test/chrome/test_bug816340.xhtml @@ -0,0 +1,32 @@ + + + + + + + + + + Mozilla Bug 816340 + + + + + diff --git a/dom/base/test/chrome/test_bug884693.xhtml b/dom/base/test/chrome/test_bug884693.xhtml new file mode 100644 index 0000000000..7d89ba25bc --- /dev/null +++ b/dom/base/test/chrome/test_bug884693.xhtml @@ -0,0 +1,79 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_bug914381.html b/dom/base/test/chrome/test_bug914381.html new file mode 100644 index 0000000000..eb82ffd0f7 --- /dev/null +++ b/dom/base/test/chrome/test_bug914381.html @@ -0,0 +1,58 @@ + + + + + + Test for Bug 914381 + + + + +Mozilla Bug 914381 +

    + +
    +
    +
    + + diff --git a/dom/base/test/chrome/test_bug990812.xhtml b/dom/base/test/chrome/test_bug990812.xhtml new file mode 100644 index 0000000000..410d6d2367 --- /dev/null +++ b/dom/base/test/chrome/test_bug990812.xhtml @@ -0,0 +1,42 @@ + + + + + + + + + + Mozilla Bug 990812 + + + + + diff --git a/dom/base/test/chrome/test_chromeOuterWindowID.xhtml b/dom/base/test/chrome/test_chromeOuterWindowID.xhtml new file mode 100644 index 0000000000..1feb7c7c74 --- /dev/null +++ b/dom/base/test/chrome/test_chromeOuterWindowID.xhtml @@ -0,0 +1,138 @@ + + + + + + + diff --git a/dom/base/test/chrome/test_custom_element_content.xhtml b/dom/base/test/chrome/test_custom_element_content.xhtml new file mode 100644 index 0000000000..7778bc350e --- /dev/null +++ b/dom/base/test/chrome/test_custom_element_content.xhtml @@ -0,0 +1,55 @@ + + + + + + + + + + Mozilla Bug 1130028 + + + + + + diff --git a/dom/base/test/chrome/test_custom_element_ep.xhtml b/dom/base/test/chrome/test_custom_element_ep.xhtml new file mode 100644 index 0000000000..28b4e876f5 --- /dev/null +++ b/dom/base/test/chrome/test_custom_element_ep.xhtml @@ -0,0 +1,41 @@ + + + + + + + + + + Mozilla Bug 1130028 + + + + + + diff --git a/dom/base/test/chrome/test_document-element-inserted.xhtml b/dom/base/test/chrome/test_document-element-inserted.xhtml new file mode 100644 index 0000000000..5fd35e364d --- /dev/null +++ b/dom/base/test/chrome/test_document-element-inserted.xhtml @@ -0,0 +1,54 @@ + + + + + + + + + + Mozilla Bug 1411707 + + + + + diff --git a/dom/base/test/chrome/test_domparsing.xhtml b/dom/base/test/chrome/test_domparsing.xhtml new file mode 100644 index 0000000000..48a7d43b6a --- /dev/null +++ b/dom/base/test/chrome/test_domparsing.xhtml @@ -0,0 +1,145 @@ + + + + + + diff --git a/dom/base/test/chrome/test_fileconstructor.xhtml b/dom/base/test/chrome/test_fileconstructor.xhtml new file mode 100644 index 0000000000..8884eb169b --- /dev/null +++ b/dom/base/test/chrome/test_fileconstructor.xhtml @@ -0,0 +1,86 @@ + + + + + + + + + + + Mozilla Bug 607114 +

    + +
    +
    + + + + +
    diff --git a/dom/base/test/chrome/test_getElementsWithGrid.html b/dom/base/test/chrome/test_getElementsWithGrid.html new file mode 100644 index 0000000000..3554acb2e9 --- /dev/null +++ b/dom/base/test/chrome/test_getElementsWithGrid.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + +
    +
    +
    +
    + +
    + +
    +
    +
    + + + +
    + +
    + +
    + + + +
    + + + +
    + + + diff --git a/dom/base/test/chrome/test_input_value_set_preserve_undo.xhtml b/dom/base/test/chrome/test_input_value_set_preserve_undo.xhtml new file mode 100644 index 0000000000..80465202ab --- /dev/null +++ b/dom/base/test/chrome/test_input_value_set_preserve_undo.xhtml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/dom/base/test/chrome/test_nsITextInputProcessor.xhtml b/dom/base/test/chrome/test_nsITextInputProcessor.xhtml new file mode 100644 index 0000000000..3343c28560 --- /dev/null +++ b/dom/base/test/chrome/test_nsITextInputProcessor.xhtml @@ -0,0 +1,29 @@ + + + + + + + + +

    +

    + +
    +
    + + + +
    diff --git a/dom/base/test/chrome/test_nsITextInputProcessorCallback_at_changing_default_value_of_textarea.html b/dom/base/test/chrome/test_nsITextInputProcessorCallback_at_changing_default_value_of_textarea.html new file mode 100644 index 0000000000..179ffee086 --- /dev/null +++ b/dom/base/test/chrome/test_nsITextInputProcessorCallback_at_changing_default_value_of_textarea.html @@ -0,0 +1,107 @@ + + + + +Text change notifications at updating default value of non-dirty textarea + + + + + + diff --git a/dom/base/test/chrome/test_permission_hasValidTransientUserActivation.xhtml b/dom/base/test/chrome/test_permission_hasValidTransientUserActivation.xhtml new file mode 100644 index 0000000000..89da945588 --- /dev/null +++ b/dom/base/test/chrome/test_permission_hasValidTransientUserActivation.xhtml @@ -0,0 +1,93 @@ + + + + + + + + + +
    +

    + + +
    +
    + + + + +
    diff --git a/dom/base/test/chrome/window_swapFrameLoaders.xhtml b/dom/base/test/chrome/window_swapFrameLoaders.xhtml new file mode 100644 index 0000000000..4a38bcc1fc --- /dev/null +++ b/dom/base/test/chrome/window_swapFrameLoaders.xhtml @@ -0,0 +1,223 @@ + + + + + + + + diff --git a/dom/base/test/common_postMessages.js b/dom/base/test/common_postMessages.js new file mode 100644 index 0000000000..c4836fdd77 --- /dev/null +++ b/dom/base/test/common_postMessages.js @@ -0,0 +1,393 @@ +function getType(a) { + if (a === null || a === undefined) { + return "null"; + } + + if (Array.isArray(a)) { + return "array"; + } + + if (typeof a == "object") { + return "object"; + } + + if ( + SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported() && + a instanceof WebAssembly.Module + ) { + return "wasm"; + } + + return "primitive"; +} + +function compare(a, b) { + is(getType(a), getType(b), "Type matches"); + + var type = getType(a); + if (type == "array") { + is(a.length, b.length, "Array.length matches"); + for (var i = 0; i < a.length; ++i) { + compare(a[i], b[i]); + } + + return; + } + + if (type == "object") { + ok(a !== b, "They should not match"); + + var aProps = []; + for (var p in a) { + aProps.push(p); + } + + var bProps = []; + for (var p in b) { + bProps.push(p); + } + + is(aProps.length, bProps.length, "Props match"); + is(aProps.sort().toString(), bProps.sort().toString(), "Props names match"); + + for (var p in a) { + compare(a[p], b[p]); + } + + return; + } + + if (type == "wasm") { + var wasmA = new WebAssembly.Instance(a); + ok(wasmA instanceof WebAssembly.Instance, "got an instance"); + + var wasmB = new WebAssembly.Instance(b); + ok(wasmB instanceof WebAssembly.Instance, "got an instance"); + + ok(wasmA.exports.foo() === wasmB.exports.foo(), "Same result!"); + ok(wasmB.exports.foo() === 42, "We want 42"); + } + + if (type != "null") { + is(a, b, "Same value"); + } +} + +var clonableObjects = [ + { target: "all", data: "hello world" }, + { target: "all", data: 123 }, + { target: "all", data: null }, + { target: "all", data: true }, + { target: "all", data: new Date() }, + { target: "all", data: [1, "test", true, new Date()] }, + { + target: "all", + data: { a: true, b: null, c: new Date(), d: [true, false, {}] }, + }, + { target: "all", data: new Blob([123], { type: "plain/text" }) }, + { target: "all", data: new ImageData(2, 2) }, +]; + +function create_fileList() { + var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + var fileList = document.getElementById("fileList"); + SpecialPowers.wrap(fileList).mozSetFileArray([message.file]); + + // Just a simple test + var domFile = fileList.files[0]; + is(domFile.name, "prefs.js", "fileName should be prefs.js"); + + clonableObjects.push({ target: "all", data: fileList.files }); + script.destroy(); + next(); + } + + script.addMessageListener("file.opened", onOpened); + script.sendAsyncMessage("file.open"); +} + +function create_directory() { + if (navigator.userAgent.toLowerCase().includes("Android")) { + next(); + return; + } + + var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + var fileList = document.getElementById("fileList"); + SpecialPowers.wrap(fileList).mozSetDirectory(message.dir); + + SpecialPowers.wrap(fileList) + .getFilesAndDirectories() + .then(function (list) { + list = SpecialPowers.unwrap(list); + // Just a simple test + is(list.length, 1, "This list has 1 element"); + ok(list[0] instanceof Directory, "We have a directory."); + + clonableObjects.push({ target: "all", data: list[0] }); + script.destroy(); + next(); + }); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open"); +} + +function create_wasmModule() { + info("Checking if we can play with WebAssembly..."); + + if (!SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()) { + next(); + return; + } + + ok(WebAssembly, "WebAssembly object should exist"); + ok(WebAssembly.compile, "WebAssembly.compile function should exist"); + + /* + js -e ' + t = wasmTextToBinary(` + (module + (func $foo (result i32) (i32.const 42)) + (export "foo" (func $foo)) + ) + `); + print(t) + ' + */ + // prettier-ignore + const fooModuleCode = new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,127,3,2,1,0,7,7,1,3,102,111,111,0,0,10,6,1,4,0,65,42,11,0,13,4,110,97,109,101,1,6,1,0,3,102,111,111]); + + WebAssembly.compile(fooModuleCode).then( + m => { + ok(m instanceof WebAssembly.Module, "The WasmModule has been compiled."); + clonableObjects.push({ target: "sameProcess", data: m }); + next(); + }, + () => { + ok(false, "The compilation of the wasmModule failed."); + } + ); +} + +function runTests(obj) { + ok( + "clonableObjectsEveryWhere" in obj && + "clonableObjectsSameProcess" in obj && + "transferableObjects" in obj && + (obj.clonableObjectsEveryWhere || + obj.clonableObjectsSameProcess || + obj.transferableObjects), + "We must run some test!" + ); + + // cloning tests - everyWhere + new Promise(function (resolve, reject) { + var clonableObjectsId = 0; + function runClonableTest() { + if (clonableObjectsId >= clonableObjects.length) { + resolve(); + return; + } + + var object = clonableObjects[clonableObjectsId++]; + + if (object.target != "all") { + runClonableTest(); + return; + } + + obj + .send(object.data, []) + .catch(() => { + return { error: true }; + }) + .then(received => { + if (!obj.clonableObjectsEveryWhere) { + ok(received.error, "Error expected"); + } else { + ok(!received.error, "Error not expected"); + compare(received.data, object.data); + } + runClonableTest(); + }); + } + + runClonableTest(); + }) + + // clonable same process + .then(function () { + return new Promise(function (resolve, reject) { + var clonableObjectsId = 0; + function runClonableTest() { + if (clonableObjectsId >= clonableObjects.length) { + resolve(); + return; + } + + var object = clonableObjects[clonableObjectsId++]; + + if (object.target != "sameProcess") { + runClonableTest(); + return; + } + + obj + .send(object.data, []) + .catch(() => { + return { error: true }; + }) + .then(received => { + if (!obj.clonableObjectsSameProcess) { + ok(received.error, "Error expected"); + } else { + ok(!received.error, "Error not expected"); + compare(received.data, object.data); + } + runClonableTest(); + }); + } + + runClonableTest(); + }); + }) + + // transfering tests + .then(function () { + if (!obj.transferableObjects) { + return Promise.resolve(); + } + + // MessagePort + return new Promise(function (r, rr) { + var mc = new MessageChannel(); + obj.send(42, [mc.port1]).then(function (received) { + is(received.ports.length, 1, "MessagePort has been transferred"); + mc.port2.postMessage("hello world"); + received.ports[0].onmessage = function (e) { + is(e.data, "hello world", "Ports are connected!"); + r(); + }; + }); + }); + }) + + // no dup transfering + .then(function () { + if (!obj.transferableObjects) { + return Promise.resolve(); + } + + // MessagePort + return new Promise(function (r, rr) { + var mc = new MessageChannel(); + obj + .send(42, [mc.port1, mc.port1]) + .then( + function (received) { + ok(false, "Duplicate ports should throw!"); + }, + function () { + ok(true, "Duplicate ports should throw!"); + } + ) + .then(r); + }); + }) + + // maintaining order of transferred ports + .then(function () { + if (!obj.transferableObjects) { + return Promise.resolve(); + } + + // MessagePort + return new Promise(function (r, rr) { + var mcs = []; + const NPORTS = 50; + for (let i = 0; i < NPORTS; i++) { + mcs.push(new MessageChannel()); + } + obj + .send( + 42, + mcs.map(channel => channel.port1) + ) + .then(function (received) { + is( + received.ports.length, + NPORTS, + `all ${NPORTS} ports transferred` + ); + const promises = Array(NPORTS) + .fill() + .map( + (_, i) => + new Promise(function (subr, subrr) { + mcs[i].port2.postMessage(i); + received.ports[i].onmessage = e => subr(e.data == i); + }) + ); + return Promise.all(promises); + }) + .then(function (result) { + let in_order = 0; + for (const correct of result) { + if (correct) { + in_order++; + } + } + is(in_order, NPORTS, "All transferred ports are in order"); + }) + .then(r); + }); + }) + + // non transfering tests + .then(function () { + if (obj.transferableObjects) { + return Promise.resolve(); + } + + // MessagePort + return new Promise(function (r, rr) { + var mc = new MessageChannel(); + obj + .send(42, [mc.port1]) + .then( + function (received) { + ok(false, "This object should not support port transferring"); + }, + function () { + ok(true, "This object should not support port transferring"); + } + ) + .then(r); + }); + }) + + // done. + .then(function () { + obj.finished(); + }); +} + +function next() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + test(); +} + +var tests = [create_fileList, create_directory, create_wasmModule]; diff --git a/dom/base/test/copypaste.js b/dom/base/test/copypaste.js new file mode 100644 index 0000000000..d7fae29724 --- /dev/null +++ b/dom/base/test/copypaste.js @@ -0,0 +1,557 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function modifySelection(s) { + var g = window.getSelection(); + var l = g.getRangeAt(0); + var d = document.createElement("p"); + d.innerHTML = s; + d.appendChild(l.cloneContents()); + + var e = document.createElement("div"); + document.body.appendChild(e); + e.appendChild(d); + var a = document.createRange(); + a.selectNode(d); + g.removeAllRanges(); + g.addRange(a); + window.setTimeout(function () { + e.remove(); + g.removeAllRanges(); + g.addRange(l); + }, 0); +} + +function getLoadContext() { + var Ci = SpecialPowers.Ci; + return SpecialPowers.wrap(window).docShell.QueryInterface(Ci.nsILoadContext); +} + +async function testCopyPaste(isXHTML) { + var suppressUnicodeCheckIfHidden = !!isXHTML; + var suppressHTMLCheck = !!isXHTML; + + var docShell = SpecialPowers.wrap(window).docShell; + + var documentViewer = docShell.docViewer.QueryInterface( + SpecialPowers.Ci.nsIDocumentViewerEdit + ); + + var clipboard = SpecialPowers.Services.clipboard; + + var textarea = SpecialPowers.wrap(document.getElementById("input")); + + async function copySelectionToClipboard(suppressUnicodeCheck) { + await SimpleTest.promiseClipboardChange( + () => true, + () => { + documentViewer.copySelection(); + } + ); + if (!suppressUnicodeCheck) { + ok( + clipboard.hasDataMatchingFlavors(["text/plain"], 1), + "check text/plain" + ); + } + if (!suppressHTMLCheck) { + ok(clipboard.hasDataMatchingFlavors(["text/html"], 1), "check text/html"); + } + } + function clear(node, suppressUnicodeCheck) { + textarea.blur(); + var sel = window.getSelection(); + sel.removeAllRanges(); + } + async function copyToClipboard(node, suppressUnicodeCheck) { + clear(); + var r = document.createRange(); + r.selectNode(node); + window.getSelection().addRange(r); + await copySelectionToClipboard(suppressUnicodeCheck); + } + function addRange(startNode, startIndex, endNode, endIndex) { + var sel = window.getSelection(); + var r = document.createRange(); + r.setStart(startNode, startIndex); + r.setEnd(endNode, endIndex); + sel.addRange(r); + } + async function copyRangeToClipboard( + startNode, + startIndex, + endNode, + endIndex, + suppressUnicodeCheck + ) { + clear(); + addRange(startNode, startIndex, endNode, endIndex); + await copySelectionToClipboard(suppressUnicodeCheck); + } + async function copyChildrenToClipboard(id) { + clear(); + window.getSelection().selectAllChildren(document.getElementById(id)); + await copySelectionToClipboard(); + } + function getClipboardData(mime) { + var transferable = SpecialPowers.Cc[ + "@mozilla.org/widget/transferable;1" + ].createInstance(SpecialPowers.Ci.nsITransferable); + transferable.init(getLoadContext()); + transferable.addDataFlavor(mime); + clipboard.getData( + transferable, + 1, + SpecialPowers.wrap(window).browsingContext.currentWindowContext + ); + var data = SpecialPowers.createBlankObject(); + transferable.getTransferData(mime, data); + return data; + } + function testHtmlClipboardValue(mime, expected) { + // For Windows, navigator.platform returns "Win32". + var expectedValue = expected; + if (navigator.platform.includes("Win")) { + // Windows has extra content. + var expectedValue = + kTextHtmlPrefixClipboardDataWindows + + expected.replace(/\n/g, "\n") + + kTextHtmlSuffixClipboardDataWindows; + } + testClipboardValue(mime, expectedValue); + } + function testClipboardValue(mime, expected) { + if (suppressHTMLCheck && mime == "text/html") { + return null; + } + var data = SpecialPowers.wrap(getClipboardData(mime)); + is( + data.value == null + ? data.value + : data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data, + expected, + mime + " value in the clipboard" + ); + return data.value; + } + function testPasteText(expected) { + textarea.value = ""; + textarea.focus(); + textarea.editor.paste(1); + is(textarea.value, expected, "value of the textarea after the paste"); + } + function testPasteHTML(id, expected) { + var contentEditable = $(id); + contentEditable.focus(); + synthesizeKey("v", { accelKey: true }); + is(contentEditable.innerHTML, expected, id + ".innerHtml after the paste"); + } + function testSelectionToString(expected) { + is( + window.getSelection().toString().replace(/\r\n/g, "\n"), + expected, + "Selection.toString" + ); + } + function testInnerHTML(id, expected) { + var value = document.getElementById(id).innerHTML; + is(value, expected, id + ".innerHTML"); + } + + await copyChildrenToClipboard("draggable"); + testSelectionToString("This is a draggable bit of text."); + testClipboardValue("text/plain", "This is a draggable bit of text."); + testHtmlClipboardValue( + "text/html", + '
    This is a draggable bit of text.
    ' + ); + testPasteText("This is a draggable bit of text."); + + await copyChildrenToClipboard("alist"); + testSelectionToString(" bla\n\n foo\n bar\n\n"); + testClipboardValue("text/plain", " bla\n\n foo\n bar\n\n"); + testHtmlClipboardValue( + "text/html", + '
    \n bla\n
      \n
    • foo
    • \n \n
    • bar
    • \n
    \n
    ' + ); + testPasteText(" bla\n\n foo\n bar\n\n"); + + await copyChildrenToClipboard("blist"); + testSelectionToString(" mozilla\n\n foo\n bar\n\n"); + testClipboardValue("text/plain", " mozilla\n\n foo\n bar\n\n"); + testHtmlClipboardValue( + "text/html", + '
    \n mozilla\n
      \n
    1. foo
    2. \n \n
    3. bar
    4. \n
    \n
    ' + ); + testPasteText(" mozilla\n\n foo\n bar\n\n"); + + await copyChildrenToClipboard("clist"); + testSelectionToString(" mzla\n\n foo\n bazzinga!\n bar\n\n"); + testClipboardValue( + "text/plain", + " mzla\n\n foo\n bazzinga!\n bar\n\n" + ); + testHtmlClipboardValue( + "text/html", + '
    \n mzla\n
      \n
    • foo
        \n
      • bazzinga!
      • \n
    • \n \n
    • bar
    • \n
    \n
    ' + ); + testPasteText(" mzla\n\n foo\n bazzinga!\n bar\n\n"); + + await copyChildrenToClipboard("div4"); + testSelectionToString(" Tt t t "); + testClipboardValue("text/plain", " Tt t t "); + if (isXHTML) { + testHtmlClipboardValue( + "text/html", + '
    \n T\n
    ' + ); + testInnerHTML( + "div4", + '\n T\n' + ); + } else { + testHtmlClipboardValue( + "text/html", + '
    \n T\n
    ' + ); + testInnerHTML("div4", "\n T\n"); + } + testPasteText(" Tt t t "); + + await copyChildrenToClipboard("div5"); + testSelectionToString(" T "); + testClipboardValue("text/plain", " T "); + if (isXHTML) { + testHtmlClipboardValue( + "text/html", + '
    \n T\n
    ' + ); + testInnerHTML( + "div5", + '\n T\n' + ); + } else { + testHtmlClipboardValue( + "text/html", + '
    \n T\n
    ' + ); + testInnerHTML("div5", "\n T\n"); + } + testPasteText(" T "); + + await copyRangeToClipboard( + $("div6").childNodes[0], + 0, + $("div6").childNodes[1], + 1, + suppressUnicodeCheckIfHidden + ); + testSelectionToString(""); + // START Disabled due to bug 564688 + if (false) { + testClipboardValue("text/plain", ""); + testClipboardValue("text/html", ""); + } + // END Disabled due to bug 564688 + testInnerHTML("div6", "div6"); + + await copyRangeToClipboard( + $("div7").childNodes[0], + 0, + $("div7").childNodes[0], + 4, + suppressUnicodeCheckIfHidden + ); + testSelectionToString(""); + // START Disabled due to bug 564688 + if (false) { + testClipboardValue("text/plain", ""); + testClipboardValue("text/html", ""); + } + // END Disabled due to bug 564688 + testInnerHTML("div7", "div7"); + + await copyRangeToClipboard( + $("div8").childNodes[0], + 0, + $("div8").childNodes[0], + 4, + suppressUnicodeCheckIfHidden + ); + testSelectionToString(""); + // START Disabled due to bug 564688 + if (false) { + testClipboardValue("text/plain", ""); + testClipboardValue("text/html", ""); + } + // END Disabled due to bug 564688 + testInnerHTML("div8", "div8"); + + await copyRangeToClipboard( + $("div9").childNodes[0], + 0, + $("div9").childNodes[0], + 4, + suppressUnicodeCheckIfHidden + ); + testSelectionToString("div9"); + testClipboardValue("text/plain", "div9"); + testHtmlClipboardValue("text/html", "div9"); + testInnerHTML("div9", "div9"); + + await copyToClipboard($("div10"), suppressUnicodeCheckIfHidden); + testSelectionToString(""); + testInnerHTML("div10", "div10"); + + await copyToClipboard($("div10").firstChild, suppressUnicodeCheckIfHidden); + testSelectionToString(""); + + await copyRangeToClipboard( + $("div10").childNodes[0], + 0, + $("div10").childNodes[0], + 1, + suppressUnicodeCheckIfHidden + ); + testSelectionToString(""); + + await copyRangeToClipboard( + $("div10").childNodes[1], + 0, + $("div10").childNodes[1], + 1, + suppressUnicodeCheckIfHidden + ); + testSelectionToString(""); + + if (!isXHTML) { + // ============ copy/paste multi-range selection (bug 1123505) + // with text start node + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + var ul = $("ul1"); + var parent = ul.parentNode; + r.setStart(parent, 0); + r.setEnd(parent.firstChild, 15); + sel.addRange(r); //
    {Copy1then Paste]
    • LI
    • \n
    + + r = document.createRange(); + r.setStart(ul, 1); + r.setEnd(parent, 2); + sel.addRange(r); //
    Copy1then Paste
    • LI{
    • \n
    }
    + await copySelectionToClipboard(true); + testPasteHTML("contentEditable1", "Copy1then Paste"); // The
      should not appear because it has no
    • s + + // with text end node + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + var ul = $("ul2"); + var parent = ul.parentNode; + r.setStart(parent, 0); + r.setEnd(ul, 1); + sel.addRange(r); //
      {
        \n}
      • LI
      Copy2then Paste
      + + r = document.createRange(); + r.setStart(parent.childNodes[1], 0); + r.setEnd(parent, 2); + sel.addRange(r); //
        \n
      • LI
      [Copy2then Paste}
      + await copySelectionToClipboard(true); + testPasteHTML("contentEditable2", "Copy2then Paste"); // The
        should not appear because it has no
      • s + + // with text end node and non-empty start + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + var ul = $("ul3"); + var parent = ul.parentNode; + r.setStart(parent, 0); + r.setEnd(ul, 1); + sel.addRange(r); //
        {
        • \n
        • }
        • LI
        Copy3then Paste
        + + r = document.createRange(); + r.setStart(parent.childNodes[1], 0); + r.setEnd(parent, 2); + sel.addRange(r); //
        • \n
        • LI
        [Copy3then Paste}
        + await copySelectionToClipboard(true); + testPasteHTML( + "contentEditable3", + '
        • \n
        Copy3then Paste' // The
          should appear because it has a
        • + ); + + // with elements of different depth + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + var div1 = $("div1s"); + var parent = div1.parentNode; + r.setStart(parent, 0); + r.setEnd(document.getElementById("div1se1"), 1); // after the "inner" DIV + sel.addRange(r); + + r = document.createRange(); + r.setStart(div1.childNodes[1], 0); // the start of "after" + r.setEnd(parent, 1); + sel.addRange(r); + await copySelectionToClipboard(true); + testPasteHTML( + "contentEditable4", + '
          before
          after
          ' + ); + + // with elements of different depth, and a text node at the end + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + var div1 = $("div2s"); + var parent = div1.parentNode; + r.setStart(parent, 0); + r.setEnd(document.getElementById("div2se1"), 1); // after the "inner" DIV + sel.addRange(r); + + r = document.createRange(); + r.setStart(div1.childNodes[1], 0); // the start of "after" + r.setEnd(parent, 1); + sel.addRange(r); + await copySelectionToClipboard(true); + testPasteHTML( + "contentEditable5", + '
          before
          after
          ' + ); + + // crash test for bug 1127835 + var e1 = document.getElementById("1127835crash1"); + var e2 = document.getElementById("1127835crash2"); + var e3 = document.getElementById("1127835crash3"); + var t1 = e1.childNodes[0]; + var t3 = e3.childNodes[0]; + + var sel = window.getSelection(); + sel.removeAllRanges(); + + var r = document.createRange(); + r.setStart(t1, 1); + r.setEnd(e2, 0); + sel.addRange(r); //
          \n1[
          }
          \n
          3\n
          + + r = document.createRange(); + r.setStart(e2, 1); + r.setEnd(t3, 0); + sel.addRange(r); //
          \n1
          \n
          {
          ]3\n
          + await copySelectionToClipboard(true); + testPasteHTML( + "contentEditable6", + '
          \n

          ' + ); // Don't strip the empty `` element because of avoiding any dataloss provided by the element + } + + // ============ copy/paste test from/to a textarea + + var val = "1\n 2\n 3"; + textarea.value = val; + textarea.select(); + await SimpleTest.promiseClipboardChange(textarea.value, () => { + textarea.editor.copy(); + }); + textarea.value = ""; + textarea.editor.paste(1); + is(textarea.value, val); + textarea.value = ""; + + // ============ NOSCRIPT should not be copied + + await copyChildrenToClipboard("div13"); + testSelectionToString("__"); + testClipboardValue("text/plain", "__"); + testHtmlClipboardValue("text/html", '
          __
          '); + testPasteText("__"); + + // ============ converting cell boundaries to tabs in tables + + await copyToClipboard($("tr1")); + testClipboardValue("text/plain", "foo\tbar"); + + if (!isXHTML) { + // ============ spanning multiple rows + + await copyRangeToClipboard($("tr2"), 0, $("tr3"), 0); + testClipboardValue("text/plain", "1\t2\n3\t4\n"); + testHtmlClipboardValue( + "text/html", + '
          12
          34
          ' + ); + + // ============ spanning multiple rows in multi-range selection + + clear(); + addRange($("tr2"), 0, $("tr2"), 2); + addRange($("tr3"), 0, $("tr3"), 2); + await copySelectionToClipboard(); + testClipboardValue("text/plain", "1\t2\n5\t6"); + testHtmlClipboardValue( + "text/html", + '
          12
          56
          ' + ); + } + + // ============ manipulating Selection in oncopy + + await copyRangeToClipboard( + $("div11").childNodes[0], + 0, + $("div11").childNodes[1], + 2 + ); + testClipboardValue("text/plain", "Xdiv11"); + testHtmlClipboardValue("text/html", "

          Xdiv11

          "); + + await new Promise(resolve => { + setTimeout(resolve, 0); + }); + testSelectionToString("div11"); + + await new Promise(resolve => { + setTimeout(resolve, 0); + }); + await copyRangeToClipboard( + $("div12").childNodes[0], + 0, + $("div12").childNodes[1], + 2 + ); + + testClipboardValue("text/plain", "Xdiv12"); + testHtmlClipboardValue("text/html", "

          Xdiv12

          "); + await new Promise(resolve => { + setTimeout(resolve, 0); + }); + testSelectionToString("div12"); + + await new Promise(resolve => { + setTimeout(resolve, 0); + }); + + if (!isXHTML) { + // ============ copy from ruby + + const ruby1 = $("ruby1"); + const ruby1Container = ruby1.parentNode; + + // Ruby annotation is included when selecting inside ruby. + await copyRangeToClipboard(ruby1, 0, ruby1, 6); + testClipboardValue("text/plain", "aabb(AABB)"); + + // Ruby annotation is ignored when selecting across ruby. + await copyRangeToClipboard(ruby1Container, 0, ruby1Container, 3); + testClipboardValue("text/plain", "XaabbY"); + + // ... unless converter.html2txt.always_include_ruby is set + await SpecialPowers.pushPrefEnv({ + set: [["converter.html2txt.always_include_ruby", true]], + }); + await copyRangeToClipboard(ruby1Container, 0, ruby1Container, 3); + testClipboardValue("text/plain", "Xaabb(AABB)Y"); + await SpecialPowers.popPrefEnv(); + } +} diff --git a/dom/base/test/delayedServerEvents.sjs b/dom/base/test/delayedServerEvents.sjs new file mode 100644 index 0000000000..0abf18da0b --- /dev/null +++ b/dom/base/test/delayedServerEvents.sjs @@ -0,0 +1,50 @@ +// this will take strings_to_send.length*500 ms = 5 sec + +var timer = null; +var strings_to_send = [ + "retry:999999999\ndata\r\n\nda", + "ta", + ":", + "de", + "layed1\n\n", + "", + "", + "data:delayed2\n\n", + "", + "", +]; +var resp = null; + +function sendNextString() { + if (!strings_to_send.length) { + timer.cancel(); + resp.finish(); + timer = null; + resp = null; + return; + } + + try { + resp.write(strings_to_send.shift()); + } catch (e) { + timer.cancel(); + timer = null; + resp = null; + } +} + +function handleRequest(request, response) { + var bytes = strings_to_send.reduce((len, s) => len + s.length, 0); + + response.seizePower(); + response.write("HTTP/1.1 200 OK\r\n"); + response.write(`Content-Length: ${bytes}\r\n`); + response.write("Content-Type: text/event-stream; charset=utf-8\r\n"); + response.write("Cache-Control: no-cache, must-revalidate\r\n"); + response.write("\r\n"); + + resp = response; + + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback(sendNextString, 500, Ci.nsITimer.TYPE_REPEATING_SLACK); +} diff --git a/dom/base/test/dummy.html b/dom/base/test/dummy.html new file mode 100644 index 0000000000..1a87e28408 --- /dev/null +++ b/dom/base/test/dummy.html @@ -0,0 +1,9 @@ + + +Dummy test page + + + +

          Dummy test page

          + + diff --git a/dom/base/test/embed_bug455472.html b/dom/base/test/embed_bug455472.html new file mode 100644 index 0000000000..d244ea9396 --- /dev/null +++ b/dom/base/test/embed_bug455472.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/empty.html b/dom/base/test/empty.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/base/test/eventsource.resource b/dom/base/test/eventsource.resource new file mode 100644 index 0000000000..856e3b1aff --- /dev/null +++ b/dom/base/test/eventsource.resource @@ -0,0 +1,22 @@ +:this file must be enconded in utf8 +:and its Content-Type must be equal to text/event-stream + +retry:500 +data: 1 +unknow: unknow + +event: other_event_name +retry:500 +data: 1 +unknow: unknow + +event: click +retry:500 + +event: blur +retry:500 + +event:keypress +retry:500 + + diff --git a/dom/base/test/eventsource.resource^headers^ b/dom/base/test/eventsource.resource^headers^ new file mode 100644 index 0000000000..6a63b5341d --- /dev/null +++ b/dom/base/test/eventsource.resource^headers^ @@ -0,0 +1,3 @@ +Content-Type: text/event-stream +Cache-Control: no-cache, must-revalidate + diff --git a/dom/base/test/eventsource_message.sjs b/dom/base/test/eventsource_message.sjs new file mode 100644 index 0000000000..d52e2ee432 --- /dev/null +++ b/dom/base/test/eventsource_message.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) { + var match = request.queryString.match(/^status=(.*)$/); + var status = match ? +match[1] : 200; + + if (status != 200) { + response.setStatusLine(request.httpVersion, status, "Err"); + } + response.setHeader("Content-Type", "text/event-stream"); + response.setHeader("Cache-Control", "no-cache"); + response.write("data: msg 1\n"); + response.write("id: 1\n\n"); +} diff --git a/dom/base/test/eventsource_reconnect.sjs b/dom/base/test/eventsource_reconnect.sjs new file mode 100644 index 0000000000..6627fefa9f --- /dev/null +++ b/dom/base/test/eventsource_reconnect.sjs @@ -0,0 +1,18 @@ +function handleRequest(request, response) { + var name = "eventsource_reconnecting_" + request.queryString; + var reconnecting = getState(name); + var body = ""; + if (!reconnecting) { + body = "retry: 2\n"; + setState(name, "0"); + } else if (reconnecting === "0") { + setState(name, ""); + response.setStatusLine(request.httpVersion, 204, "No Content"); + } + + response.setHeader("Content-Type", "text/event-stream"); + response.setHeader("Cache-Control", "no-cache"); + + body += "data: 1\n\n"; + response.write(body); +} diff --git a/dom/base/test/eventsource_redirect.resource b/dom/base/test/eventsource_redirect.resource new file mode 100644 index 0000000000..d073527bfb --- /dev/null +++ b/dom/base/test/eventsource_redirect.resource @@ -0,0 +1,2 @@ +redirected + diff --git a/dom/base/test/eventsource_redirect.resource^headers^ b/dom/base/test/eventsource_redirect.resource^headers^ new file mode 100644 index 0000000000..eb79e2f814 --- /dev/null +++ b/dom/base/test/eventsource_redirect.resource^headers^ @@ -0,0 +1,3 @@ +HTTP 301 Moved Permanently +Location: eventsource_redirect_to.resource + diff --git a/dom/base/test/eventsource_redirect_to.resource b/dom/base/test/eventsource_redirect_to.resource new file mode 100644 index 0000000000..1eb4081ac1 --- /dev/null +++ b/dom/base/test/eventsource_redirect_to.resource @@ -0,0 +1,4 @@ +retry:500 +data: 1 + + diff --git a/dom/base/test/eventsource_redirect_to.resource^headers^ b/dom/base/test/eventsource_redirect_to.resource^headers^ new file mode 100644 index 0000000000..6a63b5341d --- /dev/null +++ b/dom/base/test/eventsource_redirect_to.resource^headers^ @@ -0,0 +1,3 @@ +Content-Type: text/event-stream +Cache-Control: no-cache, must-revalidate + diff --git a/dom/base/test/eventsource_worker.js b/dom/base/test/eventsource_worker.js new file mode 100644 index 0000000000..863d52eec1 --- /dev/null +++ b/dom/base/test/eventsource_worker.js @@ -0,0 +1,6 @@ +const es = new EventSource( + "http://mochi.test:8888/tests/dom/base/test/eventsource_message.sjs" +); +es.onmessage = function () { + es.close(); +}; diff --git a/dom/base/test/fake_plugin.tst b/dom/base/test/fake_plugin.tst new file mode 100644 index 0000000000..b3d41aed8d --- /dev/null +++ b/dom/base/test/fake_plugin.tst @@ -0,0 +1 @@ +This is used in test_object.html to test loading by extension (.tst -> application/x-test). diff --git a/dom/base/test/file1_setting_opener.html b/dom/base/test/file1_setting_opener.html new file mode 100644 index 0000000000..6bc319bc9e --- /dev/null +++ b/dom/base/test/file1_setting_opener.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file2_setting_opener.html b/dom/base/test/file2_setting_opener.html new file mode 100644 index 0000000000..b0f383ad23 --- /dev/null +++ b/dom/base/test/file2_setting_opener.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file3_setting_opener.html b/dom/base/test/file3_setting_opener.html new file mode 100644 index 0000000000..a40a0706f9 --- /dev/null +++ b/dom/base/test/file3_setting_opener.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file4_setting_opener.html b/dom/base/test/file4_setting_opener.html new file mode 100644 index 0000000000..50b5b54a0e --- /dev/null +++ b/dom/base/test/file4_setting_opener.html @@ -0,0 +1 @@ +Loaded diff --git a/dom/base/test/file_audioLoop.html b/dom/base/test/file_audioLoop.html new file mode 100644 index 0000000000..d680c9a58f --- /dev/null +++ b/dom/base/test/file_audioLoop.html @@ -0,0 +1,2 @@ + +
          Mozilla Bug 1100912 +

          + +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                  
          1. +
          3 4
          +
          rtl on host
          2. +
          3 4
          +
          rtl on host, ltr slot's parent
          3. +
          3 4
          +
          rtl on host, ltr on slot
          4. +
          1 2
          +
          auto host, rtl in shadow
          5. +
          أخبار
          +
          auto host, rtl in host (in assigned node)
          6. +
          أخبار
          +
          auto host, rtl in host, no assigned node
          7. +
          أخبار
          +
          auto host, rtl in host, explicit ltr in shadow
          8. +
          ‎1 2 أخبار
          +
          auto host, ltr in host, rtl in host, reverse order in slots
          9. +
          أخبار
          +
          auto host, rtl in host (in assigned text node)
          10. +
          1 2
          +
          auto host, 1 2 in host (in assigned text node)
          + + + \ No newline at end of file diff --git a/dom/base/test/file_bug1198095.js b/dom/base/test/file_bug1198095.js new file mode 100644 index 0000000000..b966f1983b --- /dev/null +++ b/dom/base/test/file_bug1198095.js @@ -0,0 +1,39 @@ +/* eslint-env mozilla/chrome-script */ + +// eslint-disable-next-line mozilla/reject-importGlobalProperties +Cu.importGlobalProperties(["File"]); + +function createFileWithData(message) { + var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService( + Ci.nsIProperties + ); + var testFile = dirSvc.get("ProfD", Ci.nsIFile); + testFile.append("fileAPItestfileBug1198095"); + + var outStream = Cc[ + "@mozilla.org/network/file-output-stream;1" + ].createInstance(Ci.nsIFileOutputStream); + outStream.init( + testFile, + 0x02 | 0x08 | 0x20, // write, create, truncate + 0o666, + 0 + ); + + outStream.write(message, message.length); + outStream.close(); + + return File.createFromNsIFile(testFile); +} + +addMessageListener("file.open", function (message) { + createFileWithData(message).then(function (file) { + sendAsyncMessage("file.opened", file); + }); +}); + +addMessageListener("file.modify", function (message) { + createFileWithData(message).then(function (file) { + sendAsyncMessage("file.modified", file); + }); +}); diff --git a/dom/base/test/file_bug1250148.sjs b/dom/base/test/file_bug1250148.sjs new file mode 100644 index 0000000000..5f8037a08a --- /dev/null +++ b/dom/base/test/file_bug1250148.sjs @@ -0,0 +1,73 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function utf8decode(s) { + return decodeURIComponent(escape(s)); +} + +function utf8encode(s) { + return unescape(encodeURIComponent(s)); +} + +function handleRequest(request, response) { + var bodyStream = new BinaryInputStream(request.bodyInputStream); + + var requestBody = ""; + while ((bodyAvail = bodyStream.available()) > 0) { + requestBody += bodyStream.readBytes(bodyAvail); + } + + var result = []; + + if (request.method == "POST") { + var contentTypeParams = {}; + request + .getHeader("Content-Type") + .split(/\s*\;\s*/) + .forEach(function (str) { + if (str.indexOf("=") >= 0) { + let [name, value] = str.split("="); + contentTypeParams[name] = value; + } else { + contentTypeParams[""] = str; + } + }); + + if ( + contentTypeParams[""] == "multipart/form-data" && + request.queryString == "" + ) { + requestBody + .split("--" + contentTypeParams.boundary) + .slice(1, -1) + .forEach(function (s) { + let headers = {}; + let headerEnd = s.indexOf("\r\n\r\n"); + s.substr(2, headerEnd - 2) + .split("\r\n") + .forEach(function (str) { + // We're assuming UTF8 for now + let [name, value] = str.split(": "); + headers[name] = utf8decode(value); + }); + + let body = s.substring(headerEnd + 4, s.length - 2); + if ( + !headers["Content-Type"] || + headers["Content-Type"] == "text/plain" + ) { + // We're assuming UTF8 for now + body = utf8decode(body); + } + result.push({ headers, body }); + }); + } + } + + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write(utf8encode(JSON.stringify(result))); +} diff --git a/dom/base/test/file_bug1268962.sjs b/dom/base/test/file_bug1268962.sjs new file mode 100644 index 0000000000..66559d7d2e --- /dev/null +++ b/dom/base/test/file_bug1268962.sjs @@ -0,0 +1,92 @@ +// Test server for bug 1268962 +"use strict"; + +const HTTPStatus = new Map([ + [100, "Continue"], + [101, "Switching Protocol"], + [200, "OK"], + [201, "Created"], + [202, "Accepted"], + [203, "Non-Authoritative Information"], + [204, "No Content"], + [205, "Reset Content"], + [206, "Partial Content"], + [300, "Multiple Choice"], + [301, "Moved Permanently"], + [302, "Found"], + [303, "See Other"], + [304, "Not Modified"], + [305, "Use Proxy"], + [306, "unused"], + [307, "Temporary Redirect"], + [308, "Permanent Redirect"], + [400, "Bad Request"], + [401, "Unauthorized"], + [402, "Payment Required"], + [403, "Forbidden"], + [404, "Not Found"], + [405, "Method Not Allowed"], + [406, "Not Acceptable"], + [407, "Proxy Authentication Required"], + [408, "Request Timeout"], + [409, "Conflict"], + [410, "Gone"], + [411, "Length Required"], + [412, "Precondition Failed"], + [413, "Request Entity Too Large"], + [414, "Request-URI Too Long"], + [415, "Unsupported Media Type"], + [416, "Requested Range Not Satisfiable"], + [417, "Expectation Failed"], + [500, "Internal Server Error"], + [501, "Not Implemented"], + [502, "Bad Gateway"], + [503, "Service Unavailable"], + [504, "Gateway Timeout"], + [505, "HTTP Version Not Supported"], +]); + +const SAME_ORIGIN = + "http://mochi.test:8888/tests/dom/base/test/file_bug1268962.sjs"; +const CROSS_ORIGIN = + "http://example.com/tests/dom/base/test/file_bug1268962.sjs"; + +function handleRequest(request, response) { + const queryMap = new URLSearchParams(request.queryString); + + // Check redirection before everything else. + if (queryMap.has("redirect")) { + let redirect = queryMap.get("redirect"); + let location; + if (redirect == "sameorigin") { + location = SAME_ORIGIN; + } else if (redirect == "crossorigin") { + location = CROSS_ORIGIN; + } + + if (location) { + // Use HTTP 302 redirection. + response.setStatusLine("1.1", 302, HTTPStatus.get(302)); + + // Forward query strings except the redirect option. + queryMap.delete("redirect"); + response.setHeader("Location", location + "?" + queryMap.toString()); + + return; + } + } + + if (queryMap.has("statusCode")) { + let statusCode = parseInt(queryMap.get("statusCode")); + let statusText = HTTPStatus.get(statusCode); + response.setStatusLine("1.1", statusCode, statusText); + } + if (queryMap.has("cacheControl")) { + let cacheControl = queryMap.get("cacheControl"); + response.setHeader("Cache-Control", cacheControl); + } + if (queryMap.has("allowOrigin")) { + let allowOrigin = queryMap.get("allowOrigin"); + response.setHeader("Access-Control-Allow-Origin", allowOrigin); + } +} diff --git a/dom/base/test/file_bug1274806.html b/dom/base/test/file_bug1274806.html new file mode 100644 index 0000000000..62bef3044b --- /dev/null +++ b/dom/base/test/file_bug1274806.html @@ -0,0 +1,33 @@ + + + + + + + + +

          + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur elit nisi, convallis sed scelerisque sit amet, vestibulum eu odio. Pellentesque et quam et nibh sollicitudin rutrum. Fusce tristique hendrerit ligula, et euismod sapien facilisis quis. Donec tincidunt turpis tortor, in pharetra tellus euismod ac. Vestibulum consectetur nulla lacinia, consectetur mauris ac, tempus libero. Nam non dui id enim dapibus porta id sed lectus. Praesent at suscipit neque. Vestibulum tellus lorem, placerat et volutpat sed, elementum eget lacus. Sed interdum nisi et imperdiet varius. Sed non magna odio. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus velit risus, accumsan nec efficitur nec, semper sed arcu. Praesent consectetur lectus justo, fringilla imperdiet neque lobortis id. Donec efficitur pulvinar finibus. + +

          +

          test

          + + diff --git a/dom/base/test/file_bug1303838.html b/dom/base/test/file_bug1303838.html new file mode 100644 index 0000000000..d11444a449 --- /dev/null +++ b/dom/base/test/file_bug1303838.html @@ -0,0 +1,34 @@ + + + + + + Tests for tab switching on link clicks. + + + + Link 1, + Link 2, + Link 3, + Link 4, + Link 5, + Link 6, + Link 7, + Anchor Link 1, + Anchor Link 2, + Anchor Link 3, + Frame Link 1, + Frame Link 2, + Frame Link 3, + + diff --git a/dom/base/test/file_bug1303838_target.html b/dom/base/test/file_bug1303838_target.html new file mode 100644 index 0000000000..b1c8871f6b --- /dev/null +++ b/dom/base/test/file_bug1303838_target.html @@ -0,0 +1,21 @@ + + + + + + Tests for tab switching on link clicks. + + +
          Foo
          +
          Bar
          +
          Baz
          + + + + diff --git a/dom/base/test/file_bug1303838_target_bar.html b/dom/base/test/file_bug1303838_target_bar.html new file mode 100644 index 0000000000..2f1aa2bdef --- /dev/null +++ b/dom/base/test/file_bug1303838_target_bar.html @@ -0,0 +1 @@ +bar diff --git a/dom/base/test/file_bug1303838_target_baz.html b/dom/base/test/file_bug1303838_target_baz.html new file mode 100644 index 0000000000..7b4e4c0ef3 --- /dev/null +++ b/dom/base/test/file_bug1303838_target_baz.html @@ -0,0 +1 @@ +baz diff --git a/dom/base/test/file_bug1303838_target_foo.html b/dom/base/test/file_bug1303838_target_foo.html new file mode 100644 index 0000000000..f0ab6775c0 --- /dev/null +++ b/dom/base/test/file_bug1303838_target_foo.html @@ -0,0 +1 @@ +foo diff --git a/dom/base/test/file_bug1303838_target_ibar.html b/dom/base/test/file_bug1303838_target_ibar.html new file mode 100644 index 0000000000..4832b38ce6 --- /dev/null +++ b/dom/base/test/file_bug1303838_target_ibar.html @@ -0,0 +1 @@ +ibar diff --git a/dom/base/test/file_bug1303838_target_ibaz.html b/dom/base/test/file_bug1303838_target_ibaz.html new file mode 100644 index 0000000000..243b786a5b --- /dev/null +++ b/dom/base/test/file_bug1303838_target_ibaz.html @@ -0,0 +1 @@ +ibaz diff --git a/dom/base/test/file_bug1303838_target_ifoo.html b/dom/base/test/file_bug1303838_target_ifoo.html new file mode 100644 index 0000000000..b6c3a90e2e --- /dev/null +++ b/dom/base/test/file_bug1303838_target_ifoo.html @@ -0,0 +1 @@ +ifoo diff --git a/dom/base/test/file_bug1303838_with_iframe.html b/dom/base/test/file_bug1303838_with_iframe.html new file mode 100644 index 0000000000..d949ad7383 --- /dev/null +++ b/dom/base/test/file_bug1303838_with_iframe.html @@ -0,0 +1,13 @@ + + + + + + Tests for tab switching on link clicks. + + + + + diff --git a/dom/base/test/file_bug1554070_1.html b/dom/base/test/file_bug1554070_1.html new file mode 100644 index 0000000000..0294485293 --- /dev/null +++ b/dom/base/test/file_bug1554070_1.html @@ -0,0 +1,14 @@ + + + + + + Test for Bug 1554070 + + + + file_bug1554070_2.html + + diff --git a/dom/base/test/file_bug1554070_2.html b/dom/base/test/file_bug1554070_2.html new file mode 100644 index 0000000000..9287f535d4 --- /dev/null +++ b/dom/base/test/file_bug1554070_2.html @@ -0,0 +1,13 @@ + + + + + + Test for Bug 1554070 + + + example.org + + diff --git a/dom/base/test/file_bug1639328.html b/dom/base/test/file_bug1639328.html new file mode 100644 index 0000000000..97c96cf96c --- /dev/null +++ b/dom/base/test/file_bug1639328.html @@ -0,0 +1,8 @@ + + diff --git a/dom/base/test/file_bug1691214.html b/dom/base/test/file_bug1691214.html new file mode 100644 index 0000000000..e370166598 --- /dev/null +++ b/dom/base/test/file_bug1691214.html @@ -0,0 +1,4 @@ + +Open in window. +
          +Open in window. diff --git a/dom/base/test/file_bug1700871.html b/dom/base/test/file_bug1700871.html new file mode 100644 index 0000000000..3bc1808c66 --- /dev/null +++ b/dom/base/test/file_bug1700871.html @@ -0,0 +1,18 @@ + +Open in window. +
          + + +
          + diff --git a/dom/base/test/file_bug1703472.html b/dom/base/test/file_bug1703472.html new file mode 100644 index 0000000000..9607663bc3 --- /dev/null +++ b/dom/base/test/file_bug1703472.html @@ -0,0 +1,6 @@ + + + + diff --git a/dom/base/test/file_bug28293.sjs b/dom/base/test/file_bug28293.sjs new file mode 100644 index 0000000000..1b3e19402d --- /dev/null +++ b/dom/base/test/file_bug28293.sjs @@ -0,0 +1,4 @@ +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + response.write(decodeURIComponent(request.queryString)); +} diff --git a/dom/base/test/file_bug326337.xml b/dom/base/test/file_bug326337.xml new file mode 100644 index 0000000000..d328051e74 --- /dev/null +++ b/dom/base/test/file_bug326337.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_bug326337_inner.html b/dom/base/test/file_bug326337_inner.html new file mode 100644 index 0000000000..01a1929ac8 --- /dev/null +++ b/dom/base/test/file_bug326337_inner.html @@ -0,0 +1,44 @@ + + + + + Inner file for Bug 326337 + + + + + + diff --git a/dom/base/test/file_bug326337_outer.html b/dom/base/test/file_bug326337_outer.html new file mode 100644 index 0000000000..9d63f72632 --- /dev/null +++ b/dom/base/test/file_bug326337_outer.html @@ -0,0 +1,15 @@ + + + + + + + diff --git a/dom/base/test/file_bug357450.js b/dom/base/test/file_bug357450.js new file mode 100644 index 0000000000..6d0d703e78 --- /dev/null +++ b/dom/base/test/file_bug357450.js @@ -0,0 +1,74 @@ +/** Test for Bug 357450 **/ + +SimpleTest.waitForExplicitFinish(); + +function testGetElements(root, classtestCount) { + ok(root.getElementsByClassName, "getElementsByClassName exists"); + is( + typeof root.getElementsByClassName, + "function", + "getElementsByClassName is a function" + ); + + var nodes = root.getElementsByClassName("f"); + + is(typeof nodes.item, "function"); + is(typeof nodes.length, "number"); + is(nodes.length, 0, "string with no matching class should get an empty list"); + + nodes = root.getElementsByClassName("foo"); + ok(nodes, "should have nodelist object"); + + // HTML5 says ints are allowed in class names + // should match int class + + nodes = root.getElementsByClassName("1"); + is(nodes[0], $("int-class"), "match integer class name"); + nodes = root.getElementsByClassName([1]); + is(nodes[0], $("int-class"), "match integer class name 2"); + nodes = root.getElementsByClassName(["1 junk"]); + + is(nodes.length, 0, "two classes, but no elements have both"); + + nodes = root.getElementsByClassName("test1"); + is(nodes[0], $("test1"), "Id and class name turn up the same node"); + nodes = root.getElementsByClassName("test1 test2"); + is(nodes.length, 0, "two classes, but no elements have both"); + + // WHATWG examples + nodes = document.getElementById("example").getElementsByClassName("aaa"); + is(nodes.length, 2, "returns 2 elements"); + + nodes = document.getElementById("example").getElementsByClassName("ccc bbb"); + is( + nodes.length, + 1, + "only match elements that have all the classes specified in that array. tokenize string arg." + ); + is(nodes[0], $("p3"), "matched tokenized string"); + + nodes = document.getElementById("example").getElementsByClassName(""); + is(nodes.length, 0, "class name with empty string shouldn't return nodes"); + + nodes = root.getElementsByClassName({}); + ok(nodes, "bogus arg shouldn't be null"); + is(typeof nodes.item, "function"); + is(typeof nodes.length, "number"); + is(nodes.length, 0, "bogus arg should get an empty nodelist"); +} + +addLoadEvent(function () { + if (document.getElementsByName) { + var anchorNodes = document.getElementsByName("nametest"); + is(anchorNodes.length, 1, "getElementsByName still works"); + is( + anchorNodes[0].getAttribute("name"), + "nametest", + "getElementsByName still works" + ); + } + testGetElements($("content"), 1); + testGetElements(document.documentElement, 3); + testGetElements(document, 3); +}); +addLoadEvent(SimpleTest.finish); diff --git a/dom/base/test/file_bug416317.xhtml b/dom/base/test/file_bug416317.xhtml new file mode 100644 index 0000000000..148cb6bd53 --- /dev/null +++ b/dom/base/test/file_bug416317.xhtml @@ -0,0 +1,1469 @@ + + + + + selectorTest + + + body { background-color: green; } + .test > .blox1 { background-color: lime; } + + /* test 2 : attribute existence selector */ + /* attribute with a value */ + .blox2[align] { background-color: lime; } + /* attribute with empty value */ + .blox3[align] { background-color: lime; } + /* attribute with almost similar name */ + .blox4, .blox5 { background-color: lime } + .blox4[align], .blox5[align] { background-color: red; } + + /* test3 : attribute value selector */ + .blox6[align="center"] { background-color: lime; } + .blox6[align="c"] { background-color: red; } + .blox6[align="centera"] { background-color: red; } + .blox6[foo="\e9"] { background-color: lime; } + .blox6[\_foo="\e9"] { background-color: lime; } + + /* test 4 : [~=] */ + .blox7[class~="foo"] { background-color: lime; } + .blox8, .blox9, .blox10 { background-color: lime; } + .blox8[class~=""] { background-color: red; } + .blox9[foo~=""] { background-color: red; } + .blox10[foo~="foo"] { background-color: red; } + + /* test5 [^=] */ + .attrStart > .t3 { background-color: lime; } + .attrStart > .t1[class^="unit"] { background-color: lime; } + .attrStart > .t2 { background-color: lime; } + .attrStart > .t2[class^="nit"] { background-color: red; } + .attrStart > .t3[align^=""] { background-color: red; } + .attrStart > .t4[foo^="\e9"] { background-color: lime; } + + /* test6 [$=] */ + .attrEnd > .t3 { background-color: lime; } + .attrEnd > .t1[class$="t1"] { background-color: lime; } + .attrEnd > .t2 { background-color: lime; } + .attrEnd > .t2[class$="unit"] { background-color: red; } + .attrEnd > .t3[align$=""] { background-color: red; } + .attrEnd > .t4[foo$="\e9"] { background-color: lime; } + + /* test7 [*=] */ + .attrMiddle > .t3 { background-color: lime; } + .attrMiddle > .t1[class*="t t"] { background-color: lime; } + .attrMiddle > .t2 { background-color: lime; } + .attrMiddle > .t2[class*="a"] { background-color: red; } + .attrMiddle > .t3[align*=""] { background-color: red; } + .attrMiddle > .t4[foo*="\e9"] { background-color: lime; } + + /* :first-child tests */ + .firstChild .unitTest:first-child { background-color: lime; } + .blox12:first-child { background-color: red; } + .blox13:first-child { background-color: red; } + .blox12, .blox13 { background-color: lime } + + /* :root tests */ + :root { background-color: green; } + + /* :scope tests */ + :scope { background-color: green; } + + /* :nth-child(n) tests */ + .nthchild1 > :nth-last-child(odd) { background-color: lime; } + .nthchild1 > :nth-child(odd) { background-color: lime; } + + .nthchild2 > :nth-last-child(even) { background-color: lime; } + .nthchild2 > :nth-child(even) { background-color: lime; } + + .nthchild3 > :nth-child(3n+2) { background-color: lime; } + .nthchild3 > :nth-last-child(3n+1) { background-color: lime; } + .nthchild3 > :nth-last-child(3n+3) { background-color: lime; } + + .nthoftype1 > div:nth-of-type(odd) { background-color: lime; } + .nthoftype1 > div:nth-last-of-type(odd) { background-color: lime; } + .nthoftype1 > p { background-color: green; } + + .nthoftype2 > div:nth-of-type(even) { background-color: lime; } + .nthoftype2 > div:nth-last-of-type(even) { background-color: lime; } + .nthoftype2 > p { background-color: green; } + + .nthoftype3 > div:nth-of-type(3n+1) { background-color: lime; } + .nthoftype3 > div:nth-last-of-type(3n+1) { background-color: lime; } + .nthoftype3 > div:nth-last-of-type(3n+2) { background-color: lime; } + .nthoftype3 > p { background-color: green; } + + /* :not() tests */ + .blox14:not(span) { background-color: lime; } + .blox15:not([foo="blox14"]) { background-color: lime; } + .blox16:not(.blox15) { background-color: lime; } + + /* :only-of-type tests */ + .blox17:only-of-type { background-color: lime; } + .blox18:only-of-type { background-color: red; } + .blox18:not(:only-of-type) { background-color: lime; } + + /* :last-child tests */ + .lastChild > :last-child { background-color: lime } + .lastChild > :not(:last-child) { background-color: lime } + + /* :first-of-type tests */ + .firstOfType > *:first-of-type { background-color: lime; } + *.firstOfType > :not(:first-of-type) { background-color: lime; } + + /* :last-of-type tests */ + .lastOfType > *:last-of-type { background-color: lime; } + *.lastOfType > :not(:last-of-type) { background-color: lime; } + + /* :only-child tests */ + .onlyChild > *:not(:only-child) { background-color: lime; } + .onlyChild > .unitTest > *:only-child { background-color: lime; } + + /* :only-of-type tests */ + .onlyOfType *:only-of-type { background-color: lime; } + .onlyOfType *:not(:only-of-type) { background-color: lime; } + + /* :empty tests */ + .empty > *.isEmpty:empty { background-color: lime; color: lime; } + .empty > .isNotEmpty { background-color: blue; color: blue; } + .empty > .isNotEmpty:empty { background-color: red; color: red; } + .empty > .isNotEmpty:not(:empty) { background-color: lime; color: lime; } + + /* :lang() tests */ + .lang :lang(en) { background-color: lime; } + .lang :lang(fr) { background-color: lime; } + .lang .t1 { background-color: blue; } + .lang .t1:lang(es) { background-color: lime; } + .lang :lang(es-AR) { background-color: red; } + + /* [|=] tests */ + .attrLang .t1 { background-color: lime; } + .attrLang .t1[lang|="en"] { background-color: red; } + .attrLang [lang|="fr"] { background-color: lime; } + .attrLang .t2[lang|="en"] { background-color: lime; } + .attrLang .t3 { background-color: blue; } + .attrLang .t3[lang|="es"] { background-color: lime; } + .attrLang [lang|="es-AR"] { background-color: red; } + + /* UI tests */ + .UI .t1:enabled > .unitTest { background-color: lime; } + .UI .t2:disabled > .unitTest { background-color: lime; } + .UI .t3:checked + div { background-color: lime; } + .UI .t4:not(:checked) + div { background-color: lime; } + + /* ~ combinator tests */ + .tilda .t1 { background-color: white; } + .tilda .t1 ~ .unitTest { background-color: lime; } + .tilda .t1:hover ~ .unitTest { background-color: red; } + + /* ~ combinator tests */ + .plus .t1, .plus .t2 { background-color: white; } + .plus .t1 + .unitTest + .unitTest { background-color: lime; } + .plus .t1:hover + .unitTest + .unitTest { background-color: red; } + ]]> + + /* Tests from http://www.w3.org/Style/CSS/Test/CSS3/Selectors/20060307/html/index.html */ + + div, { background: red; } + .5cm { background: red; } + [*=test] { background: red; } + [*|*=test] { background: red; } + + div:subject { background: red; } + :canvas { background: red; } + :viewport { background: red; } + :window { background: red; } + :menu { background: red; } + :table { background: red; } + :select { background: red; } + ::canvas { background: red; } + ::viewport { background: red; } + ::window { background: red; } + ::menu { background: red; } + ::table { background: red; } + ::select { background: red; } + + ..test { background: red; color: yellow; } + .foo..quux { background: red; color: yellow; } + .bar. { background: red; color: yellow; } + + + + +

          Selectors API Test Suite

          +

          Testrunner by John Resig, tests by John Resig, Disruptive Innovations, W3C CSS Working Group, jQuery JavaScript Library.

          +
          +
          +

          CSS 3 Selectors tests

          +

          (c) Disruptive Innovations 2008
          + Last update: 2008-06-06

          +
          + +
          +
          +
          + +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +

          +

          +
          + +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          + +
          +
          +

          +

          +
          +

          +
          +
          +
          +
          +
          +

          +

          +
          +

          +
          +
          +
          +
          +
          +

          +

          +
          +

          +
          +
          +

          +
          +
          +
          + +
          +

          +
            +
          + +
          +

          +
          +

          +
          +
          + +
          +

          +
          +

          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +

          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
           
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          + + +
          +
          +
          + the previous square should be green when the checkbox is checked and become red when you uncheck it +
          +
          +
          + the previous square should be green when the checkbox is NOT checked and become red when you check it +
          + +
          +
          +
          +
          +
          + the three last squares should be green and become red when the pointer hovers over the white square +
          +
          +
          +
          +
          + the last square should be green and become red when the pointer hovers over the FIRST white square +
          +
          +
          +
          +

          CSS 3 Selectors tests

          +

          (c) Disruptive Innovations 2008
          + Last update: 2008-06-06

          +
          + +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          + +
          +
          +

          +

          +
          + +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          + +
          +
          +

          +

          +
          +

          +
          +
          +
          +
          +
          +

          +

          +
          +

          +
          +
          +
          +
          +
          +

          +

          +
          +

          +
          +
          +

          +
          +
          +
          + +
          +

          +
            +
          + +
          +

          +
          +

          +
          +
          + +
          +

          +
          +

          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          +

          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
           
          +
          + +
          +
          +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + +
          + + +
          +
          +
          + the previous square should be green when the checkbox is checked and become red when you uncheck it +
          +
          +
          + the previous square should be green when the checkbox is NOT checked and become red when you check it +
          + +
          +
          +
          +
          +
          + the three last squares should be green and become red when the pointer hovers over the white square +
          +
          +
          +
          +
          + the last square should be green and become red when the pointer hovers over the FIRST white square +
          +
          +
          +
          + + + Example circle01 - circle filled with red and stroked with blue + + + + + + Example circle01 - circle filled with red and stroked with blue + + + + + + Example circle01 - circle filled with red and stroked with blue + + + +
          + +

          jQuery Test Suite

          + +

          + + +
          + +
          +
          + + + + + + + + +
            +
            +
              + + diff --git a/dom/base/test/file_bug426646-1.html b/dom/base/test/file_bug426646-1.html new file mode 100644 index 0000000000..4319311b08 --- /dev/null +++ b/dom/base/test/file_bug426646-1.html @@ -0,0 +1,37 @@ + +Bug 426646, Using location.replace breaks iframe history + + + + diff --git a/dom/base/test/file_bug426646-2.html b/dom/base/test/file_bug426646-2.html new file mode 100644 index 0000000000..2da090b32f --- /dev/null +++ b/dom/base/test/file_bug426646-2.html @@ -0,0 +1,65 @@ + +Bug 426646, Using location.replace breaks iframe history + + + + diff --git a/dom/base/test/file_bug428847-1.xhtml b/dom/base/test/file_bug428847-1.xhtml new file mode 100644 index 0000000000..b88701ece2 --- /dev/null +++ b/dom/base/test/file_bug428847-1.xhtml @@ -0,0 +1,4 @@ + + + + diff --git a/dom/base/test/file_bug428847-2.xhtml b/dom/base/test/file_bug428847-2.xhtml new file mode 100644 index 0000000000..75c60b7792 --- /dev/null +++ b/dom/base/test/file_bug428847-2.xhtml @@ -0,0 +1,4 @@ + + + + diff --git a/dom/base/test/file_bug498897.css b/dom/base/test/file_bug498897.css new file mode 100644 index 0000000000..84beffdefc --- /dev/null +++ b/dom/base/test/file_bug498897.css @@ -0,0 +1 @@ +body { background: orange; } diff --git a/dom/base/test/file_bug498897.html b/dom/base/test/file_bug498897.html new file mode 100644 index 0000000000..b0d36f4ca5 --- /dev/null +++ b/dom/base/test/file_bug498897.html @@ -0,0 +1,23 @@ + + + Testcase for bug 498897 + + + + + diff --git a/dom/base/test/file_bug498897.html^headers^ b/dom/base/test/file_bug498897.html^headers^ new file mode 100644 index 0000000000..09b46ca4ee --- /dev/null +++ b/dom/base/test/file_bug498897.html^headers^ @@ -0,0 +1 @@ +Link: ; rel=stylesheet diff --git a/dom/base/test/file_bug503473-frame.sjs b/dom/base/test/file_bug503473-frame.sjs new file mode 100644 index 0000000000..f642241091 --- /dev/null +++ b/dom/base/test/file_bug503473-frame.sjs @@ -0,0 +1,22 @@ +function handleRequest(request, response) { + response.processAsync(); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + + response.write( + "" + + "
              " + + "" + ); + + response.bodyOutputStream.flush(); + // leave the stream open +} diff --git a/dom/base/test/file_bug503481.sjs b/dom/base/test/file_bug503481.sjs new file mode 100644 index 0000000000..3b066a95cd --- /dev/null +++ b/dom/base/test/file_bug503481.sjs @@ -0,0 +1,54 @@ +// 'timer' is global to avoid getting GCed which would cancel the timer +var timer; +const nsITimer = Ci.nsITimer; + +function attemptUnblock(s) { + try { + let blockedResponse = null; + getObjectState("bug503481_" + s, function (x) { + blockedResponse = x.wrappedJSObject.r; + }); + blockedResponse.finish(); + setObjectState("bug503481_" + s, null); + } catch (e) { + dump("unable to unblock " + s + "retrying in half a second\n"); + timer = Cc["@mozilla.org/timer;1"].createInstance(nsITimer); + timer.initWithCallback( + function () { + attemptUnblock(s); + }, + 500, + nsITimer.TYPE_ONE_SHOT + ); + } +} + +function handleRequest(request, response) { + var query = {}; + request.queryString.split("&").forEach(function (val) { + var [name, value] = val.split("="); + query[name] = unescape(value); + }); + + dump("processing:" + request.queryString + "\n"); + + if (query.unblock) { + attemptUnblock(query.unblock); + } + + if (query.blockOn) { + response.processAsync(); + x = { + r: response, + QueryInterface(iid) { + return this; + }, + }; + x.wrappedJSObject = x; + setObjectState("bug503481_" + query.blockOn, x); + } + + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(query.body); +} diff --git a/dom/base/test/file_bug503481b_inner.html b/dom/base/test/file_bug503481b_inner.html new file mode 100644 index 0000000000..6b34bc47b6 --- /dev/null +++ b/dom/base/test/file_bug503481b_inner.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/file_bug518104.js b/dom/base/test/file_bug518104.js new file mode 100644 index 0000000000..72a684522f --- /dev/null +++ b/dom/base/test/file_bug518104.js @@ -0,0 +1,3 @@ +document.write("

              "); +parent.done(); +document.close(); diff --git a/dom/base/test/file_bug541937.html b/dom/base/test/file_bug541937.html new file mode 100644 index 0000000000..93056754f9 --- /dev/null +++ b/dom/base/test/file_bug541937.html @@ -0,0 +1,7 @@ + + Test + foo + + +

              Hello world

              + \ No newline at end of file diff --git a/dom/base/test/file_bug541937.xhtml b/dom/base/test/file_bug541937.xhtml new file mode 100644 index 0000000000..f4e5f3d320 --- /dev/null +++ b/dom/base/test/file_bug541937.xhtml @@ -0,0 +1,12 @@ + + + + + Test + foo + + + +

              Hello world

              + + \ No newline at end of file diff --git a/dom/base/test/file_bug557892.html b/dom/base/test/file_bug557892.html new file mode 100644 index 0000000000..4b91ddafdd --- /dev/null +++ b/dom/base/test/file_bug557892.html @@ -0,0 +1,25 @@ + +Crash [@ nsGenericElement::SetAttr] with classList.toggle + + + + + + + diff --git a/dom/base/test/file_bug562137.txt b/dom/base/test/file_bug562137.txt new file mode 100644 index 0000000000..4a21b817e5 --- /dev/null +++ b/dom/base/test/file_bug562137.txt @@ -0,0 +1 @@ +I have nbsp diff --git a/dom/base/test/file_bug590812-ref.xhtml b/dom/base/test/file_bug590812-ref.xhtml new file mode 100644 index 0000000000..7309425fb4 --- /dev/null +++ b/dom/base/test/file_bug590812-ref.xhtml @@ -0,0 +1,3 @@ +
              <out>Here be sea hags</out>
              diff --git a/dom/base/test/file_bug590812.xml b/dom/base/test/file_bug590812.xml new file mode 100644 index 0000000000..759d5066cf --- /dev/null +++ b/dom/base/test/file_bug590812.xml @@ -0,0 +1 @@ +Here be sea hags diff --git a/dom/base/test/file_bug590870.html b/dom/base/test/file_bug590870.html new file mode 100644 index 0000000000..4432b01d3c --- /dev/null +++ b/dom/base/test/file_bug590870.html @@ -0,0 +1,16 @@ + + + + + + Here be dragons! + + diff --git a/dom/base/test/file_bug601803a.html b/dom/base/test/file_bug601803a.html new file mode 100644 index 0000000000..c39ff7219e --- /dev/null +++ b/dom/base/test/file_bug601803a.html @@ -0,0 +1,22 @@ + + + + Test for Bug 601803 + + + + + + diff --git a/dom/base/test/file_bug601803b.html b/dom/base/test/file_bug601803b.html new file mode 100644 index 0000000000..0363654c06 --- /dev/null +++ b/dom/base/test/file_bug601803b.html @@ -0,0 +1,11 @@ + + + + Test for Bug 601803 + + + + + diff --git a/dom/base/test/file_bug604660-1.xml b/dom/base/test/file_bug604660-1.xml new file mode 100644 index 0000000000..231b4357d6 --- /dev/null +++ b/dom/base/test/file_bug604660-1.xml @@ -0,0 +1,3 @@ + + + diff --git a/dom/base/test/file_bug604660-2.xsl b/dom/base/test/file_bug604660-2.xsl new file mode 100644 index 0000000000..16611726ce --- /dev/null +++ b/dom/base/test/file_bug604660-2.xsl @@ -0,0 +1,19 @@ + + + + + + XSLT script execution test + + + + + + + + + + + + + diff --git a/dom/base/test/file_bug604660-3.js b/dom/base/test/file_bug604660-3.js new file mode 100644 index 0000000000..c11ae68f28 --- /dev/null +++ b/dom/base/test/file_bug604660-3.js @@ -0,0 +1 @@ +parent.scriptRan(2); diff --git a/dom/base/test/file_bug604660-4.js b/dom/base/test/file_bug604660-4.js new file mode 100644 index 0000000000..2bd5b43e5b --- /dev/null +++ b/dom/base/test/file_bug604660-4.js @@ -0,0 +1 @@ +parent.scriptRan(4); diff --git a/dom/base/test/file_bug604660-5.xml b/dom/base/test/file_bug604660-5.xml new file mode 100644 index 0000000000..58c6382836 --- /dev/null +++ b/dom/base/test/file_bug604660-5.xml @@ -0,0 +1,2 @@ + + diff --git a/dom/base/test/file_bug604660-6.xsl b/dom/base/test/file_bug604660-6.xsl new file mode 100644 index 0000000000..4a75777d90 --- /dev/null +++ b/dom/base/test/file_bug604660-6.xsl @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dom/base/test/file_bug622088.sjs b/dom/base/test/file_bug622088.sjs new file mode 100644 index 0000000000..87acdc3b8b --- /dev/null +++ b/dom/base/test/file_bug622088.sjs @@ -0,0 +1,5 @@ +function handleRequest(request, response) { + // Echos the referrer back to the requester. + response.setHeader("Content-Type", "text/plain", false); + response.write(request.getHeader("Referer")); +} diff --git a/dom/base/test/file_bug622088_inner.html b/dom/base/test/file_bug622088_inner.html new file mode 100644 index 0000000000..e89273d89b --- /dev/null +++ b/dom/base/test/file_bug622088_inner.html @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/dom/base/test/file_bug675121.sjs b/dom/base/test/file_bug675121.sjs new file mode 100644 index 0000000000..5bca8923bc --- /dev/null +++ b/dom/base/test/file_bug675121.sjs @@ -0,0 +1,17 @@ +var timer; + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write("Responded"); + response.processAsync(); + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback( + function () { + response.finish(); + // 50ms certainly be enough for one refresh driver firing to happen! + }, + 50, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/dom/base/test/file_bug687859-16.js b/dom/base/test/file_bug687859-16.js new file mode 100644 index 0000000000..58f82cdda3 Binary files /dev/null and b/dom/base/test/file_bug687859-16.js differ diff --git a/dom/base/test/file_bug687859-16.js^headers^ b/dom/base/test/file_bug687859-16.js^headers^ new file mode 100644 index 0000000000..e0d4fce5d0 --- /dev/null +++ b/dom/base/test/file_bug687859-16.js^headers^ @@ -0,0 +1 @@ +Content-Type: text/javascript; charset=tis-620 diff --git a/dom/base/test/file_bug687859-bom.js b/dom/base/test/file_bug687859-bom.js new file mode 100644 index 0000000000..7536004bb6 --- /dev/null +++ b/dom/base/test/file_bug687859-bom.js @@ -0,0 +1 @@ +var stringFromBomScript = "€"; diff --git a/dom/base/test/file_bug687859-bom.js^headers^ b/dom/base/test/file_bug687859-bom.js^headers^ new file mode 100644 index 0000000000..e0d4fce5d0 --- /dev/null +++ b/dom/base/test/file_bug687859-bom.js^headers^ @@ -0,0 +1 @@ +Content-Type: text/javascript; charset=tis-620 diff --git a/dom/base/test/file_bug687859-charset.js b/dom/base/test/file_bug687859-charset.js new file mode 100644 index 0000000000..e812a1e37f --- /dev/null +++ b/dom/base/test/file_bug687859-charset.js @@ -0,0 +1 @@ +var stringFromCharsetScript = "¡"; \ No newline at end of file diff --git a/dom/base/test/file_bug687859-http.js b/dom/base/test/file_bug687859-http.js new file mode 100644 index 0000000000..1b1456d480 --- /dev/null +++ b/dom/base/test/file_bug687859-http.js @@ -0,0 +1 @@ +var stringFromHttpScript = "ä"; diff --git a/dom/base/test/file_bug687859-http.js^headers^ b/dom/base/test/file_bug687859-http.js^headers^ new file mode 100644 index 0000000000..e0d4fce5d0 --- /dev/null +++ b/dom/base/test/file_bug687859-http.js^headers^ @@ -0,0 +1 @@ +Content-Type: text/javascript; charset=tis-620 diff --git a/dom/base/test/file_bug687859-inherit.js b/dom/base/test/file_bug687859-inherit.js new file mode 100644 index 0000000000..b83f60b2fb --- /dev/null +++ b/dom/base/test/file_bug687859-inherit.js @@ -0,0 +1 @@ +var stringFromInheritScript = "¡"; \ No newline at end of file diff --git a/dom/base/test/file_bug692434.xml b/dom/base/test/file_bug692434.xml new file mode 100644 index 0000000000..2d559c3aed --- /dev/null +++ b/dom/base/test/file_bug692434.xml @@ -0,0 +1 @@ +Þ diff --git a/dom/base/test/file_bug704320_preload_attr.html b/dom/base/test/file_bug704320_preload_attr.html new file mode 100644 index 0000000000..e10f1727df --- /dev/null +++ b/dom/base/test/file_bug704320_preload_attr.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/file_bug704320_preload_common.js b/dom/base/test/file_bug704320_preload_common.js new file mode 100644 index 0000000000..c7a409e297 --- /dev/null +++ b/dom/base/test/file_bug704320_preload_common.js @@ -0,0 +1,32 @@ +// Common code for the iframes used by bug704320_preload. + +var loadCount = 0; + +// Called by the various onload handlers to indicate that a resource has +// been fully loaded. We require three loads to complete (img, script, +// link) for this test. +function incrementLoad(tag) { + loadCount++; + if (loadCount == 3) { + window.parent.postMessage("childLoadComplete", window.location.origin); + } else if (loadCount > 3) { + document.write("

              Too Many Load Events!

              "); + window.parent.postMessage("childOverload", window.location.origin); + } +} + +// This is same as incrementLoad, but the caller passes in the loadCount. +function incrementLoad2(tag, expectedLoadCount) { + loadCount++; + if (loadCount == expectedLoadCount) { + window.parent.postMessage("childLoadComplete", window.location.origin); + } else if (loadCount > expectedLoadCount) { + document.write("

              Too Many Load Events!

              "); + window.parent.postMessage("childOverload", window.location.origin); + } +} + +// in case something fails to load, cause the test to fail. +function postfail(msg) { + window.parent.postMessage("fail-" + msg, window.location.origin); +} diff --git a/dom/base/test/file_bug704320_preload_reuse.html b/dom/base/test/file_bug704320_preload_reuse.html new file mode 100644 index 0000000000..5643e3d8d6 --- /dev/null +++ b/dom/base/test/file_bug704320_preload_reuse.html @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/file_bug704320_redirect.html b/dom/base/test/file_bug704320_redirect.html new file mode 100644 index 0000000000..09ed05d6fd --- /dev/null +++ b/dom/base/test/file_bug704320_redirect.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/base/test/file_bug707142_baseline.json b/dom/base/test/file_bug707142_baseline.json new file mode 100644 index 0000000000..8c850a5fd2 --- /dev/null +++ b/dom/base/test/file_bug707142_baseline.json @@ -0,0 +1 @@ +{ "foo": "bar" } diff --git a/dom/base/test/file_bug707142_bom.json b/dom/base/test/file_bug707142_bom.json new file mode 100644 index 0000000000..e961357349 --- /dev/null +++ b/dom/base/test/file_bug707142_bom.json @@ -0,0 +1 @@ +{ "foo": "bar" } diff --git a/dom/base/test/file_bug707142_utf-16.json b/dom/base/test/file_bug707142_utf-16.json new file mode 100644 index 0000000000..eb28f6bb7e Binary files /dev/null and b/dom/base/test/file_bug707142_utf-16.json differ diff --git a/dom/base/test/file_bug708620-2.html b/dom/base/test/file_bug708620-2.html new file mode 100644 index 0000000000..86899201df --- /dev/null +++ b/dom/base/test/file_bug708620-2.html @@ -0,0 +1,4 @@ + + +Non-UTF form target + diff --git a/dom/base/test/file_bug708620.html b/dom/base/test/file_bug708620.html new file mode 100644 index 0000000000..a90e6aeeba --- /dev/null +++ b/dom/base/test/file_bug708620.html @@ -0,0 +1,7 @@ + + +Non-UTF form + +
              + +
              diff --git a/dom/base/test/file_bug753278.html b/dom/base/test/file_bug753278.html new file mode 100644 index 0000000000..922bc0c658 --- /dev/null +++ b/dom/base/test/file_bug753278.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_bug769117.html b/dom/base/test/file_bug769117.html new file mode 100644 index 0000000000..424f8dff1c --- /dev/null +++ b/dom/base/test/file_bug769117.html @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dom/base/test/file_bug782342.txt b/dom/base/test/file_bug782342.txt new file mode 100644 index 0000000000..3b18e512db --- /dev/null +++ b/dom/base/test/file_bug782342.txt @@ -0,0 +1 @@ +hello world diff --git a/dom/base/test/file_bug787778.sjs b/dom/base/test/file_bug787778.sjs new file mode 100644 index 0000000000..d22d67d9c9 --- /dev/null +++ b/dom/base/test/file_bug787778.sjs @@ -0,0 +1,7 @@ +function handleRequest(request, response) { + response.processAsync(); + response.setHeader("Content-Type", "text/plain", false); + response.setHeader("X-Frame-Options", "DENY", false); + + response.finish(); +} diff --git a/dom/base/test/file_bug869432.eventsource b/dom/base/test/file_bug869432.eventsource new file mode 100644 index 0000000000..de92d4dd86 --- /dev/null +++ b/dom/base/test/file_bug869432.eventsource @@ -0,0 +1,4 @@ +retry:500 +data: data + + diff --git a/dom/base/test/file_bug869432.eventsource^headers^ b/dom/base/test/file_bug869432.eventsource^headers^ new file mode 100644 index 0000000000..b8db77c582 --- /dev/null +++ b/dom/base/test/file_bug869432.eventsource^headers^ @@ -0,0 +1,3 @@ +HTTP 304 NO CONTENT (CLOSE) +Content-Type: text/event-stream +Cache-Control: no-cache, must-revalidate \ No newline at end of file diff --git a/dom/base/test/file_bug902350.html b/dom/base/test/file_bug902350.html new file mode 100644 index 0000000000..2101f80c7d --- /dev/null +++ b/dom/base/test/file_bug902350.html @@ -0,0 +1,19 @@ + + + + + + Test for Bug 902350 + + + +
              + +
              + + + + diff --git a/dom/base/test/file_bug902350_frame.html b/dom/base/test/file_bug902350_frame.html new file mode 100644 index 0000000000..183dabe255 --- /dev/null +++ b/dom/base/test/file_bug902350_frame.html @@ -0,0 +1,14 @@ + + + + + + Tests for Mixed Content Frame Navigation + + +Go to http site + + diff --git a/dom/base/test/file_bug907892.html b/dom/base/test/file_bug907892.html new file mode 100644 index 0000000000..9f5948661c --- /dev/null +++ b/dom/base/test/file_bug907892.html @@ -0,0 +1,12 @@ + + diff --git a/dom/base/test/file_bug945152.jar b/dom/base/test/file_bug945152.jar new file mode 100644 index 0000000000..eb732980d9 Binary files /dev/null and b/dom/base/test/file_bug945152.jar differ diff --git a/dom/base/test/file_bug945152_worker.js b/dom/base/test/file_bug945152_worker.js new file mode 100644 index 0000000000..9664045b6d --- /dev/null +++ b/dom/base/test/file_bug945152_worker.js @@ -0,0 +1,99 @@ +var gData1 = "TEST_DATA_1:ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +var gData2 = "TEST_DATA_2:1234567890"; +var gPaddingChar = "."; +var gPaddingSize = 10000; +var gPadding = ""; + +for (var i = 0; i < gPaddingSize; i++) { + gPadding += gPaddingChar; +} + +function ok(a, msg) { + postMessage({ type: "status", status: !!a, msg }); +} + +function is(a, b, msg) { + postMessage({ type: "status", status: a === b, msg }); +} + +function checkData(response, data_head, cb) { + ok(response, "Data is non-null"); + var str = String.fromCharCode.apply(null, new Uint8Array(response)); + ok(str.length == data_head.length + gPaddingSize, "Data size is correct"); + ok(str.slice(0, data_head.length) == data_head, "Data head is correct"); + ok(str.slice(data_head.length) == gPadding, "Data padding is correct"); + cb(); +} + +self.onmessage = function onmessage(event) { + var jar = event.data; + + function makeJarURL(entry) { + return "jar:" + jar + "!/" + entry; + } + + function test_mapped_sync() { + var xhr = new XMLHttpRequest({ mozAnon: true, mozSystem: true }); + xhr.open("GET", makeJarURL("data_1.txt"), false); + xhr.responseType = "arraybuffer"; + xhr.send(); + if (xhr.status) { + ok(xhr.status == 200, "Status is 200"); + var ct = xhr.getResponseHeader("Content-Type"); + ok(ct.includes("mem-mapped"), "Data is memory-mapped"); + checkData(xhr.response, gData1, runTests); + } + } + + function test_mapped_async() { + var xhr = new XMLHttpRequest({ mozAnon: true, mozSystem: true }); + xhr.open("GET", makeJarURL("data_1.txt")); + xhr.responseType = "arraybuffer"; + xhr.onreadystatechange = function () { + if (xhr.readyState !== xhr.DONE) { + return; + } + if (xhr.status) { + ok(xhr.status == 200, "Status is 200"); + var ct = xhr.getResponseHeader("Content-Type"); + ok(ct.includes("mem-mapped"), "Data is memory-mapped"); + checkData(xhr.response, gData1, runTests); + } + }; + xhr.send(); + } + + // Make sure array buffer retrieved from compressed file in package is + // handled by memory allocation instead of memory mapping. + function test_non_mapped() { + var xhr = new XMLHttpRequest({ mozAnon: true, mozSystem: true }); + xhr.open("GET", makeJarURL("data_2.txt")); + xhr.responseType = "arraybuffer"; + xhr.onreadystatechange = function () { + if (xhr.readyState !== xhr.DONE) { + return; + } + if (xhr.status) { + ok(xhr.status == 200, "Status is 200"); + var ct = xhr.getResponseHeader("Content-Type"); + ok(!ct.includes("mem-mapped"), "Data is not memory-mapped"); + checkData(xhr.response, gData2, runTests); + } + }; + xhr.send(); + } + + var tests = [test_mapped_sync, test_mapped_async, test_non_mapped]; + + function runTests() { + if (!tests.length) { + postMessage({ type: "finish" }); + return; + } + + var test = tests.shift(); + test(); + } + + runTests(); +}; diff --git a/dom/base/test/file_change_policy_redirect.html b/dom/base/test/file_change_policy_redirect.html new file mode 100644 index 0000000000..e48386d97c --- /dev/null +++ b/dom/base/test/file_change_policy_redirect.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/base/test/file_current_inner_window.html b/dom/base/test/file_current_inner_window.html new file mode 100644 index 0000000000..8156e29000 --- /dev/null +++ b/dom/base/test/file_current_inner_window.html @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/dom/base/test/file_delazification_strategy.html b/dom/base/test/file_delazification_strategy.html new file mode 100644 index 0000000000..a8f58c60f1 --- /dev/null +++ b/dom/base/test/file_delazification_strategy.html @@ -0,0 +1,10 @@ + + + + + Add a tag script to check delazification strategy + + + + + diff --git a/dom/base/test/file_delazification_strategy.js b/dom/base/test/file_delazification_strategy.js new file mode 100644 index 0000000000..5afcbeed53 --- /dev/null +++ b/dom/base/test/file_delazification_strategy.js @@ -0,0 +1,91 @@ +function baz() {} +function bar() {} +function foo() { + bar(); +} +foo(); + +// For testing, we require the script to be parsed off-htread. To schedule a +// script off-thread, we require the script to be at least 5 KB. Thus, here is +// one comment which is used to trick this heuristics: +// +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWX0Oxoc;,.... ....,;coxO0XWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,.. ..,cok0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKko:'. .':okKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl,. .,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .;oONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkl'. 'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOl' 'lONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo, ,oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .:kNMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMXx, ,xXMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMWXd' 'dXWMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMXd' 'dXMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMNx' 'xNMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMWO; ;OWMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMKl. .lXMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMWk, ,kWMMMMMMMMMMMMM +// MMMMMMMMMMMMXo. .lXMMMMMMMMMMMM +// MMMMMMMMMMW0; ...... ;0WMMMMMMMMMM +// MMMMMMMMMWk' ..,:loxxkOOkxdo:,. 'kWMMMMMMMMM +// MMMMMMMMWx. .':lxO000000000000000ko;. .xWMMMMMMMM +// MMMMMMMNd. .'cdk00000000000000000000000x;. ..',;ccloodddddddollc:;,'.. .dNMMMMMMM +// MMMMMMNd. ,dO000000000000000000000000000Oo' ..;coxk00000000000000000000000Okdlc;'. .dNMMMMMM +// MMMMMNd. .cO000000000000000000000000000000k; .;lxO0000000000000000000000000000000000Okoc,. .dWMMMMM +// MMMMWx. .'cO0000000000000000000000000000Oc. .;ok0000K00000000000000000000000000000000000000ko, .kWMMMM +// MMMMO' ,kK0000000000000000000000000000Oc. .:x000000000000000OkdoollcccllodxkO0000K00000000000k' 'OMMMM +// MMMK; .'lO000000000000000000000000000000Ol'... 'd000000000000Odl;'.. ..',:ldkO00000000KO, ;KMMM +// MMNo ,dkO0K00000000000000000000000000000000OOkxdoc;,,ck0000000000Oo;. .'ck000000KO; oNMM +// MMk. .o0000000000000000000000000000000000000000000000000000000000d, .o000000K0: .OMM +// MX: .o00000000000000000000000000000000000000000000000000000000Oc. c000000K0l. :XM +// Wx. .c00000000000000000000000000000000000000000000000000000000x, :OK000000o. .xW +// X: .:dxO00000000000000000000000000000000000000000000000000000Oo' ,k0000000d. :X +// O. .:xOO0000000000000000000000000000000000000000000000000000Ol. .x000000Kd. .O +// o ..'''''''',,:lx000000000000000000000000000000000000000000x, .lOOOOkkko. o +// ; .:x00000000000000000000000000000000000000000O:. ......... ; +// . 'd00000000000000000000000000000000000000000Ol. . +// . ,k000000000000000000000000000000000000000000o. . +// .o0000000000000000000000000000000000000000000d. +// c00000000000000000000000000000000000000000000o. +// ;OK0000000000000000000000000000000000000000000o. +// ,kK00000000000000000000000000000000000000000000xoc:,'.. +// .x00000000000000000000000000000000000000000000000000Okxolc;,'.. +// .d000000000000000K000000000000000000000000000000000000000000OOxdl:,.. +// . .o00000000000000OO0000000000000000000000000000000000000000000000000Oxo:'. . +// . .l0000000000000Oc:k0000000000000000000000000000000000000000000000000000Oxl,. . +// ; c000000000000Kk, ,x000000000000000000000000000000xodkO00000000000000000000xc. ; +// o ..''.. :000000000000Kx' ,k0000000000000000000000000000Oc. ..';codkO000000000000000k:. o +// O. .,lxO00Okxl:,. :O000000000000d. ;k0000000000000000000000000000l. ..,cok0000000000000d' .O +// X: ,d000000000000kdc;. :O000000000000l. .c0000000000000000000000000000o. .;oO00000000000k; :X +// Wx. 'x00000000000000000Oxl;..:O00000000000O: .x000000000000000000000000000d. 'oO00000K0000k, .kW +// MX: c0000000000000000000000Oxk00000000000Kk, cO00000000000000000000000000d. ;k0000000000d. :XM +// MMO. :O000000000000000000000000000000000000x. cO00000000000000000000000000d. ,k000000000O: .OMM +// MMNo .d000000000000000000000000000000000000l. .d000000000000000000000000000o. cO000000000o. .oNMM +// MMMK; 'd00000000000000000000000000000000000c ,k000000000000000000000000000l. 'x000000000d. ;KMMM +// MMMMO' .lO000000000000000000000000000000000kl;. .o00000000000000000000000000K0c .d000000000d. 'OMMMM +// MMMMWx. ;x00000000000000000000000000000000000ko:lO000000000000000000000000000O; .x000000000d. .xWMMMM +// MMMMMWd. .ck00000000000000000000000000000000000000000000000000000000000000000k, ;kK00000000l. .dWMMMMM +// MMMMMMNd. .:x000000000000000000000000000000000000000000000000000000000000000d. .o000000000O; .dNMMMMMM +// MMMMMMMNd. .;dO000000000000000000000000000000000000000000000000000000000000l. .o0000000000d. .dNMMMMMMM +// MMMMMMMMWx. .,,'.. 'cx00000000000000000000000000000000000000000000000000000000KO: .;d0000000000x, .xWMMMMMMMM +// MMMMMMMMMWk' 'd00Oxdl;'. .,lx000000000000000000000000000000000000000000000000000000k' .:dO0000000000x, 'kWMMMMMMMMM +// MMMMMMMMMMW0; .:x000000kd:'. .,lk000000000000000000000000000000000000000000000000000d. ..,cdk0K000000000Oo. :0WMMMMMMMMMM +// MMMMMMMMMMMMXo. .,ok000000Odc. ,x000000000000000000000000000000000000000000000000000d,...'',;:cldxO000000000000K0d;. .oXMMMMMMMMMMMM +// MMMMMMMMMMMMMWk, .:x0000000Oo;.. .,oO000000000000000000000000000000000000000000000000000000OOOO00000000000000000000Od;. ,kWMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMXl. .;dO0000000Oxdoooxk0000000000OxxO0000000000000000000000000000000000000000000000000000000000000000Oxc' .lXMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMWO; 'lk00000000000000000000Oxc' ..:oxO0K000000000000000000000000000000000000000000000000000000Oko:'. ;OWMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMNx, .;ok00000000000000kdc'. ..;cdxO00000000000000000000000000000000000000000000Okxdoc;'. ,xNMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMXd' .,:ldxkkkkxdl:,. ..,:cldxkkkO000000000000Okkxdlc:;;;:::::;;;,,'... 'dXMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMXd' ...... ....'',,,,,,,,'.... 'dXWMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMXx,. ,xXMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .:kNMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo,. .,oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOl' 'lONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXkl'. .'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .;oONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl;. .,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKko:'. .':okKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,.. ..,cok0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWX0Oxoc;,.... ....,;coxO0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM diff --git a/dom/base/test/file_domwindowutils_animation.html b/dom/base/test/file_domwindowutils_animation.html new file mode 100644 index 0000000000..c8b6f2a99d --- /dev/null +++ b/dom/base/test/file_domwindowutils_animation.html @@ -0,0 +1,233 @@ + + + + + DOMWindowUtils test with animation + + + + + + + diff --git a/dom/base/test/file_domwindowutils_dynamic_toolbar.html b/dom/base/test/file_domwindowutils_dynamic_toolbar.html new file mode 100644 index 0000000000..becb4bf08f --- /dev/null +++ b/dom/base/test/file_domwindowutils_dynamic_toolbar.html @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/dom/base/test/file_empty.html b/dom/base/test/file_empty.html new file mode 100644 index 0000000000..495c23ec8a --- /dev/null +++ b/dom/base/test/file_empty.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_explicit_user_agent.sjs b/dom/base/test/file_explicit_user_agent.sjs new file mode 100644 index 0000000000..33b9a5c505 --- /dev/null +++ b/dom/base/test/file_explicit_user_agent.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) { + if (request.hasHeader("User-Agent")) { + response.setHeader("Result-User-Agent", request.getHeader("User-Agent")); + } + response.write(""); +} diff --git a/dom/base/test/file_external_script.html b/dom/base/test/file_external_script.html new file mode 100644 index 0000000000..16f059d558 --- /dev/null +++ b/dom/base/test/file_external_script.html @@ -0,0 +1,11 @@ + + + + + + + + +

              Hello Mochitest

              + + diff --git a/dom/base/test/file_external_script.xhtml b/dom/base/test/file_external_script.xhtml new file mode 100644 index 0000000000..4327c499cb --- /dev/null +++ b/dom/base/test/file_external_script.xhtml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/dom/base/test/file_focus_display_none_xorigin_iframe_inner.html b/dom/base/test/file_focus_display_none_xorigin_iframe_inner.html new file mode 100644 index 0000000000..5831df882c --- /dev/null +++ b/dom/base/test/file_focus_display_none_xorigin_iframe_inner.html @@ -0,0 +1,15 @@ + + +

              Inner

              +
              + diff --git a/dom/base/test/file_focus_shadow_dom.html b/dom/base/test/file_focus_shadow_dom.html new file mode 100644 index 0000000000..6fa9d1b88e --- /dev/null +++ b/dom/base/test/file_focus_shadow_dom.html @@ -0,0 +1,999 @@ + + + Test for Bug 1453693 + + + + + + + + + diff --git a/dom/base/test/file_general_document.html b/dom/base/test/file_general_document.html new file mode 100644 index 0000000000..2539669de9 --- /dev/null +++ b/dom/base/test/file_general_document.html @@ -0,0 +1,10 @@ + + + + +General document for testing + + +

              Hello mochitest!

              + + diff --git a/dom/base/test/file_history_document_open.html b/dom/base/test/file_history_document_open.html new file mode 100644 index 0000000000..b9f05f7c2c --- /dev/null +++ b/dom/base/test/file_history_document_open.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_htmlserializer_1.html b/dom/base/test/file_htmlserializer_1.html new file mode 100644 index 0000000000..9576b5d7d6 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1.html @@ -0,0 +1,44 @@ + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_bodyonly.html b/dom/base/test/file_htmlserializer_1_bodyonly.html new file mode 100644 index 0000000000..848167c62a --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_bodyonly.html @@ -0,0 +1,43 @@ + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_format.html b/dom/base/test/file_htmlserializer_1_format.html new file mode 100644 index 0000000000..09f80467e4 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_format.html @@ -0,0 +1,57 @@ + + + + + Test for html serializer + + +

              Hello world

              +

              Lorem ipsum dolor sit amet, consectetuer + adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis + ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent + taciti sociosqu ad litora torquent per conubia + nostra, per inceptos hymenaeos.

              +
                +
              • Nam tellus massa,éàèçù
              • +
              • fringilla aliquam,
              • +
              • fermentum sit amet,
              • +
              • posuere ac,
              • +
              • est.
              • +
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + +
                +
              1. Fusce a ipsum
              2. +
              3. non lacus posuere aliquet.
              4. +
              5. Sed fermentum posuere nulla
              6. +
              7. Donec tempor.
              8. +
              + Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              + ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus + aliquet lectus. Nunc vitae eros. Class aptent taciti

              + + diff --git a/dom/base/test/file_htmlserializer_1_linebreak.html b/dom/base/test/file_htmlserializer_1_linebreak.html new file mode 100644 index 0000000000..8194b8b415 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_linebreak.html @@ -0,0 +1,47 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_links.html b/dom/base/test/file_htmlserializer_1_links.html new file mode 100644 index 0000000000..f0864c940c --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_links.html @@ -0,0 +1,47 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              diff --git a/dom/base/test/file_htmlserializer_1_nested_body.html b/dom/base/test/file_htmlserializer_1_nested_body.html new file mode 100644 index 0000000000..94f67547e3 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_nested_body.html @@ -0,0 +1,47 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              this is an other body element

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_no_body.html b/dom/base/test/file_htmlserializer_1_no_body.html new file mode 100644 index 0000000000..9c749721b1 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_no_body.html @@ -0,0 +1,5 @@ + + + Test for html serializer + + \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_noflag.html b/dom/base/test/file_htmlserializer_1_noflag.html new file mode 100644 index 0000000000..8194b8b415 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_noflag.html @@ -0,0 +1,47 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_noformatpre.html b/dom/base/test/file_htmlserializer_1_noformatpre.html new file mode 100644 index 0000000000..aba95b62c8 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_noformatpre.html @@ -0,0 +1,51 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              +
              + Cras quis
              +
              + nisi at odio
              +
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, 
              +
              +lacus risus pulvinar ante.
              +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_raw.html b/dom/base/test/file_htmlserializer_1_raw.html new file mode 100644 index 0000000000..c646f26963 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_raw.html @@ -0,0 +1,45 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_sibling_body.html b/dom/base/test/file_htmlserializer_1_sibling_body.html new file mode 100644 index 0000000000..f533e6679a --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_sibling_body.html @@ -0,0 +1,47 @@ + + + Test for html serializer + +

              this is an other body element

              +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_sibling_body_only_body.html b/dom/base/test/file_htmlserializer_1_sibling_body_only_body.html new file mode 100644 index 0000000000..97c1625156 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_sibling_body_only_body.html @@ -0,0 +1,43 @@ +

              this is an other body element

              +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_1_wrap.html b/dom/base/test/file_htmlserializer_1_wrap.html new file mode 100644 index 0000000000..4552e9cba5 --- /dev/null +++ b/dom/base/test/file_htmlserializer_1_wrap.html @@ -0,0 +1,52 @@ + + + Test for html serializer + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu + ad + litora torquent per + conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum +posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros leo ut libero +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus +aliquet lectus. Nunc vitae eros. Class aptent taciti

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_2.html b/dom/base/test/file_htmlserializer_2.html new file mode 100644 index 0000000000..2156b1610c --- /dev/null +++ b/dom/base/test/file_htmlserializer_2.html @@ -0,0 +1,22 @@ +Test for html serializer with entities + + +

              The basic set is just   & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ +Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø +Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê +ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý +þ ÿ

              +

              symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ +Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς +σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ +™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ +∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ◊ ♠ ♣ ♥ ♦ +

              +

              others +Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’ +‚“ ” „ † ‡ ‰ ‹ › € +

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_2_basic.html b/dom/base/test/file_htmlserializer_2_basic.html new file mode 100644 index 0000000000..56ac95dfdd --- /dev/null +++ b/dom/base/test/file_htmlserializer_2_basic.html @@ -0,0 +1,24 @@ + + +Test for html serializer with entities + + +

              The basic set is just   & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À à Â Ã Ä Å Æ +Ç È É Ê Ë Ì à Î à à Ñ Ò Ó Ô Õ Ö × Ø +Ù Ú Û Ü à Þ ß à á â ã ä å æ ç è é ê +ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý +þ ÿ

              +

              symbols, math.. Æ’ Α Î’ Γ Δ Ε Ζ Η Θ Ι Κ Λ Îœ ΠΞ Ο Π Ρ Σ Τ Î¥ +Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο Ï€ Ï Ï‚ +σ Ï„ Ï… φ χ ψ ω Ï‘ Ï’ Ï– • … ′ ″ ‾ ℠℘ â„‘ â„œ +â„¢ ℵ ↠↑ → ↓ ↔ ↵ ⇠⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ +∋ ∠∑ − ∗ √ ∠∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ â‹… ⌈ ⌉ ⌊ ⌋ â—Š â™  ♣ ♥ ♦ +

              +

              others +Å’ Å“ Å  Å¡ Ÿ ˆ Ëœ       ‌ †‎ â€â€“— ‘ ’ +‚“ †„ † ‡ ‰ ‹ › € +

              \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_ipv6.html b/dom/base/test/file_htmlserializer_ipv6.html new file mode 100644 index 0000000000..298493e718 --- /dev/null +++ b/dom/base/test/file_htmlserializer_ipv6.html @@ -0,0 +1,5 @@ + + Testcase for IPv6 addresses + + Test + \ No newline at end of file diff --git a/dom/base/test/file_htmlserializer_ipv6_out.html b/dom/base/test/file_htmlserializer_ipv6_out.html new file mode 100644 index 0000000000..675a406d85 --- /dev/null +++ b/dom/base/test/file_htmlserializer_ipv6_out.html @@ -0,0 +1,6 @@ + + + Testcase for IPv6 addresses + + Test + \ No newline at end of file diff --git a/dom/base/test/file_inline_script.html b/dom/base/test/file_inline_script.html new file mode 100644 index 0000000000..838c70f946 --- /dev/null +++ b/dom/base/test/file_inline_script.html @@ -0,0 +1,11 @@ + + + + + + + + +

              Hello Mochitest

              + + diff --git a/dom/base/test/file_inline_script.xhtml b/dom/base/test/file_inline_script.xhtml new file mode 100644 index 0000000000..525daf29fe --- /dev/null +++ b/dom/base/test/file_inline_script.xhtml @@ -0,0 +1,11 @@ + + + + + + +</head> +<body> + <p>Hello Mochitest</p> +</body> +</html> diff --git a/dom/base/test/file_js_cache.html b/dom/base/test/file_js_cache.html new file mode 100644 index 0000000000..6feb94d872 --- /dev/null +++ b/dom/base/test/file_js_cache.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Add a tag script to save the bytecode + + + + + diff --git a/dom/base/test/file_js_cache.js b/dom/base/test/file_js_cache.js new file mode 100644 index 0000000000..b9b966775c --- /dev/null +++ b/dom/base/test/file_js_cache.js @@ -0,0 +1,5 @@ +function baz() {} +function bar() {} +function foo() { bar() } +foo(); + diff --git a/dom/base/test/file_js_cache_module.html b/dom/base/test/file_js_cache_module.html new file mode 100644 index 0000000000..36d549c945 --- /dev/null +++ b/dom/base/test/file_js_cache_module.html @@ -0,0 +1,13 @@ + + + + + Load the script as a module + + + + + + diff --git a/dom/base/test/file_js_cache_save_after_load.html b/dom/base/test/file_js_cache_save_after_load.html new file mode 100644 index 0000000000..8a696c0026 --- /dev/null +++ b/dom/base/test/file_js_cache_save_after_load.html @@ -0,0 +1,10 @@ + + + + + Save the bytecode when all scripts are executed + + + + + diff --git a/dom/base/test/file_js_cache_save_after_load.js b/dom/base/test/file_js_cache_save_after_load.js new file mode 100644 index 0000000000..7f5a20b524 --- /dev/null +++ b/dom/base/test/file_js_cache_save_after_load.js @@ -0,0 +1,15 @@ +function send_ping() { + window.dispatchEvent(new Event("ping")); +} +send_ping(); // ping (=1) + +window.addEventListener("load", function () { + send_ping(); // ping (=2) + + // Append a script which should call |foo|, before the encoding of this script + // bytecode. + var script = document.createElement("script"); + script.type = "text/javascript"; + script.innerText = "send_ping();"; // ping (=3) + document.head.appendChild(script); +}); diff --git a/dom/base/test/file_js_cache_syntax_error.html b/dom/base/test/file_js_cache_syntax_error.html new file mode 100644 index 0000000000..cc4a9b2daa --- /dev/null +++ b/dom/base/test/file_js_cache_syntax_error.html @@ -0,0 +1,10 @@ + + + + + Do not save bytecode on compilation errors + + + + + diff --git a/dom/base/test/file_js_cache_syntax_error.js b/dom/base/test/file_js_cache_syntax_error.js new file mode 100644 index 0000000000..fcf587ae70 --- /dev/null +++ b/dom/base/test/file_js_cache_syntax_error.js @@ -0,0 +1 @@ +var // SyntaxError: missing variable name. diff --git a/dom/base/test/file_js_cache_with_sri.html b/dom/base/test/file_js_cache_with_sri.html new file mode 100644 index 0000000000..38ecb26984 --- /dev/null +++ b/dom/base/test/file_js_cache_with_sri.html @@ -0,0 +1,12 @@ + + + + + Add a tag script to save the bytecode + + + + + diff --git a/dom/base/test/file_location_href_unknown_protocol.html b/dom/base/test/file_location_href_unknown_protocol.html new file mode 100644 index 0000000000..10c994fbde --- /dev/null +++ b/dom/base/test/file_location_href_unknown_protocol.html @@ -0,0 +1,15 @@ + + diff --git a/dom/base/test/file_lock_orientation_with_pending_fullscreen.html b/dom/base/test/file_lock_orientation_with_pending_fullscreen.html new file mode 100644 index 0000000000..07af0fc67d --- /dev/null +++ b/dom/base/test/file_lock_orientation_with_pending_fullscreen.html @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/dom/base/test/file_messagemanager_unload.html b/dom/base/test/file_messagemanager_unload.html new file mode 100644 index 0000000000..f01e60bae2 --- /dev/null +++ b/dom/base/test/file_messagemanager_unload.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/base/test/file_module_js_cache.html b/dom/base/test/file_module_js_cache.html new file mode 100644 index 0000000000..1a0d433dcd --- /dev/null +++ b/dom/base/test/file_module_js_cache.html @@ -0,0 +1,10 @@ + + + + + Add a tag module script to save the bytecode + + + + + diff --git a/dom/base/test/file_module_js_cache.mjs b/dom/base/test/file_module_js_cache.mjs new file mode 100644 index 0000000000..1b08386c81 --- /dev/null +++ b/dom/base/test/file_module_js_cache.mjs @@ -0,0 +1,6 @@ +function baz() {} +function bar() {} +function foo() { + bar(); +} +foo(); diff --git a/dom/base/test/file_module_js_cache_no_module.html b/dom/base/test/file_module_js_cache_no_module.html new file mode 100644 index 0000000000..d81884e44d --- /dev/null +++ b/dom/base/test/file_module_js_cache_no_module.html @@ -0,0 +1,10 @@ + + + + + Load the module script as a regular script + + + + + diff --git a/dom/base/test/file_module_js_cache_with_sri.html b/dom/base/test/file_module_js_cache_with_sri.html new file mode 100644 index 0000000000..f0039a431b --- /dev/null +++ b/dom/base/test/file_module_js_cache_with_sri.html @@ -0,0 +1,12 @@ + + + + + Add a tag module script to save the bytecode + + + + + diff --git a/dom/base/test/file_mozfiledataurl_img.jpg b/dom/base/test/file_mozfiledataurl_img.jpg new file mode 100644 index 0000000000..dcd99b9670 Binary files /dev/null and b/dom/base/test/file_mozfiledataurl_img.jpg differ diff --git a/dom/base/test/file_navigator_resolve_identity_xrays.xhtml b/dom/base/test/file_navigator_resolve_identity_xrays.xhtml new file mode 100644 index 0000000000..bdce7c7b64 --- /dev/null +++ b/dom/base/test/file_navigator_resolve_identity_xrays.xhtml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/dom/base/test/file_receiveMessage.html b/dom/base/test/file_receiveMessage.html new file mode 100644 index 0000000000..66f421270f --- /dev/null +++ b/dom/base/test/file_receiveMessage.html @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/dom/base/test/file_restrictedEventSource.sjs b/dom/base/test/file_restrictedEventSource.sjs new file mode 100644 index 0000000000..b7ca11002a --- /dev/null +++ b/dom/base/test/file_restrictedEventSource.sjs @@ -0,0 +1,69 @@ +function handleRequest(request, response) { + if ( + (request.queryString == "test=user1_xhr" && + request.hasHeader("Authorization") && + request.getHeader("Authorization") == "Basic dXNlciAxOnBhc3N3b3JkIDE=") || + (request.queryString == "test=user1_evtsrc" && + request.hasHeader("Authorization") && + request.getHeader("Authorization") == "Basic dXNlciAxOnBhc3N3b3JkIDE=") + ) { + response.setStatusLine(null, 200, "OK"); + response.setHeader("Content-Type", "text/event-stream", false); + response.setHeader( + "Access-Control-Allow-Origin", + "http://mochi.test:8888", + false + ); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + response.setHeader("Cache-Control", "no-cache, must-revalidate", false); + if (request.queryString == "test=user1_xhr") { + response.setHeader("Set-Cookie", "test=5c", false); + } + response.write("event: message\ndata: 1\n\n"); + } else if ( + (request.queryString == "test=user2_xhr" && + request.hasHeader("Authorization") && + request.getHeader("Authorization") == "Basic dXNlciAyOnBhc3N3b3JkIDI=") || + (request.queryString == "test=user2_evtsrc" && + request.hasHeader("Authorization") && + request.getHeader("Authorization") == "Basic dXNlciAyOnBhc3N3b3JkIDI=" && + request.hasHeader("Cookie") && + request.getHeader("Cookie") == "test=5d") + ) { + response.setStatusLine(null, 200, "OK"); + response.setHeader("Content-Type", "text/event-stream", false); + response.setHeader( + "Access-Control-Allow-Origin", + "http://mochi.test:8888", + false + ); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + response.setHeader("Cache-Control", "no-cache, must-revalidate", false); + if (request.queryString == "test=user2_xhr") { + response.setHeader("Set-Cookie", "test=5d", false); + } + response.write("event: message\ndata: 1\n\n"); + } else if ( + request.queryString == "test=user1_xhr" || + request.queryString == "test=user2_xhr" + ) { + response.setStatusLine(null, 401, "Unauthorized"); + response.setHeader("WWW-Authenticate", 'basic realm="restricted"', false); + response.setHeader( + "Access-Control-Allow-Origin", + "http://mochi.test:8888", + false + ); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + response.write("Unauthorized"); + } else { + response.setStatusLine(null, 403, "Forbidden"); + response.setHeader( + "Access-Control-Allow-Origin", + "http://mochi.test:8888", + false + ); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + response.write("Forbidden"); + } +} diff --git a/dom/base/test/file_sandbox_and_document_uri.html b/dom/base/test/file_sandbox_and_document_uri.html new file mode 100644 index 0000000000..ac23cd1fec --- /dev/null +++ b/dom/base/test/file_sandbox_and_document_uri.html @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/dom/base/test/file_script.js b/dom/base/test/file_script.js new file mode 100644 index 0000000000..3e15525fa6 --- /dev/null +++ b/dom/base/test/file_script.js @@ -0,0 +1 @@ +window.scriptRan = true; diff --git a/dom/base/test/file_script_module_dynamic_and_element.html b/dom/base/test/file_script_module_dynamic_and_element.html new file mode 100644 index 0000000000..3614ed6a99 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_element.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_dynamic_and_element.mjs b/dom/base/test/file_script_module_dynamic_and_element.mjs new file mode 100644 index 0000000000..ead071d159 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_element.mjs @@ -0,0 +1,20 @@ +const { f } = await import( + "./file_script_module_dynamic_and_element_imported_1.mjs" +); +import { g } from "./file_script_module_dynamic_and_element_imported_2.mjs"; +import { h } from "./file_script_module_dynamic_and_element_imported_3.mjs"; + +f(); +g(); +h(); + +let script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute( + "src", + "file_script_module_dynamic_and_element_imported_1.mjs" +); +document.body.appendChild(script); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_dynamic_and_element_imported_1.mjs b/dom/base/test/file_script_module_dynamic_and_element_imported_1.mjs new file mode 100644 index 0000000000..f58abdf254 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_element_imported_1.mjs @@ -0,0 +1,7 @@ +import { g } from "./file_script_module_dynamic_and_element_imported_2.mjs"; +import { h } from "./file_script_module_dynamic_and_element_imported_3.mjs"; + +g(); +h(); + +export function f() {} diff --git a/dom/base/test/file_script_module_dynamic_and_element_imported_2.mjs b/dom/base/test/file_script_module_dynamic_and_element_imported_2.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_element_imported_2.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_dynamic_and_element_imported_3.mjs b/dom/base/test/file_script_module_dynamic_and_element_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_element_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_script_module_dynamic_and_static.html b/dom/base/test/file_script_module_dynamic_and_static.html new file mode 100644 index 0000000000..4ecd6c74a3 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_static.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_dynamic_and_static.mjs b/dom/base/test/file_script_module_dynamic_and_static.mjs new file mode 100644 index 0000000000..da8fff4002 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_static.mjs @@ -0,0 +1,11 @@ +const { f } = await import( + "./file_script_module_dynamic_and_static_imported_1.mjs" +); +import { g } from "./file_script_module_dynamic_and_static_imported_2.mjs"; +import { h } from "./file_script_module_dynamic_and_static_imported_3.mjs"; + +f(); +g(); +h(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_dynamic_and_static_imported_1.mjs b/dom/base/test/file_script_module_dynamic_and_static_imported_1.mjs new file mode 100644 index 0000000000..3a752224a9 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_static_imported_1.mjs @@ -0,0 +1,5 @@ +import { h } from "./file_script_module_dynamic_and_static_imported_3.mjs"; + +h(); + +export function f() {} diff --git a/dom/base/test/file_script_module_dynamic_and_static_imported_2.mjs b/dom/base/test/file_script_module_dynamic_and_static_imported_2.mjs new file mode 100644 index 0000000000..e00553b7e4 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_static_imported_2.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_dynamic_and_static_imported_1.mjs"; + +f(); + +export function g() {} diff --git a/dom/base/test/file_script_module_dynamic_and_static_imported_3.mjs b/dom/base/test/file_script_module_dynamic_and_static_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_and_static_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_script_module_dynamic_import.html b/dom/base/test/file_script_module_dynamic_import.html new file mode 100644 index 0000000000..3222e0dc5e --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_import.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_dynamic_import.mjs b/dom/base/test/file_script_module_dynamic_import.mjs new file mode 100644 index 0000000000..10c0186e69 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_import.mjs @@ -0,0 +1,4 @@ +const { f } = await import("./file_script_module_dynamic_import_imported.mjs"); +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_dynamic_import_imported.mjs b/dom/base/test/file_script_module_dynamic_import_imported.mjs new file mode 100644 index 0000000000..8b38a11158 --- /dev/null +++ b/dom/base/test/file_script_module_dynamic_import_imported.mjs @@ -0,0 +1 @@ +export function f() {} diff --git a/dom/base/test/file_script_module_element_and_dynamic.html b/dom/base/test/file_script_module_element_and_dynamic.html new file mode 100644 index 0000000000..ceec5c2c64 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_dynamic.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_element_and_dynamic.mjs b/dom/base/test/file_script_module_element_and_dynamic.mjs new file mode 100644 index 0000000000..3eeba5f28d --- /dev/null +++ b/dom/base/test/file_script_module_element_and_dynamic.mjs @@ -0,0 +1,11 @@ +const { f } = await import( + "./file_script_module_element_and_dynamic_imported_1.mjs" +); +import { g } from "./file_script_module_element_and_dynamic_imported_2.mjs"; +import { h } from "./file_script_module_element_and_dynamic_imported_3.mjs"; + +f(); +g(); +h(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_element_and_dynamic_imported_1.mjs b/dom/base/test/file_script_module_element_and_dynamic_imported_1.mjs new file mode 100644 index 0000000000..cf09ed7dde --- /dev/null +++ b/dom/base/test/file_script_module_element_and_dynamic_imported_1.mjs @@ -0,0 +1,13 @@ +import { g } from "./file_script_module_element_and_dynamic_imported_2.mjs"; +import { h } from "./file_script_module_element_and_dynamic_imported_3.mjs"; + +g(); +h(); + +export function f() {} + +let script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute("src", "file_script_module_element_and_dynamic.mjs"); +document.body.appendChild(script); diff --git a/dom/base/test/file_script_module_element_and_dynamic_imported_2.mjs b/dom/base/test/file_script_module_element_and_dynamic_imported_2.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_dynamic_imported_2.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_element_and_dynamic_imported_3.mjs b/dom/base/test/file_script_module_element_and_dynamic_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_dynamic_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_script_module_element_and_import.html b/dom/base/test/file_script_module_element_and_import.html new file mode 100644 index 0000000000..483a97a61c --- /dev/null +++ b/dom/base/test/file_script_module_element_and_import.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_element_and_import.mjs b/dom/base/test/file_script_module_element_and_import.mjs new file mode 100644 index 0000000000..1c10b2b300 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_import.mjs @@ -0,0 +1,9 @@ +import { f } from "./file_script_module_element_and_import_imported_1.mjs"; +import { g } from "./file_script_module_element_and_import_imported_2.mjs"; +import { h } from "./file_script_module_element_and_import_imported_3.mjs"; + +f(); +g(); +h(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_element_and_import_imported_1.mjs b/dom/base/test/file_script_module_element_and_import_imported_1.mjs new file mode 100644 index 0000000000..358b1e34bd --- /dev/null +++ b/dom/base/test/file_script_module_element_and_import_imported_1.mjs @@ -0,0 +1,13 @@ +import { g } from "./file_script_module_element_and_import_imported_2.mjs"; +import { h } from "./file_script_module_element_and_import_imported_3.mjs"; + +g(); +h(); + +export function f() {} + +let script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute("src", "file_script_module_element_and_import.mjs"); +document.body.appendChild(script); diff --git a/dom/base/test/file_script_module_element_and_import_imported_2.mjs b/dom/base/test/file_script_module_element_and_import_imported_2.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_import_imported_2.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_element_and_import_imported_3.mjs b/dom/base/test/file_script_module_element_and_import_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_element_and_import_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_script_module_frames_dynamic.html b/dom/base/test/file_script_module_frames_dynamic.html new file mode 100644 index 0000000000..9f07e094fa --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic.html @@ -0,0 +1,24 @@ + + + + + Test module script bytecode across iframe + + + + + + + diff --git a/dom/base/test/file_script_module_frames_dynamic_load.html b/dom/base/test/file_script_module_frames_dynamic_load.html new file mode 100644 index 0000000000..228ef710b3 --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic_load.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_dynamic_load.mjs b/dom/base/test/file_script_module_frames_dynamic_load.mjs new file mode 100644 index 0000000000..ed7ca91fd4 --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic_load.mjs @@ -0,0 +1,4 @@ +const { f } = await import("./file_script_module_frames_dynamic_shared.mjs"); +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_frames_dynamic_save.html b/dom/base/test/file_script_module_frames_dynamic_save.html new file mode 100644 index 0000000000..13d07d4b95 --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic_save.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_dynamic_save.mjs b/dom/base/test/file_script_module_frames_dynamic_save.mjs new file mode 100644 index 0000000000..ed7ca91fd4 --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic_save.mjs @@ -0,0 +1,4 @@ +const { f } = await import("./file_script_module_frames_dynamic_shared.mjs"); +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_frames_dynamic_shared.mjs b/dom/base/test/file_script_module_frames_dynamic_shared.mjs new file mode 100644 index 0000000000..8b38a11158 --- /dev/null +++ b/dom/base/test/file_script_module_frames_dynamic_shared.mjs @@ -0,0 +1 @@ +export function f() {} diff --git a/dom/base/test/file_script_module_frames_element.html b/dom/base/test/file_script_module_frames_element.html new file mode 100644 index 0000000000..aec8dfa5f0 --- /dev/null +++ b/dom/base/test/file_script_module_frames_element.html @@ -0,0 +1,24 @@ + + + + + Test module script bytecode across iframe + + + + + + + diff --git a/dom/base/test/file_script_module_frames_element_load.html b/dom/base/test/file_script_module_frames_element_load.html new file mode 100644 index 0000000000..a35c188ce2 --- /dev/null +++ b/dom/base/test/file_script_module_frames_element_load.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_element_save.html b/dom/base/test/file_script_module_frames_element_save.html new file mode 100644 index 0000000000..186d55e024 --- /dev/null +++ b/dom/base/test/file_script_module_frames_element_save.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_element_shared.mjs b/dom/base/test/file_script_module_frames_element_shared.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_frames_element_shared.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_frames_import.html b/dom/base/test/file_script_module_frames_import.html new file mode 100644 index 0000000000..a71d372724 --- /dev/null +++ b/dom/base/test/file_script_module_frames_import.html @@ -0,0 +1,24 @@ + + + + + Test module script bytecode across iframe + + + + + + + diff --git a/dom/base/test/file_script_module_frames_import_load.html b/dom/base/test/file_script_module_frames_import_load.html new file mode 100644 index 0000000000..9e1a11f19d --- /dev/null +++ b/dom/base/test/file_script_module_frames_import_load.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_import_load.mjs b/dom/base/test/file_script_module_frames_import_load.mjs new file mode 100644 index 0000000000..96353ac0e1 --- /dev/null +++ b/dom/base/test/file_script_module_frames_import_load.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_frames_import_shared.mjs"; + +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_frames_import_save.html b/dom/base/test/file_script_module_frames_import_save.html new file mode 100644 index 0000000000..4949de345f --- /dev/null +++ b/dom/base/test/file_script_module_frames_import_save.html @@ -0,0 +1,19 @@ + + + + + Test module script bytecode across iframe + + + + + + diff --git a/dom/base/test/file_script_module_frames_import_save.mjs b/dom/base/test/file_script_module_frames_import_save.mjs new file mode 100644 index 0000000000..96353ac0e1 --- /dev/null +++ b/dom/base/test/file_script_module_frames_import_save.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_frames_import_shared.mjs"; + +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_frames_import_shared.mjs b/dom/base/test/file_script_module_frames_import_shared.mjs new file mode 100644 index 0000000000..8b38a11158 --- /dev/null +++ b/dom/base/test/file_script_module_frames_import_shared.mjs @@ -0,0 +1 @@ +export function f() {} diff --git a/dom/base/test/file_script_module_frames_relay.js b/dom/base/test/file_script_module_frames_relay.js new file mode 100644 index 0000000000..141f202962 --- /dev/null +++ b/dom/base/test/file_script_module_frames_relay.js @@ -0,0 +1,22 @@ +function relay(event) { + if (event.type != "test_evaluated") { + if (!/^watchme/.test(event.target.id)) { + return; + } + } + + const type = `${window.name}_${event.type}`; + + window.parent.dispatchEvent(new window.parent.Event(type)); +} + +window.addEventListener("scriptloader_load_source", relay); +window.addEventListener("scriptloader_load_bytecode", relay); +window.addEventListener("scriptloader_execute", relay); +window.addEventListener("scriptloader_evaluate_module", relay); +window.addEventListener("scriptloader_encode", relay); +window.addEventListener("scriptloader_no_encode", relay); +window.addEventListener("scriptloader_bytecode_saved", relay); +window.addEventListener("scriptloader_bytecode_failed", relay); +window.addEventListener("scriptloader_fallback", relay); +window.addEventListener("test_evaluated", relay); diff --git a/dom/base/test/file_script_module_import.html b/dom/base/test/file_script_module_import.html new file mode 100644 index 0000000000..f12e0db913 --- /dev/null +++ b/dom/base/test/file_script_module_import.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_import.mjs b/dom/base/test/file_script_module_import.mjs new file mode 100644 index 0000000000..6574dbdfb3 --- /dev/null +++ b/dom/base/test/file_script_module_import.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_import_imported.mjs"; + +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_import_and_element.html b/dom/base/test/file_script_module_import_and_element.html new file mode 100644 index 0000000000..b376028ce6 --- /dev/null +++ b/dom/base/test/file_script_module_import_and_element.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_import_and_element.mjs b/dom/base/test/file_script_module_import_and_element.mjs new file mode 100644 index 0000000000..c16f07dec7 --- /dev/null +++ b/dom/base/test/file_script_module_import_and_element.mjs @@ -0,0 +1,18 @@ +import { f } from "./file_script_module_import_and_element_imported_1.mjs"; +import { g } from "./file_script_module_import_and_element_imported_2.mjs"; +import { h } from "./file_script_module_import_and_element_imported_3.mjs"; + +f(); +g(); +h(); + +let script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute( + "src", + "file_script_module_import_and_element_imported_1.mjs" +); +document.body.appendChild(script); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_import_and_element_imported_1.mjs b/dom/base/test/file_script_module_import_and_element_imported_1.mjs new file mode 100644 index 0000000000..6371cf2a4f --- /dev/null +++ b/dom/base/test/file_script_module_import_and_element_imported_1.mjs @@ -0,0 +1,7 @@ +import { g } from "./file_script_module_import_and_element_imported_2.mjs"; +import { h } from "./file_script_module_import_and_element_imported_3.mjs"; + +g(); +h(); + +export function f() {} diff --git a/dom/base/test/file_script_module_import_and_element_imported_2.mjs b/dom/base/test/file_script_module_import_and_element_imported_2.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_import_and_element_imported_2.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_import_and_element_imported_3.mjs b/dom/base/test/file_script_module_import_and_element_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_import_and_element_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_script_module_import_imported.mjs b/dom/base/test/file_script_module_import_imported.mjs new file mode 100644 index 0000000000..8b38a11158 --- /dev/null +++ b/dom/base/test/file_script_module_import_imported.mjs @@ -0,0 +1 @@ +export function f() {} diff --git a/dom/base/test/file_script_module_import_multi.html b/dom/base/test/file_script_module_import_multi.html new file mode 100644 index 0000000000..58e08c5d0a --- /dev/null +++ b/dom/base/test/file_script_module_import_multi.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_import_multi.mjs b/dom/base/test/file_script_module_import_multi.mjs new file mode 100644 index 0000000000..f3a2f38fe8 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi.mjs @@ -0,0 +1,7 @@ +import { f } from "./file_script_module_import_multi_imported_once.mjs"; +import { g } from "./file_script_module_import_multi_imported_twice.mjs"; + +f(); +g(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_import_multi_elems.html b/dom/base/test/file_script_module_import_multi_elems.html new file mode 100644 index 0000000000..27c1cb6904 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_import_multi_elems_1.mjs b/dom/base/test/file_script_module_import_multi_elems_1.mjs new file mode 100644 index 0000000000..2e421242fb --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_1.mjs @@ -0,0 +1,15 @@ +import { f } from "./file_script_module_import_multi_elems_imported_once_1.mjs"; +import { h } from "./file_script_module_import_multi_elems_imported_twice.mjs"; + +f(); +h(); + +// Dynamically insert the element after loading all source, so that +// the module import doesn't race. +const script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute("src", "file_script_module_import_multi_elems_2.mjs"); +document.body.appendChild(script); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_import_multi_elems_2.mjs b/dom/base/test/file_script_module_import_multi_elems_2.mjs new file mode 100644 index 0000000000..df06378ebc --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_2.mjs @@ -0,0 +1,7 @@ +import { g } from "./file_script_module_import_multi_elems_imported_once_2.mjs"; +import { h } from "./file_script_module_import_multi_elems_imported_twice.mjs"; + +g(); +h(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_import_multi_elems_imported_once_1.mjs b/dom/base/test/file_script_module_import_multi_elems_imported_once_1.mjs new file mode 100644 index 0000000000..8b38a11158 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_imported_once_1.mjs @@ -0,0 +1 @@ +export function f() {} diff --git a/dom/base/test/file_script_module_import_multi_elems_imported_once_2.mjs b/dom/base/test/file_script_module_import_multi_elems_imported_once_2.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_imported_once_2.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_import_multi_elems_imported_once_3.mjs b/dom/base/test/file_script_module_import_multi_elems_imported_once_3.mjs new file mode 100644 index 0000000000..411595cafc --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_imported_once_3.mjs @@ -0,0 +1 @@ +export function i() {} diff --git a/dom/base/test/file_script_module_import_multi_elems_imported_twice.mjs b/dom/base/test/file_script_module_import_multi_elems_imported_twice.mjs new file mode 100644 index 0000000000..0b846e478e --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_elems_imported_twice.mjs @@ -0,0 +1,4 @@ +import { i } from "./file_script_module_import_multi_elems_imported_once_3.mjs"; + +i(); +export function h() {} diff --git a/dom/base/test/file_script_module_import_multi_imported_once.mjs b/dom/base/test/file_script_module_import_multi_imported_once.mjs new file mode 100644 index 0000000000..9a04303d66 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_imported_once.mjs @@ -0,0 +1,5 @@ +import { g } from "./file_script_module_import_multi_imported_twice.mjs"; + +g(); + +export function f() {} diff --git a/dom/base/test/file_script_module_import_multi_imported_twice.mjs b/dom/base/test/file_script_module_import_multi_imported_twice.mjs new file mode 100644 index 0000000000..f75e8c9b21 --- /dev/null +++ b/dom/base/test/file_script_module_import_multi_imported_twice.mjs @@ -0,0 +1 @@ +export function g() {} diff --git a/dom/base/test/file_script_module_single.html b/dom/base/test/file_script_module_single.html new file mode 100644 index 0000000000..d02a7b5c53 --- /dev/null +++ b/dom/base/test/file_script_module_single.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_single.mjs b/dom/base/test/file_script_module_single.mjs new file mode 100644 index 0000000000..9a5745f516 --- /dev/null +++ b/dom/base/test/file_script_module_single.mjs @@ -0,0 +1,8 @@ +function baz() {} +function bar() {} +function foo() { + bar(); +} +foo(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_basic.html b/dom/base/test/file_script_module_sri_basic.html new file mode 100644 index 0000000000..d762218d6b --- /dev/null +++ b/dom/base/test/file_script_module_sri_basic.html @@ -0,0 +1,11 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_basic.mjs b/dom/base/test/file_script_module_sri_basic.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_sri_basic.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_basic_prep.html b/dom/base/test/file_script_module_sri_basic_prep.html new file mode 100644 index 0000000000..d762218d6b --- /dev/null +++ b/dom/base/test/file_script_module_sri_basic_prep.html @@ -0,0 +1,11 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_dynamic_elem.html b/dom/base/test/file_script_module_sri_dynamic_elem.html new file mode 100644 index 0000000000..d178f919be --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_dynamic_elem.mjs b/dom/base/test/file_script_module_sri_dynamic_elem.mjs new file mode 100644 index 0000000000..5a3552a106 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem.mjs @@ -0,0 +1,6 @@ +const { f } = await import( + "./file_script_module_sri_dynamic_elem_imported.mjs" +); +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_imported.mjs b/dom/base/test/file_script_module_sri_dynamic_elem_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.html b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.html new file mode 100644 index 0000000000..f81e10497d --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.mjs b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.mjs new file mode 100644 index 0000000000..638ac3b298 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload.mjs @@ -0,0 +1,20 @@ +const { f } = await import( + "./file_script_module_sri_dynamic_elem_nopreload_imported.mjs" +); +f(); + +// Dynamically insert the script element in order to suppress preload. +const script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute( + "src", + "file_script_module_sri_dynamic_elem_nopreload_imported.mjs" +); +script.setAttribute( + "integrity", + "sha384-3XSIfAj4/GALfWzL3T89+t3eaLIY59g8IWz1qq59xKnEW3aGd4cz7XvdcYqoK2+J" +); +document.body.appendChild(script); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_imported.mjs b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_prep.html b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_prep.html new file mode 100644 index 0000000000..40f8cdc692 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_nopreload_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_dynamic_elem_prep.html b/dom/base/test/file_script_module_sri_dynamic_elem_prep.html new file mode 100644 index 0000000000..c4c8367836 --- /dev/null +++ b/dom/base/test/file_script_module_sri_dynamic_elem_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_dynamic.html b/dom/base/test/file_script_module_sri_elem_dynamic.html new file mode 100644 index 0000000000..1aee3802ba --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_dynamic.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_dynamic.mjs b/dom/base/test/file_script_module_sri_elem_dynamic.mjs new file mode 100644 index 0000000000..a45a1c5756 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_dynamic.mjs @@ -0,0 +1,6 @@ +const { f } = await import( + "./file_script_module_sri_elem_dynamic_imported.mjs" +); +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_dynamic_imported.mjs b/dom/base/test/file_script_module_sri_elem_dynamic_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_dynamic_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_dynamic_prep.html b/dom/base/test/file_script_module_sri_elem_dynamic_prep.html new file mode 100644 index 0000000000..a4e9c7e3c1 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_dynamic_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_elem_1.html b/dom/base/test/file_script_module_sri_elem_elem_1.html new file mode 100644 index 0000000000..fafc07378c --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_1.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_elem_1.mjs b/dom/base/test/file_script_module_sri_elem_elem_1.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_1.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_elem_1_prep.html b/dom/base/test/file_script_module_sri_elem_elem_1_prep.html new file mode 100644 index 0000000000..a96d200c16 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_1_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_elem_2.html b/dom/base/test/file_script_module_sri_elem_elem_2.html new file mode 100644 index 0000000000..6df0a23061 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_2.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_elem_2.mjs b/dom/base/test/file_script_module_sri_elem_elem_2.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_2.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_elem_2_prep.html b/dom/base/test/file_script_module_sri_elem_elem_2_prep.html new file mode 100644 index 0000000000..d07887731b --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_elem_2_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_import.html b/dom/base/test/file_script_module_sri_elem_import.html new file mode 100644 index 0000000000..d8a04951c6 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_import.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_elem_import.mjs b/dom/base/test/file_script_module_sri_elem_import.mjs new file mode 100644 index 0000000000..acdd930cff --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_import.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_sri_elem_import_imported.mjs"; + +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_import_imported.mjs b/dom/base/test/file_script_module_sri_elem_import_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_import_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_elem_import_prep.html b/dom/base/test/file_script_module_sri_elem_import_prep.html new file mode 100644 index 0000000000..69ee5ba072 --- /dev/null +++ b/dom/base/test/file_script_module_sri_elem_import_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_fallback.html b/dom/base/test/file_script_module_sri_fallback.html new file mode 100644 index 0000000000..19a9c5e70a --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback.html @@ -0,0 +1,11 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_fallback.mjs b/dom/base/test/file_script_module_sri_fallback.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_fallback_failure.html b/dom/base/test/file_script_module_sri_fallback_failure.html new file mode 100644 index 0000000000..ea61b449bf --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback_failure.html @@ -0,0 +1,15 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_fallback_failure.mjs b/dom/base/test/file_script_module_sri_fallback_failure.mjs new file mode 100644 index 0000000000..741b76cd09 --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback_failure.mjs @@ -0,0 +1 @@ +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_fallback_failure_prep.html b/dom/base/test/file_script_module_sri_fallback_failure_prep.html new file mode 100644 index 0000000000..b949060132 --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback_failure_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_fallback_prep.html b/dom/base/test/file_script_module_sri_fallback_prep.html new file mode 100644 index 0000000000..91456da399 --- /dev/null +++ b/dom/base/test/file_script_module_sri_fallback_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_import_elem.html b/dom/base/test/file_script_module_sri_import_elem.html new file mode 100644 index 0000000000..67ec02d66d --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem.html @@ -0,0 +1,12 @@ + + + + + Test module script bytecode fallback + + + + + + diff --git a/dom/base/test/file_script_module_sri_import_elem.mjs b/dom/base/test/file_script_module_sri_import_elem.mjs new file mode 100644 index 0000000000..d6fed48264 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem.mjs @@ -0,0 +1,5 @@ +import { f } from "./file_script_module_sri_import_elem_imported.mjs"; + +f(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_import_elem_imported.mjs b/dom/base/test/file_script_module_sri_import_elem_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_import_elem_nopreload.html b/dom/base/test/file_script_module_sri_import_elem_nopreload.html new file mode 100644 index 0000000000..5b2388cd44 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_nopreload.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_import_elem_nopreload.mjs b/dom/base/test/file_script_module_sri_import_elem_nopreload.mjs new file mode 100644 index 0000000000..beb7c4fa45 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_nopreload.mjs @@ -0,0 +1,19 @@ +import { f } from "./file_script_module_sri_import_elem_nopreload_imported.mjs"; + +f(); + +// Dynamically insert the script element in order to suppress preload. +const script = document.createElement("script"); +script.id = "watchme2"; +script.setAttribute("type", "module"); +script.setAttribute( + "src", + "file_script_module_sri_import_elem_nopreload_imported.mjs" +); +script.setAttribute( + "integrity", + "sha384-3XSIfAj4/GALfWzL3T89+t3eaLIY59g8IWz1qq59xKnEW3aGd4cz7XvdcYqoK2+J" +); +document.body.appendChild(script); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_import_elem_nopreload_imported.mjs b/dom/base/test/file_script_module_sri_import_elem_nopreload_imported.mjs new file mode 100644 index 0000000000..bf624148c0 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_nopreload_imported.mjs @@ -0,0 +1,3 @@ +export function f() {} + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_sri_import_elem_nopreload_prep.html b/dom/base/test/file_script_module_sri_import_elem_nopreload_prep.html new file mode 100644 index 0000000000..7467946340 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_nopreload_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_sri_import_elem_prep.html b/dom/base/test/file_script_module_sri_import_elem_prep.html new file mode 100644 index 0000000000..2c1b427653 --- /dev/null +++ b/dom/base/test/file_script_module_sri_import_elem_prep.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode fallback + + + + + diff --git a/dom/base/test/file_script_module_static_and_dynamic.html b/dom/base/test/file_script_module_static_and_dynamic.html new file mode 100644 index 0000000000..452fd2d61b --- /dev/null +++ b/dom/base/test/file_script_module_static_and_dynamic.html @@ -0,0 +1,10 @@ + + + + + Test module script bytecode + + + + + diff --git a/dom/base/test/file_script_module_static_and_dynamic.mjs b/dom/base/test/file_script_module_static_and_dynamic.mjs new file mode 100644 index 0000000000..8f6699315a --- /dev/null +++ b/dom/base/test/file_script_module_static_and_dynamic.mjs @@ -0,0 +1,9 @@ +import { f } from "./file_script_module_static_and_dynamic_imported_1.mjs"; +import { g } from "./file_script_module_static_and_dynamic_imported_2.mjs"; +import { h } from "./file_script_module_static_and_dynamic_imported_3.mjs"; + +f(); +g(); +h(); + +window.dispatchEvent(new Event("test_evaluated")); diff --git a/dom/base/test/file_script_module_static_and_dynamic_imported_1.mjs b/dom/base/test/file_script_module_static_and_dynamic_imported_1.mjs new file mode 100644 index 0000000000..4c027c78ef --- /dev/null +++ b/dom/base/test/file_script_module_static_and_dynamic_imported_1.mjs @@ -0,0 +1,5 @@ +import { h } from "./file_script_module_static_and_dynamic_imported_3.mjs"; + +h(); + +export function f() {} diff --git a/dom/base/test/file_script_module_static_and_dynamic_imported_2.mjs b/dom/base/test/file_script_module_static_and_dynamic_imported_2.mjs new file mode 100644 index 0000000000..63392ed71b --- /dev/null +++ b/dom/base/test/file_script_module_static_and_dynamic_imported_2.mjs @@ -0,0 +1,6 @@ +const { f } = await import( + "./file_script_module_static_and_dynamic_imported_1.mjs" +); +f(); + +export function g() {} diff --git a/dom/base/test/file_script_module_static_and_dynamic_imported_3.mjs b/dom/base/test/file_script_module_static_and_dynamic_imported_3.mjs new file mode 100644 index 0000000000..6b340b7588 --- /dev/null +++ b/dom/base/test/file_script_module_static_and_dynamic_imported_3.mjs @@ -0,0 +1 @@ +export function h() {} diff --git a/dom/base/test/file_serializer_noscript.html b/dom/base/test/file_serializer_noscript.html new file mode 100644 index 0000000000..440baf036c --- /dev/null +++ b/dom/base/test/file_serializer_noscript.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_setname.html b/dom/base/test/file_setname.html new file mode 100644 index 0000000000..0830feb53a --- /dev/null +++ b/dom/base/test/file_setname.html @@ -0,0 +1,8 @@ + + + + + + diff --git a/dom/base/test/file_settimeout_inner.html b/dom/base/test/file_settimeout_inner.html new file mode 100644 index 0000000000..8a6626528d --- /dev/null +++ b/dom/base/test/file_settimeout_inner.html @@ -0,0 +1,6 @@ + diff --git a/dom/base/test/file_suppressed_events_and_scrolling.html b/dom/base/test/file_suppressed_events_and_scrolling.html new file mode 100644 index 0000000000..edf6793dfb --- /dev/null +++ b/dom/base/test/file_suppressed_events_and_scrolling.html @@ -0,0 +1,30 @@ + + + + diff --git a/dom/base/test/file_suppressed_events_inner.html b/dom/base/test/file_suppressed_events_inner.html new file mode 100644 index 0000000000..44cc45254d --- /dev/null +++ b/dom/base/test/file_suppressed_events_inner.html @@ -0,0 +1,16 @@ + + + +Test event suppression + + +
              Inner
              + + + diff --git a/dom/base/test/file_suppressed_events_middle.html b/dom/base/test/file_suppressed_events_middle.html new file mode 100644 index 0000000000..86b1f05374 --- /dev/null +++ b/dom/base/test/file_suppressed_events_middle.html @@ -0,0 +1,10 @@ + + + +Test event suppression + + +
              Middle
              + + + diff --git a/dom/base/test/file_suppressed_events_top.html b/dom/base/test/file_suppressed_events_top.html new file mode 100644 index 0000000000..ca031abb70 --- /dev/null +++ b/dom/base/test/file_suppressed_events_top.html @@ -0,0 +1,79 @@ + + + +Test event suppression + + + + + + + +
              Top
              + + + + diff --git a/dom/base/test/file_suppressed_events_top_modalstate.html b/dom/base/test/file_suppressed_events_top_modalstate.html new file mode 100644 index 0000000000..e20938bb28 --- /dev/null +++ b/dom/base/test/file_suppressed_events_top_modalstate.html @@ -0,0 +1,79 @@ + + + +Test event suppression + + + + + + + +
              Top
              + + + + diff --git a/dom/base/test/file_suppressed_events_top_xhr.html b/dom/base/test/file_suppressed_events_top_xhr.html new file mode 100644 index 0000000000..79299e291e --- /dev/null +++ b/dom/base/test/file_suppressed_events_top_xhr.html @@ -0,0 +1,82 @@ + + + +Test event suppression + + + + + + + +
              Top
              + + + + diff --git a/dom/base/test/file_timer_flood.html b/dom/base/test/file_timer_flood.html new file mode 100644 index 0000000000..dc729d7e42 --- /dev/null +++ b/dom/base/test/file_timer_flood.html @@ -0,0 +1,19 @@ + + + + + + diff --git a/dom/base/test/file_title.xhtml b/dom/base/test/file_title.xhtml new file mode 100644 index 0000000000..d1b04418aa --- /dev/null +++ b/dom/base/test/file_title.xhtml @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_toScreenRect.html b/dom/base/test/file_toScreenRect.html new file mode 100644 index 0000000000..990d9326f2 --- /dev/null +++ b/dom/base/test/file_toScreenRect.html @@ -0,0 +1,48 @@ + + + + + +
              + diff --git a/dom/base/test/file_use_counter_bfcache.html b/dom/base/test/file_use_counter_bfcache.html new file mode 100644 index 0000000000..6baf738945 --- /dev/null +++ b/dom/base/test/file_use_counter_bfcache.html @@ -0,0 +1,38 @@ + + diff --git a/dom/base/test/file_use_counter_bfcache_helper.html b/dom/base/test/file_use_counter_bfcache_helper.html new file mode 100644 index 0000000000..a5da790ae6 --- /dev/null +++ b/dom/base/test/file_use_counter_bfcache_helper.html @@ -0,0 +1,40 @@ + +b +c + + diff --git a/dom/base/test/file_use_counter_outer.html b/dom/base/test/file_use_counter_outer.html new file mode 100644 index 0000000000..1a7eb90f7c --- /dev/null +++ b/dom/base/test/file_use_counter_outer.html @@ -0,0 +1,17 @@ + + + + + + Test for Bug 968923 + + +Mozilla Bug 968923 + + + + diff --git a/dom/base/test/file_use_counter_outer_display_none.html b/dom/base/test/file_use_counter_outer_display_none.html new file mode 100644 index 0000000000..22c4c4c8ab --- /dev/null +++ b/dom/base/test/file_use_counter_outer_display_none.html @@ -0,0 +1,16 @@ + + + + + + Test for Bug 968923 + + +Mozilla Bug 968923 + + + diff --git a/dom/base/test/file_use_counter_style.html b/dom/base/test/file_use_counter_style.html new file mode 100644 index 0000000000..4fd18195c2 --- /dev/null +++ b/dom/base/test/file_use_counter_style.html @@ -0,0 +1,14 @@ + + + +
              diff --git a/dom/base/test/file_use_counter_svg_currentScale.svg b/dom/base/test/file_use_counter_svg_currentScale.svg new file mode 100644 index 0000000000..cf4d64aba0 --- /dev/null +++ b/dom/base/test/file_use_counter_svg_currentScale.svg @@ -0,0 +1,17 @@ + + + Test graphic for hitting currentScale + + + + + + + + + diff --git a/dom/base/test/file_use_counter_svg_fill_pattern.svg b/dom/base/test/file_use_counter_svg_fill_pattern.svg new file mode 100644 index 0000000000..1cd84dd5e1 --- /dev/null +++ b/dom/base/test/file_use_counter_svg_fill_pattern.svg @@ -0,0 +1,16 @@ + + + Borrowed from http://www.w3.org/TR/SVG/pservers.html + + + + + + + + + diff --git a/dom/base/test/file_use_counter_svg_fill_pattern_data.svg b/dom/base/test/file_use_counter_svg_fill_pattern_data.svg new file mode 100644 index 0000000000..9a180b2432 --- /dev/null +++ b/dom/base/test/file_use_counter_svg_fill_pattern_data.svg @@ -0,0 +1,13 @@ + + + Borrowed from http://www.w3.org/TR/SVG/pservers.html + + + + + + diff --git a/dom/base/test/file_use_counter_svg_fill_pattern_definition.svg b/dom/base/test/file_use_counter_svg_fill_pattern_definition.svg new file mode 100644 index 0000000000..a84292a63f --- /dev/null +++ b/dom/base/test/file_use_counter_svg_fill_pattern_definition.svg @@ -0,0 +1,12 @@ + + + Borrowed from http://www.w3.org/TR/SVG/pservers.html + + + + + + diff --git a/dom/base/test/file_use_counter_svg_fill_pattern_internal.svg b/dom/base/test/file_use_counter_svg_fill_pattern_internal.svg new file mode 100644 index 0000000000..47adafe38c --- /dev/null +++ b/dom/base/test/file_use_counter_svg_fill_pattern_internal.svg @@ -0,0 +1,24 @@ + + + Borrowed from http://www.w3.org/TR/SVG/pservers.html + + + + + + + + + + + + + + + diff --git a/dom/base/test/file_use_counter_svg_getElementById.svg b/dom/base/test/file_use_counter_svg_getElementById.svg new file mode 100644 index 0000000000..7cd12ba315 --- /dev/null +++ b/dom/base/test/file_use_counter_svg_getElementById.svg @@ -0,0 +1,22 @@ + + + Test graphic for hitting getElementById + + + + + + + + + diff --git a/dom/base/test/file_viewport_metrics_on_landscape_content.html b/dom/base/test/file_viewport_metrics_on_landscape_content.html new file mode 100644 index 0000000000..02b079aeac --- /dev/null +++ b/dom/base/test/file_viewport_metrics_on_landscape_content.html @@ -0,0 +1,65 @@ + + + + + +
              + + diff --git a/dom/base/test/file_viewport_scroll_quirks.html b/dom/base/test/file_viewport_scroll_quirks.html new file mode 100644 index 0000000000..992b8a9968 --- /dev/null +++ b/dom/base/test/file_viewport_scroll_quirks.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_viewport_scroll_xml.xml b/dom/base/test/file_viewport_scroll_xml.xml new file mode 100644 index 0000000000..1453e9b1ea --- /dev/null +++ b/dom/base/test/file_viewport_scroll_xml.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/file_webaudio_startstop.html b/dom/base/test/file_webaudio_startstop.html new file mode 100644 index 0000000000..c0e4fafb01 --- /dev/null +++ b/dom/base/test/file_webaudio_startstop.html @@ -0,0 +1,36 @@ + + diff --git a/dom/base/test/file_window_close.html b/dom/base/test/file_window_close.html new file mode 100644 index 0000000000..5adec04ec4 --- /dev/null +++ b/dom/base/test/file_window_close.html @@ -0,0 +1,68 @@ + + + + + + + + diff --git a/dom/base/test/file_window_close_2.html b/dom/base/test/file_window_close_2.html new file mode 100644 index 0000000000..c06ec90a8b --- /dev/null +++ b/dom/base/test/file_window_close_2.html @@ -0,0 +1,4 @@ + + + + diff --git a/dom/base/test/file_window_focus_by_close_and_open.html b/dom/base/test/file_window_focus_by_close_and_open.html new file mode 100644 index 0000000000..ab5ad72ae3 --- /dev/null +++ b/dom/base/test/file_window_focus_by_close_and_open.html @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/dom/base/test/file_x-frame-options_main.html b/dom/base/test/file_x-frame-options_main.html new file mode 100644 index 0000000000..903f951e08 --- /dev/null +++ b/dom/base/test/file_x-frame-options_main.html @@ -0,0 +1,44 @@ + + +X-Frame-Options tests + + + + +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              + + + + + + + diff --git a/dom/base/test/file_x-frame-options_page.sjs b/dom/base/test/file_x-frame-options_page.sjs new file mode 100644 index 0000000000..13c9aa7cac --- /dev/null +++ b/dom/base/test/file_x-frame-options_page.sjs @@ -0,0 +1,67 @@ +// SJS file for X-Frame-Options mochitests +function handleRequest(request, response) { + var query = {}; + var BOUNDARY = "BOUNDARYOMG3984"; + request.queryString.split("&").forEach(function (val) { + var [name, value] = val.split("="); + query[name] = unescape(value); + }); + + if (query.multipart == "1") { + response.setHeader( + "Content-Type", + "multipart/x-mixed-replace;boundary=" + BOUNDARY, + false + ); + response.setHeader("Cache-Control", "no-cache", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.write("--" + BOUNDARY + "\r\n"); + response.write("Content-Type: text/html\r\n\r\n"); + } else { + response.setHeader("Content-Type", "text/html", false); + response.setHeader("Cache-Control", "no-cache", false); + } + + var testHeaders = { + deny: "DENY", + sameorigin: "SAMEORIGIN", + sameorigin2: "SAMEORIGIN, SAMEORIGIN", + sameorigin3: "SAMEORIGIN,SAMEORIGIN , SAMEORIGIN", + mixedpolicy: "DENY,SAMEORIGIN", + + /* added for bug 836132 */ + afa: "ALLOW-FROM http://mochi.test:8888/", + afd: "ALLOW-FROM http://example.com/", + afa1: "ALLOW-FROM http://mochi.test:8888", + afd1: "ALLOW-FROM:example.com", + afd2: "ALLOW-FROM: example.com", + afd3: "ALLOW-FROM example.com", + afd4: "ALLOW-FROM:http://example.com", + afd5: "ALLOW-FROM: http://example.com", + afd6: "ALLOW-FROM http://example.com", + afd7: "ALLOW-FROM:mochi.test:8888", + afd8: "ALLOW-FROM: mochi.test:8888", + afd9: "ALLOW-FROM:http://mochi.test:8888", + afd10: "ALLOW-FROM: http://mochi.test:8888", + afd11: "ALLOW-FROM mochi.test:8888", + afd12: "ALLOW-FROM", + afd13: "ALLOW-FROM ", + afd14: "ALLOW-FROM:", + }; + + if (testHeaders.hasOwnProperty(query.xfo)) { + response.setHeader("X-Frame-Options", testHeaders[query.xfo], false); + } + + // from the test harness we'll be checking for the presence of this element + // to test if the page loaded + response.write('

              ' + query.testid + "

              "); + + if (query.testid == "postmessage") { + response.write(""); + } + + if (query.multipart == "1") { + response.write("\r\n--" + BOUNDARY + "\r\n"); + } +} diff --git a/dom/base/test/file_xhtmlserializer_1.xhtml b/dom/base/test/file_xhtmlserializer_1.xhtml new file mode 100644 index 0000000000..64271ce2ce --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1.xhtml @@ -0,0 +1,60 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + diff --git a/dom/base/test/file_xhtmlserializer_1_bodyonly.xhtml b/dom/base/test/file_xhtmlserializer_1_bodyonly.xhtml new file mode 100644 index 0000000000..fbefe91d6e --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_bodyonly.xhtml @@ -0,0 +1,56 @@ + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_format.xhtml b/dom/base/test/file_xhtmlserializer_1_format.xhtml new file mode 100644 index 0000000000..d62cc367ba --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_format.xhtml @@ -0,0 +1,71 @@ + + + + + + Test for html serializer + + +

              Hello world

              +

              Lorem ipsum dolor sit amet, consectetuer + adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis + ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent + taciti sociosqu ad litora torquent per conubia + nostra, per inceptos hymenaeos.

              +
                +
              • Nam tellus massa,éàèçù
              • +
              • fringilla aliquam,
              • +
              • fermentum sit amet,
              • +
              • posuere ac,
              • +
              • est.
              • +
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + +
                +
              1. Fusce a ipsum
              2. +
              3. non lacus posuere aliquet.
              4. +
              5. Sed fermentum posuere nulla
              6. +
              7. Donec tempor.
              8. +
              + Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              + ut gravida eros
              + leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus + aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia
              +      libero ullamcorper laoreet.
              Cras quis
              nisi at + odio
              consectetuer molestie. Curabitur consectetuer urna a + sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in + faucibus orci luctus et ultrices posuere cubilia Curae; Sed + sollicitudin, nulla at pharetra rutrum, +
              + lacus risus pulvinar ante. +
              + + diff --git a/dom/base/test/file_xhtmlserializer_1_linebreak.xhtml b/dom/base/test/file_xhtmlserializer_1_linebreak.xhtml new file mode 100644 index 0000000000..a0aecdd2c6 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_linebreak.xhtml @@ -0,0 +1,65 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_links.xhtml b/dom/base/test/file_xhtmlserializer_1_links.xhtml new file mode 100644 index 0000000000..0c2814311b --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_links.xhtml @@ -0,0 +1,65 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + diff --git a/dom/base/test/file_xhtmlserializer_1_nested_body.xhtml b/dom/base/test/file_xhtmlserializer_1_nested_body.xhtml new file mode 100644 index 0000000000..120f8e7dcb --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_nested_body.xhtml @@ -0,0 +1,65 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              +

              this is an other body element

              + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_no_body.xhtml b/dom/base/test/file_xhtmlserializer_1_no_body.xhtml new file mode 100644 index 0000000000..6f5055bd57 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_no_body.xhtml @@ -0,0 +1,10 @@ + + + + + + Test for html serializer + + + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_noflag.xhtml b/dom/base/test/file_xhtmlserializer_1_noflag.xhtml new file mode 100644 index 0000000000..a0aecdd2c6 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_noflag.xhtml @@ -0,0 +1,65 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_noformatpre.xhtml b/dom/base/test/file_xhtmlserializer_1_noformatpre.xhtml new file mode 100644 index 0000000000..a5eb6e9692 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_noformatpre.xhtml @@ -0,0 +1,69 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              +
              + Cras quis
              +
              + nisi at odio
              +
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, 
              +
              +lacus risus pulvinar ante.
              +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_raw.xhtml b/dom/base/test/file_xhtmlserializer_1_raw.xhtml new file mode 100644 index 0000000000..d13fce2ccd --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_raw.xhtml @@ -0,0 +1,60 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_sibling_body.xhtml b/dom/base/test/file_xhtmlserializer_1_sibling_body.xhtml new file mode 100644 index 0000000000..9ef4840e36 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_sibling_body.xhtml @@ -0,0 +1,65 @@ + + + + + + Test for html serializer + + +

              this is an other body element

              +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml b/dom/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml new file mode 100644 index 0000000000..f9f92a0670 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml @@ -0,0 +1,56 @@ +

              this is an other body element

              +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad + litora torquent per conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_1_wrap.xhtml b/dom/base/test/file_xhtmlserializer_1_wrap.xhtml new file mode 100644 index 0000000000..6b156278ad --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_1_wrap.xhtml @@ -0,0 +1,70 @@ + + + + + + Test for html serializer + + + +

              Hello world

              + + Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. +Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu + ad + litora torquent per + conubia +nostra, per inceptos hymenaeos.

              + + +
              • Nam tellus massa,éàèçù
              • + fringilla +aliquam,
              • fermentum sit amet,
              • posuere ac,
              • est.
              +
              Duis tristique egestas ligula. Mauris quis felis.
              + + + +
              1. Fusce + a ipsum
              2. non lacus posuere aliquet.
              3. Sed fermentum +posuere nulla
              4. Donec tempor.
              +Donec sollicitudin tortor + +
              lacinia libero ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
              +lacus risus pulvinar ante. +
              +ut gravida eros
              leo ut libero + +

              + +

              Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus +aliquet lectus. Nunc vitae eros. Class aptent taciti

              +
              lacinia libero 
              +ullamcorper laoreet.
              + Cras quis
              + nisi at odio
              + consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non +urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci +luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at +pharetra rutrum,
              +lacus risus pulvinar ante. +
              + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_2.xhtml b/dom/base/test/file_xhtmlserializer_2.xhtml new file mode 100644 index 0000000000..2a9c55b95d --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_2.xhtml @@ -0,0 +1,30 @@ + + + + + Test for html serializer with entities + + + +

              The basic set is just " " & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ +Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø +Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê +ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý +þ ÿ

              +

              symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ +Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς +σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ +™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ +∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ ♦ +

              +

              others +Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’ +‚“ ” „ † ‡ ‰ ‹ › € +

              + + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_2_basic.xhtml b/dom/base/test/file_xhtmlserializer_2_basic.xhtml new file mode 100644 index 0000000000..c35cc48cf8 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_2_basic.xhtml @@ -0,0 +1,31 @@ + + + + + + Test for html serializer with entities + + + +

              The basic set is just " " & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À à Â Ã Ä Å Æ +Ç È É Ê Ë Ì à Î à à Ñ Ò Ó Ô Õ Ö × Ø +Ù Ú Û Ü à Þ ß à á â ã ä å æ ç è é ê +ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý +þ ÿ

              +

              symbols, math.. Æ’ Α Î’ Γ Δ Ε Ζ Η Θ Ι Κ Λ Îœ ΠΞ Ο Π Ρ Σ Τ Î¥ +Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο Ï€ Ï Ï‚ +σ Ï„ Ï… φ χ ψ ω Ï‘ Ï’ Ï– • … ′ ″ ‾ ℠℘ â„‘ â„œ +â„¢ ℵ ↠↑ → ↓ ↔ ↵ ⇠⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ +∋ ∠∑ − ∗ √ ∠∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ â‹… ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ â—Š â™  ♣ ♥ ♦ +

              +

              others +Å’ Å“ Å  Å¡ Ÿ ˆ Ëœ       ‌ †‎ â€â€“— ‘ ’ +‚“ †„ † ‡ ‰ ‹ › € +

              + + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_2_enthtml.xhtml b/dom/base/test/file_xhtmlserializer_2_enthtml.xhtml new file mode 100644 index 0000000000..0ba1c8421c --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_2_enthtml.xhtml @@ -0,0 +1,55 @@ + + + + + + Test for html serializer with entities + + + +

              The basic set is just   & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ +© ª « ¬ ­ ® ¯ ° ± ² +³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ +¾ ¿ À Á Â Ã Ä Å +Æ +Ç È É Ê Ë Ì Í Î +Ï Ð Ñ Ò Ó Ô Õ Ö × +Ø +Ù Ú Û Ü Ý Þ ß à +á â ã ä å æ ç è +é ê +ë ì í î ï ð ñ ò ó + ô õ ö ÷ ø ù ú û +ü ý +þ ÿ

              +

              symbols, math.. ƒ Α Β Γ Δ Ε +Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο +Π Ρ Σ Τ Υ +Φ Χ Ψ Ω α β γ δ ε +ζ η θ ι κ λ μ ν ξ ο +π ρ ς +σ τ υ φ χ ψ ω ϑ ϒ +ϖ • … ′ ″ ‾ ⁄ ℘ ℑ +ℜ +™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ +⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ +∈ ∉ +∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ +∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ +≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ +⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ +♦ +

              +

              others +Œ œ Š š Ÿ ˆ ˜     +  ‌ ‍ ‎ ‏–— ‘ ’ +‚“ ” „ † ‡ ‰ ‹ +› € +

              + + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_2_entw3c.xhtml b/dom/base/test/file_xhtmlserializer_2_entw3c.xhtml new file mode 100644 index 0000000000..0ba1c8421c --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_2_entw3c.xhtml @@ -0,0 +1,55 @@ + + + + + + Test for html serializer with entities + + + +

              The basic set is just   & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ +© ª « ¬ ­ ® ¯ ° ± ² +³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ +¾ ¿ À Á Â Ã Ä Å +Æ +Ç È É Ê Ë Ì Í Î +Ï Ð Ñ Ò Ó Ô Õ Ö × +Ø +Ù Ú Û Ü Ý Þ ß à +á â ã ä å æ ç è +é ê +ë ì í î ï ð ñ ò ó + ô õ ö ÷ ø ù ú û +ü ý +þ ÿ

              +

              symbols, math.. ƒ Α Β Γ Δ Ε +Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο +Π Ρ Σ Τ Υ +Φ Χ Ψ Ω α β γ δ ε +ζ η θ ι κ λ μ ν ξ ο +π ρ ς +σ τ υ φ χ ψ ω ϑ ϒ +ϖ • … ′ ″ ‾ ⁄ ℘ ℑ +ℜ +™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ +⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ +∈ ∉ +∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ +∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ +≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ +⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ +♦ +

              +

              others +Œ œ Š š Ÿ ˆ ˜     +  ‌ ‍ ‎ ‏–— ‘ ’ +‚“ ” „ † ‡ ‰ ‹ +› € +

              + + + \ No newline at end of file diff --git a/dom/base/test/file_xhtmlserializer_2_latin1.xhtml b/dom/base/test/file_xhtmlserializer_2_latin1.xhtml new file mode 100644 index 0000000000..59b564ca77 --- /dev/null +++ b/dom/base/test/file_xhtmlserializer_2_latin1.xhtml @@ -0,0 +1,41 @@ + + + + + + Test for html serializer with entities + + + +

              The basic set is just   & < > " for interoperability with older products that don't support α and friends.

              + +

              latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ +© ª « ¬ ­ ® ¯ ° ± ² +³ ´ +µ ¶ · ¸ ¹ º » ¼ ½ +¾ ¿ À Á Â Ã Ä Å +Æ +Ç È É Ê Ë Ì Í Î +Ï Ð Ñ Ò Ó Ô Õ Ö × +Ø +Ù Ú Û Ü Ý Þ ß à +á â ã ä å æ ç è +é ê +ë ì í î ï ð ñ ò ó + ô õ ö ÷ ø ù ú û +ü ý +þ ÿ

              +

              symbols, math.. Æ’ Α Î’ Γ Δ Ε Ζ Η Θ Ι Κ Λ Îœ ΠΞ Ο Π Ρ Σ Τ Î¥ +Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο Ï€ Ï Ï‚ +σ Ï„ Ï… φ χ ψ ω Ï‘ Ï’ Ï– • … ′ ″ ‾ ℠℘ â„‘ â„œ +â„¢ ℵ ↠↑ → ↓ ↔ ↵ ⇠⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ +∋ ∠∑ − ∗ √ ∠∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ +⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ â‹… ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ â—Š â™  ♣ ♥ ♦ +

              +

              others +Å’ Å“ Å  Å¡ Ÿ ˆ Ëœ       ‌ †‎ â€â€“— ‘ ’ +‚“ †„ † ‡ ‰ ‹ › € +

              + + + \ No newline at end of file diff --git a/dom/base/test/file_youtube_flash_embed.html b/dom/base/test/file_youtube_flash_embed.html new file mode 100644 index 0000000000..0eb63477f4 --- /dev/null +++ b/dom/base/test/file_youtube_flash_embed.html @@ -0,0 +1,65 @@ + + + + + + Test for Bug 1240471 + + + + + + + + + + diff --git a/dom/base/test/fmm/browser.toml b/dom/base/test/fmm/browser.toml new file mode 100644 index 0000000000..064189b03d --- /dev/null +++ b/dom/base/test/fmm/browser.toml @@ -0,0 +1,4 @@ +[DEFAULT] + +["browser_frame_message_manager_cache.js"] + diff --git a/dom/base/test/fmm/browser_frame_message_manager_cache.js b/dom/base/test/fmm/browser_frame_message_manager_cache.js new file mode 100644 index 0000000000..fcedd6721a --- /dev/null +++ b/dom/base/test/fmm/browser_frame_message_manager_cache.js @@ -0,0 +1,23 @@ +add_task(async function testCacheAfterInvalidate() { + // Load some page to make scripts cached. + let tab1 = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:addons" + ); + + // Discard ScriptPreloader cache. + Services.obs.notifyObservers(null, "startupcache-invalidate"); + + // Load some other page to use the cache in nsMessageManagerScriptExecutor + // cache. + let tab2 = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:preferences" + ); + + // Verify the browser doesn't crash. + ok(true); + + BrowserTestUtils.removeTab(tab1); + BrowserTestUtils.removeTab(tab2); +}); diff --git a/dom/base/test/forRemoval.resource b/dom/base/test/forRemoval.resource new file mode 100644 index 0000000000..09e882b3ba --- /dev/null +++ b/dom/base/test/forRemoval.resource @@ -0,0 +1,24 @@ +:this file must be enconded in utf8 +:and its Content-Type must be equal to text/event-stream + +retry:500 +event: message +data: 1 + +retry:500 +event: message +data: 2 + +retry:500 +event: message +data: 3 + +retry:500 +event: message +data: 4 + +retry:500 +event: message +data: 5 + + diff --git a/dom/base/test/forRemoval.resource^headers^ b/dom/base/test/forRemoval.resource^headers^ new file mode 100644 index 0000000000..6a63b5341d --- /dev/null +++ b/dom/base/test/forRemoval.resource^headers^ @@ -0,0 +1,3 @@ +Content-Type: text/event-stream +Cache-Control: no-cache, must-revalidate + diff --git a/dom/base/test/formReset.html b/dom/base/test/formReset.html new file mode 100644 index 0000000000..faee1e5b4d --- /dev/null +++ b/dom/base/test/formReset.html @@ -0,0 +1,15 @@ + + + + Form Elements + + + +

              Check me!
              + Uncheck me!
              +
              +
              +

              + + diff --git a/dom/base/test/fullscreen/MozDomFullscreen_chrome.xhtml b/dom/base/test/fullscreen/MozDomFullscreen_chrome.xhtml new file mode 100644 index 0000000000..93f00311e7 --- /dev/null +++ b/dom/base/test/fullscreen/MozDomFullscreen_chrome.xhtml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + diff --git a/dom/base/test/fullscreen/browser.toml b/dom/base/test/fullscreen/browser.toml new file mode 100644 index 0000000000..dc883a4ac2 --- /dev/null +++ b/dom/base/test/fullscreen/browser.toml @@ -0,0 +1,54 @@ +[DEFAULT] +tags = "fullscreen" +head = "head.js" +support-files = [ + "dummy_page.html", + "file_fullscreen-api-keys.html", + "file_fullscreen-iframe-inner.html", + "file_fullscreen-iframe-middle.html", + "file_fullscreen-iframe-top.html", + "file_fullscreen-newtab.html", + "fullscreen_helpers.js", +] + +["browser_fullscreen-api-keys.js"] + +["browser_fullscreen-bug-1798219.js"] +skip-if = ["!nightly_build"] # Bug 1818608 +support-files = [ + "file_fullscreen-bug-1798219.html", + "file_fullscreen-bug-1798219-2.html", +] + +["browser_fullscreen-contextmenu-esc.js"] + +["browser_fullscreen-document-mutation-navigation.js"] + +["browser_fullscreen-document-mutation-race.js"] + +["browser_fullscreen-document-mutation.js"] + +["browser_fullscreen-navigation-history-race.js"] + +["browser_fullscreen-navigation-history.js"] + +["browser_fullscreen-navigation-race.js"] + +["browser_fullscreen-navigation.js"] + +["browser_fullscreen-newtab.js"] +skip-if = [ + "os == 'mac'", # Bug 1494843 + "os == 'linux' && bits == 64 && os_version == '18.04'", # Bug 1601460 +] + +["browser_fullscreen-sizemode.js"] + +["browser_fullscreen-tab-close-race.js"] + +["browser_fullscreen-tab-close.js"] + +["browser_fullscreen-window-open-race.js"] +skip-if = ["os == 'mac'"] # test is checking for synchronous fullscreen completion + +["browser_fullscreen_exit_on_external_protocol.js"] diff --git a/dom/base/test/fullscreen/browser_fullscreen-api-keys.js b/dom/base/test/fullscreen/browser_fullscreen-api-keys.js new file mode 100644 index 0000000000..1b1a07975e --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-api-keys.js @@ -0,0 +1,218 @@ +"use strict"; + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +/** Test for Bug 545812 **/ + +// List of key codes which should exit full-screen mode. +const kKeyList = [ + { key: "Escape", keyCode: "VK_ESCAPE", suppressed: true }, + { key: "F11", keyCode: "VK_F11", suppressed: false }, +]; + +function receiveExpectedKeyEvents(aBrowser, aKeyCode, aTrusted) { + return SpecialPowers.spawn( + aBrowser, + [aKeyCode, aTrusted], + (keyCode, trusted) => { + return new Promise(resolve => { + let events = trusted + ? ["keydown", "keyup"] + : ["keydown", "keypress", "keyup"]; + if (trusted && keyCode == content.wrappedJSObject.KeyEvent.DOM_VK_F11) { + // trusted `F11` key shouldn't be fired because of reserved when it's + // a shortcut key for exiting from the full screen mode. + events.shift(); + } + function listener(event) { + let expected = events.shift(); + Assert.equal( + event.type, + expected, + `Should receive a ${expected} event` + ); + Assert.equal( + event.keyCode, + keyCode, + `Should receive the event with key code ${keyCode}` + ); + if (!events.length) { + content.document.removeEventListener("keydown", listener, true); + content.document.removeEventListener("keyup", listener, true); + content.document.removeEventListener("keypress", listener, true); + resolve(); + } + } + + content.document.addEventListener("keydown", listener, true); + content.document.addEventListener("keyup", listener, true); + content.document.addEventListener("keypress", listener, true); + }); + } + ); +} + +const kPage = + "https://example.org/browser/" + + "dom/base/test/fullscreen/file_fullscreen-api-keys.html"; + +add_task(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ); + + let tab = BrowserTestUtils.addTab(gBrowser, kPage); + let browser = tab.linkedBrowser; + gBrowser.selectedTab = tab; + registerCleanupFunction(() => gBrowser.removeTab(tab)); + await waitForDocLoadComplete(); + + // Wait for the document being activated, so that + // fullscreen request won't be denied. + await SpecialPowers.spawn(browser, [], () => { + return ContentTaskUtils.waitForCondition( + () => content.browsingContext.isActive && content.document.hasFocus(), + "document is active" + ); + }); + + // Register listener to capture unexpected events + let keyEventsCount = 0; + let fullScreenEventsCount = 0; + let removeFullScreenListener = BrowserTestUtils.addContentEventListener( + browser, + "fullscreenchange", + () => fullScreenEventsCount++ + ); + let removeKeyDownListener = BrowserTestUtils.addContentEventListener( + browser, + "keydown", + () => keyEventsCount++, + { wantUntrusted: true } + ); + let removeKeyPressListener = BrowserTestUtils.addContentEventListener( + browser, + "keypress", + () => keyEventsCount++, + { wantUntrusted: true } + ); + let removeKeyUpListener = BrowserTestUtils.addContentEventListener( + browser, + "keyup", + () => keyEventsCount++, + { wantUntrusted: true } + ); + + let expectedFullScreenEventsCount = 0; + let expectedKeyEventsCount = 0; + + for (let { key, keyCode, suppressed } of kKeyList) { + let keyCodeValue = KeyEvent["DOM_" + keyCode]; + info(`Test keycode ${key} (${keyCodeValue})`); + + info("Enter fullscreen"); + let state = new Promise(resolve => { + let removeFun = BrowserTestUtils.addContentEventListener( + browser, + "fullscreenchange", + async () => { + removeFun(); + resolve( + await SpecialPowers.spawn(browser, [], () => { + return !!content.document.fullscreenElement; + }) + ); + } + ); + }); + // request fullscreen + SpecialPowers.spawn(browser, [], () => { + content.document.body.requestFullscreen(); + }); + ok(await state, "The content should have entered fullscreen"); + ok(document.fullscreenElement, "The chrome should also be in fullscreen"); + + is( + fullScreenEventsCount, + ++expectedFullScreenEventsCount, + "correct number of fullscreen events occurred" + ); + + info("Dispatch untrusted key events from content"); + let promiseExpectedKeyEvents = receiveExpectedKeyEvents( + browser, + keyCodeValue, + false + ); + + SpecialPowers.spawn(browser, [keyCode], keyCodeChild => { + var evt = new content.CustomEvent("Test:DispatchKeyEvents", { + detail: Cu.cloneInto({ code: keyCodeChild }, content), + }); + content.dispatchEvent(evt); + }); + await promiseExpectedKeyEvents; + + expectedKeyEventsCount += 3; + is( + keyEventsCount, + expectedKeyEventsCount, + "correct number of key events occurred" + ); + + info("Send trusted key events"); + + state = new Promise(resolve => { + let removeFun = BrowserTestUtils.addContentEventListener( + browser, + "fullscreenchange", + async () => { + removeFun(); + resolve( + await SpecialPowers.spawn(browser, [], () => { + return !!content.document.fullscreenElement; + }) + ); + } + ); + }); + + promiseExpectedKeyEvents = suppressed + ? Promise.resolve() + : receiveExpectedKeyEvents(browser, keyCodeValue, true); + await SpecialPowers.spawn(browser, [], () => {}); + + EventUtils.synthesizeKey("KEY_" + key); + await promiseExpectedKeyEvents; + + ok(!(await state), "The content should have exited fullscreen"); + ok( + !document.fullscreenElement, + "The chrome should also have exited fullscreen" + ); + + is( + fullScreenEventsCount, + ++expectedFullScreenEventsCount, + "correct number of fullscreen events occurred" + ); + if (!suppressed) { + expectedKeyEventsCount += keyCode == "VK_F11" ? 1 : 3; + } + is( + keyEventsCount, + expectedKeyEventsCount, + "correct number of key events occurred" + ); + } + + removeFullScreenListener(); + removeKeyDownListener(); + removeKeyPressListener(); + removeKeyUpListener(); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-bug-1798219.js b/dom/base/test/fullscreen/browser_fullscreen-bug-1798219.js new file mode 100644 index 0000000000..2aef23b042 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-bug-1798219.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Import helpers +/* import-globals-from fullscreen_helpers.js */ +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error, https://bugzilla.mozilla.org/show_bug.cgi?id=1742890. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function waitAndCheckFullscreenState(aWindow) { + // Wait fullscreen exit event if browser is still in fullscreen mode. + if ( + aWindow.fullScreen || + aWindow.document.documentElement.hasAttribute("inFullscreen") + ) { + info("The widget is still in fullscreen, wait again"); + await waitWidgetFullscreenEvent(aWindow, false, true); + } + if (aWindow.document.documentElement.hasAttribute("inDOMFullscreen")) { + info("The chrome document is still in fullscreen, wait again"); + await waitForFullScreenObserver(aWindow, false, true); + } + + // Ensure the browser exits fullscreen state. + ok(!aWindow.fullScreen, "The widget should not be in fullscreen"); + ok( + !aWindow.document.documentElement.hasAttribute("inFullscreen"), + "The chrome window should not be in fullscreen" + ); + ok( + !aWindow.document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); +} + +add_task(async () => { + const URL = + "http://mochi.test:8888/browser/dom/base/test/fullscreen/file_fullscreen-bug-1798219.html"; + // We need this dummy tab which load the same URL as test tab to keep the + // original content process alive after test page navigates away. + let dummyTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: URL, + }, + async function (browser) { + await SpecialPowers.spawn(browser, [], function () { + content.document.querySelector("button").click(); + }); + + // Test requests fullscreen and performs navigation simultaneously, + // the fullscreen request might be rejected directly if navigation happens + // first, so there might be no reliable state that we can wait. So give + // some time for possible fullscreen transition instead and ensure window + // should end up exiting fullscreen. + await new Promise(aResolve => { + SimpleTest.executeSoon(() => { + SimpleTest.executeSoon(aResolve); + }); + }); + await waitAndCheckFullscreenState(window); + } + ); + + let dummyTabClosed = BrowserTestUtils.waitForTabClosing(dummyTab); + BrowserTestUtils.removeTab(dummyTab); + await dummyTabClosed; +}); + +add_task(async () => { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://mochi.test:8888/browser/dom/base/test/fullscreen/file_fullscreen-bug-1798219-2.html", + }, + async function (browser) { + // Open a new window to run the tests, the original window will keep the + // original content process alive after the test window navigates away. + let promiseWin = BrowserTestUtils.waitForNewWindow(); + await SpecialPowers.spawn(browser, [], function () { + content.document.querySelector("button").click(); + }); + let newWindow = await promiseWin; + + await SpecialPowers.spawn( + newWindow.gBrowser.selectedTab.linkedBrowser, + [], + function () { + content.document.querySelector("button").click(); + } + ); + + // Test requests fullscreen and performs navigation simultaneously, + // the fullscreen request might be rejected directly if navigation happens + // first, so there might be no reliable state that we can wait. So give + // some time for possible fullscreen transition instead and ensure window + // should end up exiting fullscreen. + await new Promise(aResolve => { + SimpleTest.executeSoon(() => { + SimpleTest.executeSoon(aResolve); + }); + }); + await waitAndCheckFullscreenState(newWindow); + + newWindow.close(); + } + ); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-contextmenu-esc.js b/dom/base/test/fullscreen/browser_fullscreen-contextmenu-esc.js new file mode 100644 index 0000000000..e89409a90f --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-contextmenu-esc.js @@ -0,0 +1,128 @@ +"use strict"; + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +function captureUnexpectedFullscreenChange() { + ok(false, "Caught an unexpected fullscreen change"); +} + +const kPage = + "https://example.org/browser/dom/base/test/fullscreen/dummy_page.html"; + +function waitForDocActivated(aBrowser) { + return SpecialPowers.spawn(aBrowser, [], () => { + return ContentTaskUtils.waitForCondition( + () => content.browsingContext.isActive && content.document.hasFocus() + ); + }); +} + +add_task(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ); + + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: kPage, + waitForStateStop: true, + }); + let browser = tab.linkedBrowser; + + // As requestFullscreen checks the active state of the docshell, + // wait for the document to be activated, just to be sure that + // the fullscreen request won't be denied. + await SpecialPowers.spawn(browser, [], () => { + return ContentTaskUtils.waitForCondition( + () => content.browsingContext.isActive && content.document.hasFocus() + ); + }); + + let contextMenu = document.getElementById("contentAreaContextMenu"); + ok(contextMenu, "Got context menu"); + + let state; + info("Enter DOM fullscreen"); + let fullScreenChangedPromise = BrowserTestUtils.waitForContentEvent( + browser, + "fullscreenchange" + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.requestFullscreen(); + }); + + await fullScreenChangedPromise; + state = await SpecialPowers.spawn(browser, [], () => { + return !!content.document.fullscreenElement; + }); + ok(state, "The content should have entered fullscreen"); + ok(document.fullscreenElement, "The chrome should also be in fullscreen"); + + let removeContentEventListener = BrowserTestUtils.addContentEventListener( + browser, + "fullscreenchange", + captureUnexpectedFullscreenChange + ); + + info("Open context menu"); + is(contextMenu.state, "closed", "Should not have opened context menu"); + + let popupShownPromise = promiseWaitForEvent(window, "popupshown"); + + EventUtils.synthesizeMouse( + browser, + screen.width / 2, + screen.height / 2, + { type: "contextmenu", button: 2 }, + window + ); + await popupShownPromise; + is(contextMenu.state, "open", "Should have opened context menu"); + + let popupHidePromise = promiseWaitForEvent(window, "popuphidden"); + + if ( + !AppConstants.platform == "macosx" || + !Services.prefs.getBoolPref("widget.macos.native-context-menus", false) + ) { + info("Send the first escape"); + EventUtils.synthesizeKey("KEY_Escape"); + } else { + // We cannot synthesize key events at native macOS menus. + // We also do not see key events that are processed by native macOS menus, + // so we cannot accidentally exit fullscreen when the user closes a native + // menu with Escape. + // Close the menu normally. + info("Close the context menu"); + contextMenu.hidePopup(); + } + await popupHidePromise; + is(contextMenu.state, "closed", "Should have closed context menu"); + + // Wait a small time to confirm that the first ESC key + // does not exit fullscreen. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 1000)); + state = await SpecialPowers.spawn(browser, [], () => { + return !!content.document.fullscreenElement; + }); + ok(state, "The content should still be in fullscreen"); + ok(document.fullscreenElement, "The chrome should still be in fullscreen"); + + removeContentEventListener(); + info("Send the second escape"); + let fullscreenExitPromise = BrowserTestUtils.waitForContentEvent( + browser, + "fullscreenchange" + ); + EventUtils.synthesizeKey("KEY_Escape"); + await fullscreenExitPromise; + ok(!document.fullscreenElement, "The chrome should have exited fullscreen"); + + gBrowser.removeTab(tab); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-document-mutation-navigation.js b/dom/base/test/fullscreen/browser_fullscreen-document-mutation-navigation.js new file mode 100644 index 0000000000..f6b5715f59 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-document-mutation-navigation.js @@ -0,0 +1,141 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function startTests(testFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // This should exit fullscreen + promiseFsState = waitForFullscreenState(document, false, true); + await testFun(browser); + await promiseFsState; + + // This test triggers a fullscreen request during the fullscreen exit + // process, so it could be possible that the widget or the chrome + // document goes into fullscreen mode again, but they should end up + // leaving fullscreen mode again. + if ( + window.fullScreen || + document.documentElement.hasAttribute("inFullscreen") + ) { + info("widget is still in fullscreen, wait again"); + await waitWidgetFullscreenEvent(window, false, true); + } + if (document.documentElement.hasAttribute("inDOMFullscreen")) { + info("chrome document is still in fullscreen, wait again"); + await waitForFullScreenObserver(document, false, true); + } + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The widget should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inFullscreen"), + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +function MutateAndNavigateFromRemoteDocument( + aBrowsingContext, + aElementId, + aURL +) { + return SpecialPowers.spawn( + aBrowsingContext, + [aElementId, aURL], + async function (id, url) { + let element = content.document.getElementById(id); + element.requestFullscreen(); + content.document.body.appendChild(element); + content.location.href = url; + } + ); +} + +startTests(async browser => { + // toplevel + await MutateAndNavigateFromRemoteDocument( + browser.browsingContext, + "div", + "about:blank" + ); +}, "document_mutation_navigation_toplevel"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + ]); + // middle iframe + await MutateAndNavigateFromRemoteDocument( + browser.browsingContext.children[0], + "div", + "about:blank" + ); + await promiseRemoteFsState; +}, "document_mutation_navigation_middle_frame"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + ]); + // innermost iframe + await MutateAndNavigateFromRemoteDocument( + browser.browsingContext.children[0].children[0], + "div", + "about:blank" + ); + await promiseRemoteFsState; +}, "document_mutation_navigation_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-document-mutation-race.js b/dom/base/test/fullscreen/browser_fullscreen-document-mutation-race.js new file mode 100644 index 0000000000..75ca199aaa --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-document-mutation-race.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function startTests(setupFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = Promise.all([ + setupFun(browser), + waitForFullscreenState(document, false, true), + ]); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +function RemoveElementFromRemoteDocument(aBrowsingContext, aElementId) { + return SpecialPowers.spawn( + aBrowsingContext, + [aElementId], + async function (id) { + content.document.addEventListener( + "fullscreenchange", + function () { + content.document.getElementById(id).remove(); + }, + { once: true } + ); + } + ); +} + +startTests(async browser => { + // toplevel + let promise = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + ]); + await RemoveElementFromRemoteDocument(browser.browsingContext, "div"); + return promise; +}, "document_mutation_toplevel"); + +startTests(async browser => { + // middle iframe + let promise = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + ]); + await RemoveElementFromRemoteDocument( + browser.browsingContext.children[0], + "div" + ); + return promise; +}, "document_mutation_middle_frame"); + +startTests(async browser => { + // innermost iframe + let promise = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + [browser.browsingContext.children[0].children[0], "inner"], + ]); + await RemoveElementFromRemoteDocument( + browser.browsingContext.children[0].children[0], + "div" + ); + return promise; +}, "document_mutation_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-document-mutation.js b/dom/base/test/fullscreen/browser_fullscreen-document-mutation.js new file mode 100644 index 0000000000..7cecdabb95 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-document-mutation.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function startTests(testFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // This should exit fullscreen + promiseFsState = waitForFullscreenState(document, false); + await testFun(browser); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +function RemoveElementFromRemoteDocument(aBrowsingContext, aElementId) { + return SpecialPowers.spawn( + aBrowsingContext, + [aElementId], + async function (id) { + content.document.getElementById(id).remove(); + } + ); +} + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + ]); + // toplevel + await RemoveElementFromRemoteDocument(browser.browsingContext, "div"); + await promiseRemoteFsState; +}, "document_mutation_toplevel"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + ]); + // middle iframe + await RemoveElementFromRemoteDocument( + browser.browsingContext.children[0], + "div" + ); + await promiseRemoteFsState; +}, "document_mutation_middle_frame"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + [browser.browsingContext.children[0].children[0], "inner"], + ]); + // innermost iframe + await RemoveElementFromRemoteDocument( + browser.browsingContext.children[0].children[0], + "div" + ); + await promiseRemoteFsState; +}, "document_mutation_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-navigation-history-race.js b/dom/base/test/fullscreen/browser_fullscreen-navigation-history-race.js new file mode 100644 index 0000000000..2ea2b9ee40 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-navigation-history-race.js @@ -0,0 +1,128 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error, bug 1742890. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +function preventBFCache(aBrowsingContext, aPrevent) { + return SpecialPowers.spawn(aBrowsingContext, [aPrevent], prevent => { + if (prevent) { + // Using a dummy onunload listener to disable the bfcache. + content.window.addEventListener("unload", () => {}); + } + content.window.addEventListener( + "pagehide", + e => { + // XXX checking persisted property causes intermittent failures, so we + // dump the value instead, bug 1822263. + // is(e.persisted, !prevent, `Check BFCache state`); + info(`Check BFCache state: e.persisted is ${e.persisted}`); + }, + { once: true } + ); + }); +} + +[true, false].forEach(crossOrigin => { + [true, false].forEach(initialPagePreventsBFCache => { + [true, false].forEach(fullscreenPagePreventsBFCache => { + add_task(async function navigation_history() { + info( + `crossOrigin: ${crossOrigin}, initialPagePreventsBFCache: ${initialPagePreventsBFCache}, fullscreenPagePreventsBFCache: ${fullscreenPagePreventsBFCache}` + ); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://mochi.test:8888/browser/dom/base/test/fullscreen/dummy_page.html", + }, + async function (browser) { + // Maybe prevent BFCache on initial page. + await preventBFCache( + browser.browsingContext, + initialPagePreventsBFCache + ); + + // Navigate to fullscreen page. + const url = crossOrigin + ? "https://example.org/browser/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html" + : "http://mochi.test:8888/browser/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html"; + const loaded = BrowserTestUtils.browserLoaded(browser, false, url); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + // Maybe prevent BFCache on fullscreen test page. + await preventBFCache( + browser.browsingContext, + fullscreenPagePreventsBFCache + ); + + // Trigger click event to enter fullscreen. + await SpecialPowers.spawn(browser.browsingContext, [], () => { + let target = content.document.getElementById("div"); + target.addEventListener( + "mousedown", + function (e) { + content.window.history.back(); + }, + { once: true } + ); + EventUtils.synthesizeMouseAtCenter(target, {}, content.window); + }); + + // Give some time for fullscreen transition. + await new Promise(aResolve => { + SimpleTest.executeSoon(() => { + SimpleTest.executeSoon(aResolve); + }); + }); + + // Wait fullscreen exit event if browser is still in fullscreen mode. + if ( + window.fullScreen || + document.documentElement.hasAttribute("inFullscreen") + ) { + info("The widget is still in fullscreen, wait again"); + await waitWidgetFullscreenEvent(window, false, true); + } + if (document.documentElement.hasAttribute("inDOMFullscreen")) { + info("The chrome document is still in fullscreen, wait again"); + await waitForFullScreenObserver(window, false, true); + } + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The widget should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inFullscreen"), + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); + }); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-navigation-history.js b/dom/base/test/fullscreen/browser_fullscreen-navigation-history.js new file mode 100644 index 0000000000..c4feb7f641 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-navigation-history.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error, bug 1742890. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +function preventBFCache(aBrowsingContext, aPrevent) { + return SpecialPowers.spawn(aBrowsingContext, [aPrevent], prevent => { + if (prevent) { + // Using a dummy onunload listener to disable the bfcache. + content.window.addEventListener("unload", () => {}); + } + content.window.addEventListener( + "pagehide", + e => { + // XXX checking persisted property causes intermittent failures, so we + // dump the value instead, bug 1822263. + // is(e.persisted, !prevent, `Check BFCache state`); + info(`Check BFCache state: e.persisted is ${e.persisted}`); + }, + { once: true } + ); + }); +} + +[true, false].forEach(crossOrigin => { + [true, false].forEach(initialPagePreventsBFCache => { + [true, false].forEach(fullscreenPagePreventsBFCache => { + add_task(async function navigation_history() { + info( + `crossOrigin: ${crossOrigin}, initialPagePreventsBFCache: ${initialPagePreventsBFCache}, fullscreenPagePreventsBFCache: ${fullscreenPagePreventsBFCache}` + ); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://mochi.test:8888/browser/dom/base/test/fullscreen/dummy_page.html", + }, + async function (browser) { + // Maybe prevent BFCache on initial page. + await preventBFCache( + browser.browsingContext, + initialPagePreventsBFCache + ); + + // Navigate to fullscreen page. + const url = crossOrigin + ? "https://example.org/browser/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html" + : "http://mochi.test:8888/browser/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html"; + const loaded = BrowserTestUtils.browserLoaded(browser, false, url); + BrowserTestUtils.startLoadingURIString(browser, url); + await loaded; + + // Maybe prevent BFCache on fullscreen test page. + await preventBFCache( + browser.browsingContext, + fullscreenPagePreventsBFCache + ); + + // Trigger click event to enter fullscreen. + let promiseFsState = waitForFullscreenState(document, true); + SpecialPowers.spawn(browser.browsingContext, [], () => { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + }); + await promiseFsState; + + // Navigate back to the previous page should exit fullscreen. + promiseFsState = waitForFullscreenState(document, false); + await SpecialPowers.spawn(browser.browsingContext, [], () => { + content.window.history.back(); + }); + await promiseFsState; + } + ); + }); + }); + }); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-navigation-race.js b/dom/base/test/fullscreen/browser_fullscreen-navigation-race.js new file mode 100644 index 0000000000..f9d1543a1a --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-navigation-race.js @@ -0,0 +1,162 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +add_task(async function navigation() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `data:text/html, + + `, + }, + async function (browser) { + BrowserTestUtils.synthesizeMouseAtCenter("#button", {}, browser); + + // Give some time for fullscreen transition. + await new Promise(aResolve => { + SimpleTest.executeSoon(() => { + SimpleTest.executeSoon(aResolve); + }); + }); + + // Wait fullscreen exit event if browser is still in fullscreen mode. + if ( + window.fullScreen || + document.documentElement.hasAttribute("inFullscreen") + ) { + info("The widget is still in fullscreen, wait again"); + await waitWidgetFullscreenEvent(window, false, true); + } + if (document.documentElement.hasAttribute("inDOMFullscreen")) { + info("The chrome document is still in fullscreen, wait again"); + await waitForFullScreenObserver(window, false, true); + } + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The widget should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inFullscreen"), + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); +}); + +async function startTests(setupFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = Promise.all([ + setupFun(browser), + waitForFullscreenState(document, false, true), + ]); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +function NavigateRemoteDocument(aBrowsingContext, aURL) { + return SpecialPowers.spawn(aBrowsingContext, [aURL], async function (url) { + content.document.addEventListener( + "fullscreenchange", + function () { + content.location.href = url; + }, + { once: true } + ); + }); +} + +startTests(async browser => { + // toplevel + await NavigateRemoteDocument(browser.browsingContext, "about:blank"); +}, "navigation_toplevel"); + +startTests(async browser => { + // middle iframe + let promise = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + ]); + await NavigateRemoteDocument( + browser.browsingContext.children[0], + "about:blank" + ); + return promise; +}, "navigation_middle_frame"); + +startTests(async browser => { + // innermost iframe + let promise = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + ]); + await NavigateRemoteDocument( + browser.browsingContext.children[0].children[0], + "about:blank" + ); + return promise; +}, "navigation_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-navigation.js b/dom/base/test/fullscreen/browser_fullscreen-navigation.js new file mode 100644 index 0000000000..02387eb437 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-navigation.js @@ -0,0 +1,142 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +add_task(async function navigation() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `data:text/html, + + `, + }, + async function (browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event + BrowserTestUtils.synthesizeMouseAtCenter("#button", {}, browser); + await promiseFsState; + + promiseFsState = waitForFullscreenState(document, false); + await SpecialPowers.spawn(browser, [], async function () { + content.location.href = "about:blank"; + }); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The chrome window should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); +}); + +async function startTests(testFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // This should exit fullscreen + promiseFsState = waitForFullscreenState(document, false); + await testFun(browser); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +function NavigateRemoteDocument(aBrowsingContext, aURL) { + return SpecialPowers.spawn(aBrowsingContext, [aURL], async function (url) { + content.location.href = url; + }); +} + +startTests(async browser => { + // toplevel + await NavigateRemoteDocument(browser.browsingContext, "about:blank"); +}, "navigation_toplevel"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + ]); + // middle iframe + await NavigateRemoteDocument( + browser.browsingContext.children[0], + "about:blank" + ); + await promiseRemoteFsState; +}, "navigation_middle_frame"); + +startTests(async browser => { + let promiseRemoteFsState = waitRemoteFullscreenExitEvents([ + // browsingContext, name + [browser.browsingContext, "toplevel"], + [browser.browsingContext.children[0], "middle"], + ]); + // innermost iframe + await NavigateRemoteDocument( + browser.browsingContext.children[0].children[0], + "about:blank" + ); + await promiseRemoteFsState; +}, "navigation_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-newtab.js b/dom/base/test/fullscreen/browser_fullscreen-newtab.js new file mode 100644 index 0000000000..af714b1248 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-newtab.js @@ -0,0 +1,91 @@ +"use strict"; + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +const kPage = + "https://example.org/browser/" + + "dom/base/test/fullscreen/file_fullscreen-newtab.html"; + +function getSizeMode() { + return document.documentElement.getAttribute("sizemode"); +} + +async function runTest() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: kPage, + }, + async function (browser) { + let promiseFsEvents = SpecialPowers.spawn(browser, [], function () { + return new Promise(resolve => { + let countFsChange = 0; + let countFsError = 0; + function checkAndResolve() { + if (countFsChange > 0 && countFsError > 0) { + Assert.ok( + false, + "Got both fullscreenchange and fullscreenerror events" + ); + } else if (countFsChange > 2) { + Assert.ok(false, "Got too many fullscreenchange events"); + } else if (countFsError > 1) { + Assert.ok(false, "Got too many fullscreenerror events"); + } else if (countFsChange == 2 || countFsError == 1) { + resolve(); + } + } + + content.document.addEventListener("fullscreenchange", () => { + ++countFsChange; + checkAndResolve(); + }); + content.document.addEventListener("fullscreenerror", () => { + ++countFsError; + checkAndResolve(); + }); + }); + }); + let promiseNewTab = BrowserTestUtils.waitForNewTab( + gBrowser, + "about:blank" + ); + await BrowserTestUtils.synthesizeMouseAtCenter("#link", {}, browser); + let [newtab] = await Promise.all([promiseNewTab, promiseFsEvents]); + await BrowserTestUtils.removeTab(newtab); + + // Ensure the browser exits fullscreen state in reasonable time. + await Promise.race([ + BrowserTestUtils.waitForCondition(() => getSizeMode() == "normal"), + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + new Promise(resolve => setTimeout(resolve, 2000)), + ]); + + ok(!window.fullScreen, "The chrome window should not be in fullscreen"); + ok( + !document.fullscreen, + "The chrome document should not be in fullscreen" + ); + } + ); +} + +add_task(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ); + await runTest(); +}); + +add_task(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "200 200"], + ["full-screen-api.transition-duration.leave", "200 200"] + ); + await runTest(); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-sizemode.js b/dom/base/test/fullscreen/browser_fullscreen-sizemode.js new file mode 100644 index 0000000000..0aa79e5694 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-sizemode.js @@ -0,0 +1,225 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const isMac = AppConstants.platform == "macosx"; +const isWin = AppConstants.platform == "win"; + +async function waitForSizeMode(aWindow, aSizeMode) { + await BrowserTestUtils.waitForEvent(aWindow, "sizemodechange", false, () => { + return aWindow.windowState === aSizeMode; + }); + const expectedHidden = + aSizeMode == aWindow.STATE_MINIMIZED || aWindow.isFullyOccluded; + if (aWindow.document.hidden != expectedHidden) { + await BrowserTestUtils.waitForEvent(aWindow, "visibilitychange"); + } + is( + aWindow.document.hidden, + expectedHidden, + "Should be inactive if minimized or occluded" + ); +} + +async function checkSizeModeAndFullscreenState( + aWindow, + aSizeMode, + aFullscreen, + aFullscreenEventShouldHaveFired, + aStepFun +) { + let promises = []; + if (aWindow.windowState != aSizeMode) { + promises.push(waitForSizeMode(aWindow, aSizeMode)); + } + if (aFullscreenEventShouldHaveFired) { + promises.push( + BrowserTestUtils.waitForEvent( + aWindow, + aFullscreen ? "willenterfullscreen" : "willexitfullscreen" + ) + ); + promises.push(BrowserTestUtils.waitForEvent(aWindow, "fullscreen")); + } + + // Add listener for unexpected event. + let unexpectedEventListener = aEvent => { + ok(false, `should not receive ${aEvent.type} event`); + }; + if (aFullscreenEventShouldHaveFired) { + aWindow.addEventListener( + aFullscreen ? "willexitfullscreen" : "willenterfullscreen", + unexpectedEventListener + ); + } else { + aWindow.addEventListener("willenterfullscreen", unexpectedEventListener); + aWindow.addEventListener("willexitfullscreen", unexpectedEventListener); + aWindow.addEventListener("fullscreen", unexpectedEventListener); + } + + let eventPromise = Promise.all(promises); + aStepFun(); + await eventPromise; + + // Check SizeMode. + is( + aWindow.windowState, + aSizeMode, + "The new sizemode should have the expected value" + ); + // Check Fullscreen state. + is( + aWindow.fullScreen, + aFullscreen, + `chrome window should ${aFullscreen ? "be" : "not be"} in fullscreen` + ); + is( + aWindow.document.documentElement.hasAttribute("inFullscreen"), + aFullscreen, + `chrome documentElement should ${ + aFullscreen ? "have" : "not have" + } inFullscreen attribute` + ); + + // Remove listener for unexpected event. + if (aFullscreenEventShouldHaveFired) { + aWindow.removeEventListener( + aFullscreen ? "willexitfullscreen" : "willenterfullscreen", + unexpectedEventListener + ); + } else { + aWindow.removeEventListener("willenterfullscreen", unexpectedEventListener); + aWindow.removeEventListener("willexitfullscreen", unexpectedEventListener); + aWindow.removeEventListener("fullscreen", unexpectedEventListener); + } +} + +async function restoreWindowToNormal(aWindow) { + while (aWindow.windowState != aWindow.STATE_NORMAL) { + info(`Try to restore window with state ${aWindow.windowState} to normal`); + let eventPromise = BrowserTestUtils.waitForEvent(aWindow, "sizemodechange"); + aWindow.restore(); + await eventPromise; + info(`Window is now in state ${aWindow.windowState}`); + } +} + +add_task(async function test_fullscreen_restore() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + await restoreWindowToNormal(win); + + info("Enter fullscreen"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_FULLSCREEN, + true, + true, + () => { + win.fullScreen = true; + } + ); + + info("Restore window"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_NORMAL, + false, + true, + () => { + win.restore(); + } + ); + + await BrowserTestUtils.closeWindow(win); +}); + +// This test only enable on Windows because: +// - Test gets intermittent timeout on macOS, see bug 1828848. +// - Restoring a fullscreen window on GTK doesn't return it to the previous +// sizemode, see bug 1828837. +if (isWin) { + add_task(async function test_maximize_fullscreen_restore() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + await restoreWindowToNormal(win); + + info("Maximize window"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_MAXIMIZED, + false, + false, + () => { + win.maximize(); + } + ); + + info("Enter fullscreen"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_FULLSCREEN, + true, + true, + () => { + win.fullScreen = true; + } + ); + + info("Restore window"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_MAXIMIZED, + false, + true, + () => { + win.restore(); + } + ); + + await BrowserTestUtils.closeWindow(win); + }); +} + +// Restoring a minimized window on macOS doesn't return it to the previous +// sizemode, see bug 1828706. +if (!isMac) { + add_task(async function test_fullscreen_minimize_restore() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + await restoreWindowToNormal(win); + + info("Enter fullscreen"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_FULLSCREEN, + true, + true, + () => { + win.fullScreen = true; + } + ); + + info("Minimize window"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_MINIMIZED, + true, + false, + () => { + win.minimize(); + } + ); + + info("Restore window"); + await checkSizeModeAndFullscreenState( + win, + win.STATE_FULLSCREEN, + true, + false, + () => { + win.restore(); + } + ); + + await BrowserTestUtils.closeWindow(win); + }); +} diff --git a/dom/base/test/fullscreen/browser_fullscreen-tab-close-race.js b/dom/base/test/fullscreen/browser_fullscreen-tab-close-race.js new file mode 100644 index 0000000000..10d10a0b0f --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-tab-close-race.js @@ -0,0 +1,105 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function startTests(setupAndCompletionFn, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = waitForFullscreenExit(document); + let promiseSetup = setupAndCompletionFn(browser); + // Trigger click event in inner most iframe + await SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseSetup; + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +async function WaitRemoveDocumentAndCloseTab(aBrowser, aBrowsingContext) { + await SpecialPowers.spawn(aBrowsingContext, [], function () { + return new Promise(resolve => { + content.document.addEventListener( + "fullscreenchange", + e => { + resolve(); + }, + { once: true } + ); + }); + }); + + // This should exit fullscreen + let tab = gBrowser.getTabForBrowser(aBrowser); + BrowserTestUtils.removeTab(tab); +} + +startTests(browser => { + // toplevel + return WaitRemoveDocumentAndCloseTab(browser, browser.browsingContext); +}, "tab_close_toplevel"); + +startTests(browser => { + // middle iframe + return WaitRemoveDocumentAndCloseTab( + browser, + browser.browsingContext.children[0] + ); +}, "tab_close_middle_frame"); + +startTests(browser => { + // innermost iframe + return WaitRemoveDocumentAndCloseTab( + browser, + browser.browsingContext.children[0].children[0] + ); +}, "tab_close_inner_frame"); diff --git a/dom/base/test/fullscreen/browser_fullscreen-tab-close.js b/dom/base/test/fullscreen/browser_fullscreen-tab-close.js new file mode 100644 index 0000000000..7d1772cd48 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-tab-close.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +TEST_URLS.forEach(url => { + add_task(async () => { + info(`url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function () { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + let promiseFsExit = waitForFullscreenExit(document, false); + // This should exit fullscreen + let tab = gBrowser.getTabForBrowser(browser); + BrowserTestUtils.removeTab(tab); + await promiseFsExit; + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The chrome window should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen-window-open-race.js b/dom/base/test/fullscreen/browser_fullscreen-window-open-race.js new file mode 100644 index 0000000000..4cf8a3d8c7 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen-window-open-race.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error, bug 1742890. +SimpleTest.ignoreAllUncaughtExceptions(true); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +add_task(async () => { + const url = + "http://mochi.test:8888/browser/dom/base/test/fullscreen/dummy_page.html"; + const name = "foo"; + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function (browser) { + info("open new window"); + SpecialPowers.spawn(browser, [url, name], function (u, n) { + content.document.notifyUserGestureActivation(); + content.window.open(u, n, "width=100,height=100"); + }); + let newWin = await BrowserTestUtils.waitForNewWindow({ url }); + await SimpleTest.promiseFocus(newWin); + + info("re-focusing main window"); + await SimpleTest.promiseFocus(window); + + info("open an existing window and request fullscreen"); + await SpecialPowers.spawn(browser, [url, name], function (u, n) { + content.document.notifyUserGestureActivation(); + content.window.open(u, n); + content.document.body.requestFullscreen(); + }); + + // We call window.open() first than requestFullscreen() in a row on + // content page, but given that focus sync-up takes several IPC exchanges, + // so parent process ends up processing the requests in a reverse order, + // which should reject the fullscreen request and leave fullscreen. + await waitWidgetFullscreenEvent(window, false, true); + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The chrome window should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + + await BrowserTestUtils.closeWindow(newWin); + } + ); +}); diff --git a/dom/base/test/fullscreen/browser_fullscreen_exit_on_external_protocol.js b/dom/base/test/fullscreen/browser_fullscreen_exit_on_external_protocol.js new file mode 100644 index 0000000000..6f525da541 --- /dev/null +++ b/dom/base/test/fullscreen/browser_fullscreen_exit_on_external_protocol.js @@ -0,0 +1,215 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +SimpleTest.requestCompleteLog(); + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/base/test/fullscreen/fullscreen_helpers.js", + this +); + +add_setup(async function () { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +const { HandlerServiceTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/HandlerServiceTestUtils.sys.mjs" +); + +const gHandlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService( + Ci.nsIHandlerService +); + +const CONTENT = `data:text/html, + + + + + + +`; + +// This test tends to trigger a race in the fullscreen time telemetry, +// where the fullscreen enter and fullscreen exit events (which use the +// same histogram ID) overlap. That causes TelemetryStopwatch to log an +// error. +SimpleTest.ignoreAllUncaughtExceptions(true); + +function setupMailHandler() { + let mailHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto"); + let gOldMailHandlers = []; + + // Remove extant web handlers because they have icons that + // we fetch from the web, which isn't allowed in tests. + let handlers = mailHandlerInfo.possibleApplicationHandlers; + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp); + gOldMailHandlers.push(handler); + // If we get here, this is a web handler app. Remove it: + handlers.removeElementAt(i); + } catch (ex) {} + } + + let previousHandling = mailHandlerInfo.alwaysAskBeforeHandling; + mailHandlerInfo.alwaysAskBeforeHandling = true; + + // Create a dummy web mail handler so we always know the mailto: protocol. + // Without this, the test fails on VMs without a default mailto: handler, + // because no dialog is ever shown, as we ignore subframe navigations to + // protocols that cannot be handled. + let dummy = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + dummy.name = "Handler 1"; + dummy.uriTemplate = "https://example.com/first/%s"; + mailHandlerInfo.possibleApplicationHandlers.appendElement(dummy); + + gHandlerSvc.store(mailHandlerInfo); + registerCleanupFunction(() => { + // Re-add the original protocol handlers: + let mailHandlers = mailHandlerInfo.possibleApplicationHandlers; + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + // See if this is a web handler. If it is, it'll throw, otherwise, + // we will remove it. + mailHandlers.queryElementAt(i, Ci.nsIWebHandlerApp); + mailHandlers.removeElementAt(i); + } catch (ex) {} + } + for (let h of gOldMailHandlers) { + mailHandlers.appendElement(h); + } + mailHandlerInfo.alwaysAskBeforeHandling = previousHandling; + gHandlerSvc.store(mailHandlerInfo); + }); +} + +add_task(setupMailHandler); + +// Fullscreen is canceled during fullscreen transition +add_task(async function OpenExternalProtocolOnPendingLaterFullscreen() { + for (const useClick of [true, false]) { + await BrowserTestUtils.withNewTab(CONTENT, async browser => { + const leavelFullscreen = waitForFullscreenState(document, false, true); + await SpecialPowers.spawn( + browser, + [useClick], + async function (shouldClick) { + const button = content.document.querySelector("button"); + + const clickDone = new Promise(r => { + button.addEventListener( + "click", + function () { + content.document.documentElement.requestFullscreen(); + // When anchor.click() is called, the fullscreen request + // is probably still pending. + content.setTimeout(() => { + if (shouldClick) { + content.document.querySelector("a").click(); + } else { + content.document.location = "mailto:test@example.com"; + } + r(); + }, 0); + }, + { once: true } + ); + }); + button.click(); + await clickDone; + } + ); + + await leavelFullscreen; + ok(true, "Fullscreen should be exited"); + }); + } +}); + +// Fullscreen is canceled immediately. +add_task(async function OpenExternalProtocolOnPendingFullscreen() { + for (const useClick of [true, false]) { + await BrowserTestUtils.withNewTab(CONTENT, async browser => { + await SpecialPowers.spawn( + browser, + [useClick], + async function (shouldClick) { + const button = content.document.querySelector("button"); + + const clickDone = new Promise(r => { + button.addEventListener( + "click", + function () { + content.document.documentElement + .requestFullscreen() + .then(() => { + ok(false, "Don't enter fullscreen"); + }) + .catch(() => { + ok(true, "Cancel entering fullscreen"); + r(); + }); + // When anchor.click() is called, the fullscreen request + // is probably still pending. + if (shouldClick) { + content.document.querySelector("a").click(); + } else { + content.document.location = "mailto:test@example.com"; + } + }, + { once: true } + ); + }); + button.click(); + await clickDone; + } + ); + + ok(true, "Fullscreen should be exited"); + }); + } +}); + +add_task(async function OpenExternalProtocolOnFullscreen() { + for (const useClick of [true, false]) { + await BrowserTestUtils.withNewTab(CONTENT, async browser => { + const leavelFullscreen = waitForFullscreenState(document, false, true); + await SpecialPowers.spawn( + browser, + [useClick], + async function (shouldClick) { + let button = content.document.querySelector("button"); + button.addEventListener("click", function () { + content.document.documentElement.requestFullscreen(); + }); + button.click(); + + await new Promise(r => { + content.document.addEventListener("fullscreenchange", r); + }); + + if (shouldClick) { + content.document.querySelector("a").click(); + } else { + content.document.location = "mailto:test@example.com"; + } + } + ); + + await leavelFullscreen; + ok(true, "Fullscreen should be exited"); + }); + } +}); diff --git a/dom/base/test/fullscreen/chrome.toml b/dom/base/test/fullscreen/chrome.toml new file mode 100644 index 0000000000..0ba7862f50 --- /dev/null +++ b/dom/base/test/fullscreen/chrome.toml @@ -0,0 +1,11 @@ +[DEFAULT] +tags = "fullscreen" + +["test_MozDomFullscreen_event.xhtml"] +support-files = [ + "fullscreen.xhtml", + "MozDomFullscreen_chrome.xhtml", +] + +["test_fullscreen.xhtml"] +support-files = "file_MozDomFullscreen.html" diff --git a/dom/base/test/fullscreen/dummy_page.html b/dom/base/test/fullscreen/dummy_page.html new file mode 100644 index 0000000000..fd238954c6 --- /dev/null +++ b/dom/base/test/fullscreen/dummy_page.html @@ -0,0 +1,10 @@ + + + +Dummy test page + + + +

              Dummy test page

              + + diff --git a/dom/base/test/fullscreen/file_MozDomFullscreen.html b/dom/base/test/fullscreen/file_MozDomFullscreen.html new file mode 100644 index 0000000000..f954892706 --- /dev/null +++ b/dom/base/test/fullscreen/file_MozDomFullscreen.html @@ -0,0 +1,8 @@ + + + + +

              Outer doc

              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-api-keys.html b/dom/base/test/fullscreen/file_fullscreen-api-keys.html new file mode 100644 index 0000000000..f526aa55ba --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-api-keys.html @@ -0,0 +1,41 @@ + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-api-race.html b/dom/base/test/fullscreen/file_fullscreen-api-race.html new file mode 100644 index 0000000000..8310bc0a60 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-api-race.html @@ -0,0 +1,8 @@ + + + + Helper file for test_fullscreen-api-race.html + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-api.html b/dom/base/test/fullscreen/file_fullscreen-api.html new file mode 100644 index 0000000000..645e6ece46 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-api.html @@ -0,0 +1,340 @@ + + + + + Test for Bug 545812 + + + + + + +
              + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-async.html b/dom/base/test/fullscreen/file_fullscreen-async.html new file mode 100644 index 0000000000..e9b4147124 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-async.html @@ -0,0 +1,50 @@ + +Test for Bug 1129227 + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-backdrop.html b/dom/base/test/fullscreen/file_fullscreen-backdrop.html new file mode 100644 index 0000000000..27be77a6d1 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-backdrop.html @@ -0,0 +1,107 @@ + + + + + Test for Bug 1064843 + + + + + + + + +
              +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-bug-1798219-2.html b/dom/base/test/fullscreen/file_fullscreen-bug-1798219-2.html new file mode 100644 index 0000000000..61db80c228 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-bug-1798219-2.html @@ -0,0 +1,22 @@ + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-bug-1798219.html b/dom/base/test/fullscreen/file_fullscreen-bug-1798219.html new file mode 100644 index 0000000000..7490f12936 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-bug-1798219.html @@ -0,0 +1,14 @@ + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-denied-inner.html b/dom/base/test/fullscreen/file_fullscreen-denied-inner.html new file mode 100644 index 0000000000..6b5916b2e2 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-denied-inner.html @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-denied.html b/dom/base/test/fullscreen/file_fullscreen-denied.html new file mode 100644 index 0000000000..db9a69e71a --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-denied.html @@ -0,0 +1,171 @@ + + + + + Test for Bug 545812 + + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-esc-exit-inner.html b/dom/base/test/fullscreen/file_fullscreen-esc-exit-inner.html new file mode 100644 index 0000000000..d7d8a90aaf --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-esc-exit-inner.html @@ -0,0 +1,58 @@ + + + + + Test for Bug 700764 + + + + + + + +

              Inner frame

              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-esc-exit.html b/dom/base/test/fullscreen/file_fullscreen-esc-exit.html new file mode 100644 index 0000000000..f65f930b3f --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-esc-exit.html @@ -0,0 +1,63 @@ + + + + + Test for Bug 700764 + + + + + + + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-event-order.html b/dom/base/test/fullscreen/file_fullscreen-event-order.html new file mode 100644 index 0000000000..72fb2c9b47 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-event-order.html @@ -0,0 +1,50 @@ + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-featurePolicy-inner.html b/dom/base/test/fullscreen/file_fullscreen-featurePolicy-inner.html new file mode 100644 index 0000000000..844684b054 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-featurePolicy-inner.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-featurePolicy.html b/dom/base/test/fullscreen/file_fullscreen-featurePolicy.html new file mode 100644 index 0000000000..c8b943c612 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-featurePolicy.html @@ -0,0 +1,90 @@ + + + + Test for FeaturePolicy + fullscreen + + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-focus-inner.html b/dom/base/test/fullscreen/file_fullscreen-focus-inner.html new file mode 100644 index 0000000000..73d39a9d83 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-focus-inner.html @@ -0,0 +1,24 @@ + + + + Focus test - child window + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-focus.html b/dom/base/test/fullscreen/file_fullscreen-focus.html new file mode 100644 index 0000000000..be91025f45 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-focus.html @@ -0,0 +1,67 @@ + + + + + Test fullscreen request is blocked when window is not focused + + + + + + + + +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-hidden.html b/dom/base/test/fullscreen/file_fullscreen-hidden.html new file mode 100644 index 0000000000..bd8c8189c9 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-hidden.html @@ -0,0 +1,56 @@ + + + + + Test for Bug 697636 + + + + + + + +Mozilla Bug 697636 +

              + +
              +
              +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html b/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html new file mode 100644 index 0000000000..4a614fdecf --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-iframe-inner.html @@ -0,0 +1,5 @@ + + +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-iframe-middle.html b/dom/base/test/fullscreen/file_fullscreen-iframe-middle.html new file mode 100644 index 0000000000..b60dea43bf --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-iframe-middle.html @@ -0,0 +1,5 @@ +
              + +

              diff --git a/dom/base/test/fullscreen/file_fullscreen-iframe-top.html b/dom/base/test/fullscreen/file_fullscreen-iframe-top.html new file mode 100644 index 0000000000..dddf4930c2 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-iframe-top.html @@ -0,0 +1,5 @@ +
              + +

              diff --git a/dom/base/test/fullscreen/file_fullscreen-lenient-setters.html b/dom/base/test/fullscreen/file_fullscreen-lenient-setters.html new file mode 100644 index 0000000000..02491c177e --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-lenient-setters.html @@ -0,0 +1,61 @@ + + + + + Test for Bug 1268798 + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-multiple-inner.html b/dom/base/test/fullscreen/file_fullscreen-multiple-inner.html new file mode 100644 index 0000000000..cb5ca9b28e --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-multiple-inner.html @@ -0,0 +1,25 @@ + + + + Test for Bug 724554 + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-multiple.html b/dom/base/test/fullscreen/file_fullscreen-multiple.html new file mode 100644 index 0000000000..f9e35b5e78 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-multiple.html @@ -0,0 +1,67 @@ + + + + + Test for Bug 724554 + + + + + + + + +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-navigation.html b/dom/base/test/fullscreen/file_fullscreen-navigation.html new file mode 100644 index 0000000000..9b68fedf9a --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-navigation.html @@ -0,0 +1,52 @@ + + + + + Test for Bug 685402 + + + + + + + +Mozilla Bug 685402 +

              + +
              +
              +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-nested.html b/dom/base/test/fullscreen/file_fullscreen-nested.html new file mode 100644 index 0000000000..1629d8386c --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-nested.html @@ -0,0 +1,130 @@ + + + + Test for Bug 1187801 + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-newtab.html b/dom/base/test/fullscreen/file_fullscreen-newtab.html new file mode 100644 index 0000000000..0eaf5dd546 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-newtab.html @@ -0,0 +1,4 @@ + + +Click here diff --git a/dom/base/test/fullscreen/file_fullscreen-prefixed.html b/dom/base/test/fullscreen/file_fullscreen-prefixed.html new file mode 100644 index 0000000000..dfe1965365 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-prefixed.html @@ -0,0 +1,153 @@ + + + + + Test for Bug 743198 + + + + +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-resize.html b/dom/base/test/fullscreen/file_fullscreen-resize.html new file mode 100644 index 0000000000..3050ba0d5d --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-resize.html @@ -0,0 +1,39 @@ + + + + + Test for Bug 1742421 + + + + + +Mozilla Bug 1742421 +

              + +
              +
              +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-rollback.html b/dom/base/test/fullscreen/file_fullscreen-rollback.html new file mode 100644 index 0000000000..b1578b39cd --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-rollback.html @@ -0,0 +1,140 @@ + + + + + Test for Bug 700764 + + + + + + +
              +
              + +
              +
              + +
              + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-scrollbar.html b/dom/base/test/fullscreen/file_fullscreen-scrollbar.html new file mode 100644 index 0000000000..05ab51431a --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-scrollbar.html @@ -0,0 +1,147 @@ + + + + + Test for Bug 1201798 + + + + + + +
              +
              +
              +
              +
              +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-selector.html b/dom/base/test/fullscreen/file_fullscreen-selector.html new file mode 100644 index 0000000000..522f06f6fd --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-selector.html @@ -0,0 +1,187 @@ + + + + Test for Bug 1199522 + + + + + + + + +
              +
              +
              +
              +
              +
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-shadowdom.html b/dom/base/test/fullscreen/file_fullscreen-shadowdom.html new file mode 100644 index 0000000000..348e08ae87 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-shadowdom.html @@ -0,0 +1,52 @@ + + + + + Bug 1430305 + + + + + + + Mozilla Bug 1430305 + +
              + +
              +      
              +    
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-single.html b/dom/base/test/fullscreen/file_fullscreen-single.html new file mode 100644 index 0000000000..2ebc58bdae --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-single.html @@ -0,0 +1,78 @@ + + + + + Simple Fullscreen Enter and Exit Test + + + + + + +

              Fullscreen div

              + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-sub-iframe.html b/dom/base/test/fullscreen/file_fullscreen-sub-iframe.html new file mode 100644 index 0000000000..28b0235c87 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-sub-iframe.html @@ -0,0 +1,53 @@ + +Test for Bug 1609180 + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-svg-element.html b/dom/base/test/fullscreen/file_fullscreen-svg-element.html new file mode 100644 index 0000000000..1dfc78aa1c --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-svg-element.html @@ -0,0 +1,49 @@ + + + + + Bug 735031 + + + + + + + Mozilla Bug 735031 + + + + + +
              +      
              +    
              + + diff --git a/dom/base/test/fullscreen/file_fullscreen-table.html b/dom/base/test/fullscreen/file_fullscreen-table.html new file mode 100644 index 0000000000..39c602334a --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-table.html @@ -0,0 +1,52 @@ + + + + + Test for Bug 1223561 + + + + + + +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-top-layer.html b/dom/base/test/fullscreen/file_fullscreen-top-layer.html new file mode 100644 index 0000000000..9e95182b02 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-top-layer.html @@ -0,0 +1,160 @@ + + + + + Test for Bug 1126230 + + + + + + + +Mozilla Bug 1126230 +
              +
              +
              +
              + + + + + + + + + diff --git a/dom/base/test/fullscreen/file_fullscreen-utils.js b/dom/base/test/fullscreen/file_fullscreen-utils.js new file mode 100644 index 0000000000..b4779da4de --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-utils.js @@ -0,0 +1,87 @@ +// Keep track of how many fullscreenChange enters we've received, so that +// we can balance them with the number of exits we receive. We reset this +// to 0 when we load a test. +var fullscreenChangeEnters = 0; + +addLoadEvent(function () { + info(`Resetting fullscreen enter count.`); + fullscreenChangeEnters = 0; +}); + +// This can be used to force a certain value for fullscreenChangeEnters +// to handle unusual conditions -- such as exiting multiple levels of +// fullscreen forcibly. +function setFullscreenChangeEnters(enters) { + info(`Setting fullscreen enter count to ${enters}.`); + fullscreenChangeEnters = enters; +} + +// Returns true if the window believes it is in fullscreen. This may be true even +// before an asynchronous fullscreen transition is complete. +function inFullscreenMode(win) { + return win.document.fullscreenElement; +} + +// Adds a listener that will be called once a fullscreen transition +// is complete. When type==='enter', callback is called when we've +// received a fullscreenchange event, and the fullscreen transition is +// complete. When type==='exit', callback is called when we've +// received a fullscreenchange event and the window is out of +// fullscreen. inDoc is the document which the listeners are added on, +// if absent, the listeners are added to the current document. +// the current document. +function addFullscreenChangeContinuation(type, callback, inDoc) { + var doc = inDoc || document; + var topWin = doc.defaultView.top; + function checkCondition() { + if (type == "enter") { + fullscreenChangeEnters++; + return inFullscreenMode(topWin); + } else if (type == "exit") { + fullscreenChangeEnters--; + return fullscreenChangeEnters + ? inFullscreenMode(topWin) + : !inFullscreenMode(topWin); + } + throw new Error("'type' must be either 'enter', or 'exit'."); + } + function onFullscreenChange(event) { + doc.removeEventListener("fullscreenchange", onFullscreenChange); + ok(checkCondition(), `Should ${type} fullscreen.`); + // Delay invocation so other listeners have a chance to respond before + // we continue. + requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0); + } + doc.addEventListener("fullscreenchange", onFullscreenChange); +} + +// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document. +function addFullscreenErrorContinuation(callback, inDoc) { + let doc = inDoc || document; + let listener = function (event) { + doc.removeEventListener("fullscreenerror", listener); + // Delay invocation so other listeners have a chance to respond before + // we continue. + requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0); + }; + doc.addEventListener("fullscreenerror", listener); +} + +// Waits until the window has both the load event and a MozAfterPaint called on +// it, and then invokes the callback +function waitForLoadAndPaint(win, callback) { + win.addEventListener( + "MozAfterPaint", + function () { + // The load event may have fired before the MozAfterPaint, in which case + // listening for it now will hang. Instead we check the readyState to see if + // it already fired, and if so, invoke the callback right away. + if (win.document.readyState == "complete") { + callback(); + } else { + win.addEventListener("load", callback, { once: true }); + } + }, + { once: true } + ); +} diff --git a/dom/base/test/fullscreen/file_fullscreen-with-full-zoom.html b/dom/base/test/fullscreen/file_fullscreen-with-full-zoom.html new file mode 100644 index 0000000000..620bc5acf9 --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen-with-full-zoom.html @@ -0,0 +1,36 @@ + + + + + Test for Bug 1223561 + + + + + + +
              + + + diff --git a/dom/base/test/fullscreen/file_fullscreen_meta_viewport.html b/dom/base/test/fullscreen/file_fullscreen_meta_viewport.html new file mode 100644 index 0000000000..9938fdda6b --- /dev/null +++ b/dom/base/test/fullscreen/file_fullscreen_meta_viewport.html @@ -0,0 +1,12 @@ + + + +
              +
              diff --git a/dom/base/test/fullscreen/fullscreen.xhtml b/dom/base/test/fullscreen/fullscreen.xhtml new file mode 100644 index 0000000000..2cc95642b6 --- /dev/null +++ b/dom/base/test/fullscreen/fullscreen.xhtml @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/dom/base/test/green.png b/dom/base/test/green.png new file mode 100644 index 0000000000..7df25f33bd Binary files /dev/null and b/dom/base/test/green.png differ diff --git a/dom/base/test/gtest/TestContentUtils.cpp b/dom/base/test/gtest/TestContentUtils.cpp new file mode 100644 index 0000000000..2a2d2b4600 --- /dev/null +++ b/dom/base/test/gtest/TestContentUtils.cpp @@ -0,0 +1,221 @@ +/* -*- 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 "jsapi.h" +#include "js/PropertyAndElement.h" // JS_DefineProperty +#include "nsContentUtils.h" +#include "nsNetUtil.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/SimpleGlobalObject.h" + +using namespace mozilla::dom; + +struct IsURIInListMatch { + nsLiteralCString pattern; + bool firstMatch, secondMatch; +}; + +std::ostream& operator<<(std::ostream& aStream, + const nsContentUtils::ParsedRange& aParsedRange) { + if (aParsedRange.Start()) { + aStream << *aParsedRange.Start(); + } + + aStream << "-"; + + if (aParsedRange.End()) { + aStream << *aParsedRange.End(); + } + + return aStream; +} + +TEST(DOM_Base_ContentUtils, IsURIInList) +{ + nsCOMPtr uri, subURI; + nsresult rv = NS_NewURI(getter_AddRefs(uri), + "https://example.com/path/favicon.ico#"_ns); + ASSERT_TRUE(rv == NS_OK); + + rv = NS_NewURI(getter_AddRefs(subURI), + "http://sub.example.com/favicon.ico?"_ns); + ASSERT_TRUE(rv == NS_OK); + + static constexpr IsURIInListMatch patterns[] = { + {"bar.com,*.example.com,example.com,foo.com"_ns, true, true}, + {"bar.com,example.com,*.example.com,foo.com"_ns, true, true}, + {"*.example.com,example.com,foo.com"_ns, true, true}, + {"example.com,*.example.com,foo.com"_ns, true, true}, + {"*.example.com,example.com"_ns, true, true}, + {"example.com,*.example.com"_ns, true, true}, + {"*.example.com/,example.com/"_ns, true, true}, + {"example.com/,*.example.com/"_ns, true, true}, + {"*.example.com/pa,example.com/pa"_ns, false, false}, + {"example.com/pa,*.example.com/pa"_ns, false, false}, + {"*.example.com/pa/,example.com/pa/"_ns, false, false}, + {"example.com/pa/,*.example.com/pa/"_ns, false, false}, + {"*.example.com/path,example.com/path"_ns, false, false}, + {"example.com/path,*.example.com/path"_ns, false, false}, + {"*.example.com/path/,example.com/path/"_ns, true, false}, + {"example.com/path/,*.example.com/path/"_ns, true, false}, + {"*.example.com/favicon.ico"_ns, false, true}, + {"example.com/path/favicon.ico"_ns, true, false}, + {"*.example.com"_ns, false, true}, + {"example.com"_ns, true, false}, + {"foo.com"_ns, false, false}, + {"*.foo.com"_ns, false, false}, + }; + + for (auto& entry : patterns) { + bool result = nsContentUtils::IsURIInList(uri, entry.pattern); + ASSERT_EQ(result, entry.firstMatch) << "Matching " << entry.pattern; + + result = nsContentUtils::IsURIInList(subURI, entry.pattern); + ASSERT_EQ(result, entry.secondMatch) << "Matching " << entry.pattern; + } +} + +TEST(DOM_Base_ContentUtils, + StringifyJSON_EmptyValue_UndefinedIsNullStringLiteral) +{ + JS::Rooted globalObject( + mozilla::dom::RootingCx(), + mozilla::dom::SimpleGlobalObject::Create( + mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail)); + mozilla::dom::AutoJSAPI jsAPI; + ASSERT_TRUE(jsAPI.Init(globalObject)); + JSContext* cx = jsAPI.cx(); + nsAutoString serializedValue; + + ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, JS::UndefinedHandleValue, + serializedValue, + UndefinedIsNullStringLiteral)); + ASSERT_TRUE(serializedValue.EqualsLiteral("null")); +} + +TEST(DOM_Base_ContentUtils, StringifyJSON_Object_UndefinedIsNullStringLiteral) +{ + JS::Rooted globalObject( + mozilla::dom::RootingCx(), + mozilla::dom::SimpleGlobalObject::Create( + mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail)); + mozilla::dom::AutoJSAPI jsAPI; + ASSERT_TRUE(jsAPI.Init(globalObject)); + JSContext* cx = jsAPI.cx(); + nsAutoString serializedValue; + + JS::Rooted jsObj(cx, JS_NewPlainObject(cx)); + JS::Rooted valueStr(cx, JS_NewStringCopyZ(cx, "Hello World!")); + ASSERT_TRUE(JS_DefineProperty(cx, jsObj, "key1", valueStr, JSPROP_ENUMERATE)); + JS::Rooted jsValue(cx, JS::ObjectValue(*jsObj)); + + ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, jsValue, serializedValue, + UndefinedIsNullStringLiteral)); + + ASSERT_TRUE(serializedValue.EqualsLiteral("{\"key1\":\"Hello World!\"}")); +} + +TEST(DOM_Base_ContentUtils, StringifyJSON_EmptyValue_UndefinedIsVoidString) +{ + JS::Rooted globalObject( + mozilla::dom::RootingCx(), + mozilla::dom::SimpleGlobalObject::Create( + mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail)); + mozilla::dom::AutoJSAPI jsAPI; + ASSERT_TRUE(jsAPI.Init(globalObject)); + JSContext* cx = jsAPI.cx(); + nsAutoString serializedValue; + + ASSERT_TRUE(nsContentUtils::StringifyJSON( + cx, JS::UndefinedHandleValue, serializedValue, UndefinedIsVoidString)); + + ASSERT_TRUE(serializedValue.IsVoid()); +} + +TEST(DOM_Base_ContentUtils, StringifyJSON_Object_UndefinedIsVoidString) +{ + JS::Rooted globalObject( + mozilla::dom::RootingCx(), + mozilla::dom::SimpleGlobalObject::Create( + mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail)); + mozilla::dom::AutoJSAPI jsAPI; + ASSERT_TRUE(jsAPI.Init(globalObject)); + JSContext* cx = jsAPI.cx(); + nsAutoString serializedValue; + + JS::Rooted jsObj(cx, JS_NewPlainObject(cx)); + JS::Rooted valueStr(cx, JS_NewStringCopyZ(cx, "Hello World!")); + ASSERT_TRUE(JS_DefineProperty(cx, jsObj, "key1", valueStr, JSPROP_ENUMERATE)); + JS::Rooted jsValue(cx, JS::ObjectValue(*jsObj)); + + ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, jsValue, serializedValue, + UndefinedIsVoidString)); + + ASSERT_TRUE(serializedValue.EqualsLiteral("{\"key1\":\"Hello World!\"}")); +} + +TEST(DOM_Base_ContentUtils, ParseSingleRangeHeader) +{ + // Parsing a simple range should succeed + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes=0-42"_ns, false), + mozilla::Some(nsContentUtils::ParsedRange(mozilla::Some(0), + mozilla::Some(42)))); + + // Range containing a invalid rangeStart should fail + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes= t-200"_ns, true), + mozilla::Nothing()); + + // Range containing whitespace, with allowWhitespace=false should fail. + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes= 2-200"_ns, false), + mozilla::Nothing()); + + // Range containing whitespace, with allowWhitespace=true should succeed + EXPECT_EQ( + nsContentUtils::ParseSingleRangeRequest("bytes \t= 2 - 200"_ns, true), + mozilla::Some( + nsContentUtils::ParsedRange(mozilla::Some(2), mozilla::Some(200)))); + + // Range containing invalid whitespace should fail + EXPECT_EQ( + nsContentUtils::ParseSingleRangeRequest("bytes \r= 2 - 200"_ns, true), + mozilla::Nothing()); + + // Range without a rangeStart should succeed + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes\t=\t-200"_ns, true), + mozilla::Some(nsContentUtils::ParsedRange(mozilla::Nothing(), + mozilla::Some(200)))); + + // Range without a rangeEnd should succeed + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes=55-"_ns, true), + mozilla::Some(nsContentUtils::ParsedRange(mozilla::Some(55), + mozilla::Nothing()))); + + // Range without a rangeStart or rangeEnd should fail + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes\t=\t-"_ns, true), + mozilla::Nothing()); + + // Range with extra characters should fail + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes=0-42 "_ns, true), + mozilla::Nothing()); + + // Range with rangeStart > rangeEnd should fail + EXPECT_EQ(nsContentUtils::ParseSingleRangeRequest("bytes=42-0 "_ns, true), + mozilla::Nothing()); +} + +TEST(DOM_Base_ContentUtils, IsAllowedNonCorsRange) +{ + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=-200"_ns), false); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes= 200-"_ns), false); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=201-200"_ns), false); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=200-201 "_ns), false); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=200-"_ns), true); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=200-201"_ns), true); + EXPECT_EQ(nsContentUtils::IsAllowedNonCorsRange("bytes=-200 "_ns), false); +} diff --git a/dom/base/test/gtest/TestMimeType.cpp b/dom/base/test/gtest/TestMimeType.cpp new file mode 100644 index 0000000000..fecb3f8678 --- /dev/null +++ b/dom/base/test/gtest/TestMimeType.cpp @@ -0,0 +1,1078 @@ +/* -*- 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 "MimeType.h" +#include "nsString.h" + +using mozilla::UniquePtr; + +TEST(MimeType, EmptyString) +{ + const auto in = u""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Empty string"; +} + +TEST(MimeType, JustWhitespace) +{ + const auto in = u" \t\r\n "_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Just whitespace"; +} + +TEST(MimeType, JustBackslash) +{ + const auto in = u"\\"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Just backslash"; +} + +TEST(MimeType, JustForwardslash) +{ + const auto in = u"/"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Just forward slash"; +} + +TEST(MimeType, MissingType1) +{ + const auto in = u"/bogus"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing type #1"; +} + +TEST(MimeType, MissingType2) +{ + const auto in = u" \r\n\t/bogus"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing type #2"; +} + +TEST(MimeType, MissingSubtype1) +{ + const auto in = u"bogus"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing subtype #1"; +} + +TEST(MimeType, MissingSubType2) +{ + const auto in = u"bogus/"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing subtype #2"; +} + +TEST(MimeType, MissingSubType3) +{ + const auto in = u"bogus;"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing subtype #3"; +} + +TEST(MimeType, MissingSubType4) +{ + const auto in = u"bogus; \r\n\t"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Missing subtype #3"; +} + +TEST(MimeType, ExtraForwardSlash) +{ + const auto in = u"bogus/bogus/;"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Extra forward slash"; +} + +TEST(MimeType, WhitespaceInType) +{ + const auto in = u"t\re\nx\tt /html"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Type with whitespace"; +} + +TEST(MimeType, WhitespaceInSubtype) +{ + const auto in = u"text/ h\rt\nm\tl"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Subtype with whitespace"; +} + +TEST(MimeType, NonAlphanumericMediaType1) +{ + const auto in = u""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #1"; +} + +TEST(MimeType, NonAlphanumericMediaType2) +{ + const auto in = u"(/)"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #2"; +} + +TEST(MimeType, NonAlphanumericMediaType3) +{ + const auto in = u"{/}"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #3"; +} + +TEST(MimeType, NonAlphanumericMediaType4) +{ + const auto in = u"\"/\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #4"; +} + +TEST(MimeType, NonAlphanumericMediaType5) +{ + const auto in = u"\0/\0"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #5"; +} + +TEST(MimeType, NonAlphanumericMediaType6) +{ + const auto in = u"text/html(;doesnot=matter"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-alphanumeric media type #6"; +} + +TEST(MimeType, NonLatin1MediaType1) +{ + const auto in = u"ÿ/ÿ"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-latin1 media type #1"; +} + +TEST(MimeType, NonLatin1MediaType2) +{ + const auto in = u"\x0100/\x0100"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_FALSE(parsed) + << "Non-latin1 media type #2"; +} + +TEST(MimeType, MultipleParameters) +{ + const auto in = u"text/html;charset=gbk;no=1;charset_=gbk_;yes=2"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(u"text/html;charset=gbk;no=1;charset_=gbk_;yes=2"_ns)) + << "Multiple parameters"; +} + +TEST(MimeType, DuplicateParameter1) +{ + const auto in = u"text/html;charset=gbk;charset=windows-1255"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(u"text/html;charset=gbk"_ns)) + << "Duplicate parameter #1"; +} + +TEST(MimeType, DuplicateParameter2) +{ + const auto in = u"text/html;charset=();charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(u"text/html;charset=\"()\""_ns)) + << "Duplicate parameter #2"; +} + +TEST(MimeType, CString) +{ + const auto in = "text/html;charset=();charset=GBK"_ns; + UniquePtr parsed = CMimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsCString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals("text/html;charset=\"()\""_ns)) + << "Duplicate parameter #2"; +} + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4819) +#endif +TEST(MimeType, NonAlphanumericParametersAreQuoted) +{ + const auto in = u"text/html;test=\x00FF\\;charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(u"text/html;test=\"\x00FF\\\\\";charset=gbk"_ns)) + << "Non-alphanumeric parameters are quoted"; +} +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace1) +{ + const auto in = u"text/html;charset= g\\\"bk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" g\\\\\\\"bk\"")) + << "Parameter is quoted if has leading whitespace #1"; +} + +TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace2) +{ + const auto in = u"text/html;charset= \"g\\bk\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" \\\"g\\\\bk\\\"\"")) + << "Parameter is quoted if has leading whitespace #2"; +} + +TEST(MimeType, ParameterQuotedIfHasInternalWhitespace) +{ + const auto in = u"text/html;charset=g \\b\"k"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"g \\\\b\\\"k\"")) + << "Parameter is quoted if has internal whitespace"; +} + +TEST(MimeType, ImproperlyQuotedParameter1) +{ + const auto in = u"x/x;test=\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x;test=\"\"")) + << "Improperly-quoted parameter is handled properly #1"; +} + +TEST(MimeType, ImproperlyQuotedParameter2) +{ + const auto in = u"x/x;test=\"\\"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x;test=\"\\\\\"")) + << "Improperly-quoted parameter is handled properly #2"; +} + +TEST(MimeType, NonLatin1ParameterIgnored) +{ + const auto in = u"x/x;test=\xFFFD;x=x"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x;x=x")) + << "Non latin-1 parameters are ignored"; +} + +TEST(MimeType, ParameterIgnoredIfWhitespaceInName1) +{ + const auto in = u"text/html;charset =gbk;charset=123"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=123")) + << "Parameter ignored if whitespace in name #1"; +} + +TEST(MimeType, ParameterIgnoredIfWhitespaceInName2) +{ + const auto in = u"text/html;cha rset =gbk;charset=123"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=123")) + << "Parameter ignored if whitespace in name #2"; +} + +TEST(MimeType, WhitespaceTrimmed) +{ + const auto in = u"\n\r\t text/plain\n\r\t ;\n\r\t charset=123\n\r\t "_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/plain;charset=123")) + << "Whitespace appropriately ignored"; +} + +TEST(MimeType, WhitespaceOnlyParameterIgnored) +{ + const auto in = u"x/x;x= \r\n\t"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x")) + << "Whitespace-only parameter is ignored"; +} + +TEST(MimeType, IncompleteParameterIgnored1) +{ + const auto in = u"x/x;test"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x")) + << "Incomplete parameter is ignored #1"; +} + +TEST(MimeType, IncompleteParameterIgnored2) +{ + const auto in = u"x/x;test="_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x")) + << "Incomplete parameter is ignored #2"; +} + +TEST(MimeType, IncompleteParameterIgnored3) +{ + const auto in = u"x/x;test= \r\n\t"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("x/x")) + << "Incomplete parameter is ignored #3"; +} + +TEST(MimeType, IncompleteParameterIgnored4) +{ + const auto in = u"text/html;test;charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Incomplete parameter is ignored #4"; +} + +TEST(MimeType, IncompleteParameterIgnored5) +{ + const auto in = u"text/html;test=;charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Incomplete parameter is ignored #5"; +} + +TEST(MimeType, EmptyParameterIgnored1) +{ + const auto in = u"text/html ; ; charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Empty parameter ignored #1"; +} + +TEST(MimeType, EmptyParameterIgnored2) +{ + const auto in = u"text/html;;;;charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Empty parameter ignored #2"; +} + +TEST(MimeType, InvalidParameterIgnored1) +{ + const auto in = u"text/html;';charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Invalid parameter ignored #1"; +} + +TEST(MimeType, InvalidParameterIgnored2) +{ + const auto in = u"text/html;\";charset=gbk;=123; =321"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Invalid parameter ignored #2"; +} + +TEST(MimeType, InvalidParameterIgnored3) +{ + const auto in = u"text/html;charset= \"\u007F;charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=GBK")) + << "Invalid parameter ignored #3"; +} + +TEST(MimeType, InvalidParameterIgnored4) +{ + const auto in = nsLiteralString( + u"text/html;charset=\"\u007F;charset=foo\";charset=GBK;charset="); + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=GBK")) + << "Invalid parameter ignored #4"; +} + +TEST(MimeType, SingleQuotes1) +{ + const auto in = u"text/html;charset='gbk'"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset='gbk'")) + << "Single quotes handled properly #1"; +} + +TEST(MimeType, SingleQuotes2) +{ + const auto in = u"text/html;charset='gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset='gbk")) + << "Single quotes handled properly #2"; +} + +TEST(MimeType, SingleQuotes3) +{ + const auto in = u"text/html;charset=gbk'"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk'")) + << "Single quotes handled properly #3"; +} + +TEST(MimeType, SingleQuotes4) +{ + const auto in = u"text/html;charset=';charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset='")) + << "Single quotes handled properly #4"; +} + +TEST(MimeType, SingleQuotes5) +{ + const auto in = u"text/html;charset=''';charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset='''")) + << "Single quotes handled properly #5"; +} + +TEST(MimeType, DoubleQuotes1) +{ + const auto in = u"text/html;charset=\"gbk\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Double quotes handled properly #1"; +} + +TEST(MimeType, DoubleQuotes2) +{ + const auto in = u"text/html;charset=\"gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Double quotes handled properly #2"; +} + +TEST(MimeType, DoubleQuotes3) +{ + const auto in = u"text/html;charset=gbk\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk\\\"\"")) + << "Double quotes handled properly #3"; +} + +TEST(MimeType, DoubleQuotes4) +{ + const auto in = u"text/html;charset=\" gbk\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" gbk\"")) + << "Double quotes handled properly #4"; +} + +TEST(MimeType, DoubleQuotes5) +{ + const auto in = u"text/html;charset=\"gbk \""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk \"")) + << "Double quotes handled properly #5"; +} + +TEST(MimeType, DoubleQuotes6) +{ + const auto in = u"text/html;charset=\"\\ gbk\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" gbk\"")) + << "Double quotes handled properly #6"; +} + +TEST(MimeType, DoubleQuotes7) +{ + const auto in = u"text/html;charset=\"\\g\\b\\k\""_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Double quotes handled properly #7"; +} + +TEST(MimeType, DoubleQuotes8) +{ + const auto in = u"text/html;charset=\"gbk\"x"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) + << "Double quotes handled properly #8"; +} + +TEST(MimeType, DoubleQuotes9) +{ + const auto in = u"text/html;charset=\"\";charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"\"")) + << "Double quotes handled properly #9"; +} + +TEST(MimeType, DoubleQuotes10) +{ + const auto in = u"text/html;charset=\";charset=GBK"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\";charset=GBK\"")) + << "Double quotes handled properly #10"; +} + +TEST(MimeType, UnexpectedCodePoints) +{ + const auto in = u"text/html;charset={gbk}"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"{gbk}\"")) + << "Unexpected code points handled properly"; +} + +TEST(MimeType, LongTypesSubtypesAccepted) +{ + const auto in = nsLiteralString( + u"01234567890123456789012345678901234567890123456789012345678901234567890" + u"1" + "2345678901234567890123456789012345678901234567890123456789/" + "012345678901234567890123456789012345678901234567890123456789012345678901" + "2345678901234567890123456789012345678901234567890123456789"); + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(in)) + << "Long type/subtype accepted"; +} + +TEST(MimeType, LongParametersAccepted) +{ + const auto in = nsLiteralString( + u"text/" + "html;" + "012345678901234567890123456789012345678901234567890123456789012345678901" + "2345678901234567890123456789012345678901234567890123456789=x;charset=" + "gbk"); + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(in)) + << "Long parameters accepted"; +} + +TEST(MimeType, AllValidCharactersAccepted1) +{ + const auto in = nsLiteralString( + u"x/x;x=\"\t " + u"!\\\"#$%&'()*+,-./" + u"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`" + u"abcdefghijklmnopqrstuvwxyz{|}~" + u"\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A" + u"\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095" + u"\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0" + u"\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB" + u"\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6" + u"\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1" + u"\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC" + u"\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7" + u"\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2" + u"\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED" + u"\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8" + u"\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\""); + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.Equals(in)) + << "All valid characters accepted #1"; +} + +TEST(MimeType, CaseNormalization1) +{ + const auto in = u"TEXT/PLAIN;CHARSET=TEST"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/plain;charset=TEST")) + << "Case normalized properly #1"; +} + +TEST(MimeType, CaseNormalization2) +{ + const auto in = nsLiteralString( + u"!#$%&'*+-.^_`|~" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/" + "!#$%&'*+-.^_`|~" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-" + ".^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$" + "%&'*+-.^_`|~" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral( + "!#$%&'*+-.^_`|~" + "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/" + "!#$%&'*+-.^_`|~" + "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-" + ".^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$" + "%&'*+-.^_`|~" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) + << "Case normalized properly #2"; +} + +TEST(MimeType, LegacyCommentSyntax1) +{ + const auto in = u"text/html;charset=gbk("_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk(\"")) + << "Legacy comment syntax #1"; +} + +TEST(MimeType, LegacyCommentSyntax2) +{ + const auto in = u"text/html;x=(;charset=gbk"_ns; + UniquePtr parsed = MimeType::Parse(in); + ASSERT_TRUE(parsed) + << "Parsing succeeded"; + nsAutoString out; + parsed->Serialize(out); + ASSERT_TRUE(out.EqualsLiteral("text/html;x=\"(\";charset=gbk")) + << "Legacy comment syntax #2"; +} + +TEST(MimeTypeParsing, contentTypes1) +{ + const nsAutoCString val(",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_FALSE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes2) +{ + const nsAutoCString val("text/plain,"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes3) +{ + const nsAutoCString val("text/html,text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes4) +{ + const nsAutoCString val("text/plain;charset=gbk,text/html"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes5) +{ + const nsAutoCString val( + "text/plain;charset=gbk,text/html;charset=windows-1254"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("windows-1254")); +} + +TEST(MimeTypeParsing, contentTypes6) +{ + const nsAutoCString val("text/plain;charset=gbk,text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("gbk")); +} + +TEST(MimeTypeParsing, contentTypes7) +{ + const nsAutoCString val( + "text/plain;charset=gbk,text/plain;charset=windows-1252"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("windows-1252")); +} + +TEST(MimeTypeParsing, contentTypes8) +{ + const nsAutoCString val("text/html;charset=gbk,text/html;x=\",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("gbk")); +} + +TEST(MimeTypeParsing, contentTypes9) +{ + const nsAutoCString val("text/plain;charset=gbk;x=foo,text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("gbk")); +} + +TEST(MimeTypeParsing, contentTypes10) +{ + const nsAutoCString val("text/html;charset=gbk,text/plain,text/html"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes11) +{ + const nsAutoCString val("text/plain,*/*"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes12) +{ + const nsAutoCString val("text/html,*/*"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes13) +{ + const nsAutoCString val("*/*,text/html"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes14) +{ + const nsAutoCString val("text/plain,*/*;charset=gbk"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes15) +{ + const nsAutoCString val("text/html,*/*;charset=gbk"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes16) +{ + const nsAutoCString val("text/html;x=\",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes17) +{ + const nsAutoCString val("text/html;\",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes18) +{ + const nsAutoCString val("text/html;\",\\\",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} + +TEST(MimeTypeParsing, contentTypes19) +{ + const nsAutoCString val("text/html;\",\\\",text/plain,\";charset=GBK"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/html")); + ASSERT_TRUE(contentCharset.EqualsLiteral("GBK")); +} + +TEST(MimeTypeParsing, contentTypes20) +{ + const nsAutoCString val("text/html;\",\",text/plain"); + nsCString contentType; + nsCString contentCharset; + + bool parsed = CMimeType::Parse(val, contentType, contentCharset); + + ASSERT_TRUE(parsed); + ASSERT_TRUE(contentType.EqualsLiteral("text/plain")); + ASSERT_TRUE(contentCharset.EqualsLiteral("")); +} diff --git a/dom/base/test/gtest/TestParser.cpp b/dom/base/test/gtest/TestParser.cpp new file mode 100644 index 0000000000..d9240cced7 --- /dev/null +++ b/dom/base/test/gtest/TestParser.cpp @@ -0,0 +1,52 @@ +/* -*- 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 "gtest/gtest.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "mozilla/dom/DOMParser.h" +#include "mozilla/dom/Document.h" +#include "nsIDocumentEncoder.h" +#include "mozilla/ErrorResult.h" + +// This is a test for mozilla::dom::DOMParser::CreateWithoutGlobal() which was +// implemented for use in Thunderbird's MailNews module. + +// int main(int argc, char** argv) +TEST(TestParser, TestParserMain) +{ + bool allTestsPassed = false; + constexpr auto htmlInput = + u"" + "" + "Hello Thunderbird!"_ns; + + do { + // Parse the HTML source. + mozilla::IgnoredErrorResult rv2; + RefPtr parser = + mozilla::dom::DOMParser::CreateWithoutGlobal(rv2); + if (rv2.Failed()) break; + nsCOMPtr document = parser->ParseFromString( + htmlInput, mozilla::dom::SupportedType::Text_html, rv2); + if (rv2.Failed()) break; + + // Serialize it back to HTML source again. + nsCOMPtr encoder = + do_createDocumentEncoder("text/html"); + if (!encoder) break; + nsresult rv = + encoder->Init(document, u"text/html"_ns, nsIDocumentEncoder::OutputRaw); + if (NS_FAILED(rv)) break; + nsString parsed; + rv = encoder->EncodeToString(parsed); + if (NS_FAILED(rv)) break; + + EXPECT_TRUE(parsed.Equals(htmlInput)); + allTestsPassed = true; + } while (false); + + EXPECT_TRUE(allTestsPassed); +} diff --git a/dom/base/test/gtest/TestPlainTextSerializer.cpp b/dom/base/test/gtest/TestPlainTextSerializer.cpp new file mode 100644 index 0000000000..52ef864aa9 --- /dev/null +++ b/dom/base/test/gtest/TestPlainTextSerializer.cpp @@ -0,0 +1,340 @@ +/* -*- 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 "nsServiceManagerUtils.h" +#include "nsString.h" +#include "nsIDocumentEncoder.h" +#include "nsCRT.h" +#include "nsIParserUtils.h" + +const uint32_t kDefaultWrapColumn = 72; + +void ConvertBufToPlainText(nsString& aConBuf, int aFlag, uint32_t aWrapColumn) { + nsCOMPtr utils = do_GetService(NS_PARSERUTILS_CONTRACTID); + utils->ConvertToPlainText(aConBuf, aFlag, aWrapColumn, aConBuf); +} + +// Test for ASCII with format=flowed; delsp=yes +TEST(PlainTextSerializer, ASCIIWithFlowedDelSp) +{ + nsString test; + nsString result; + + test.AssignLiteral( + "" + "Firefox Firefox Firefox Firefox " + "Firefox Firefox Firefox Firefox " + "Firefox Firefox Firefox Firefox" + ""); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputFormatDelSp, + kDefaultWrapColumn); + + // create result case + result.AssignLiteral( + "Firefox Firefox Firefox Firefox " + "Firefox Firefox Firefox Firefox " + "Firefox \r\nFirefox Firefox Firefox\r\n"); + + ASSERT_TRUE(test.Equals(result)) + << "Wrong HTML to ASCII text serialization with format=flowed; delsp=yes"; +} + +TEST(PlainTextSerializer, Bug1864820) +{ + nsString test( + uR"#( + +>  label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=interop&q=label%3Ainterop-2023-property +
              +>  label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=interop&q=label%3Ainterop-2023-property +
              + +)#"); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputPersistNBSP | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed, + kDefaultWrapColumn); + + nsString result( + uR"#( + >  label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=interop&q=label%3Ainterop-2023-property + + >  label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=interop&q=label%3Ainterop-2023-property +)#"); + result.Trim(" \n"); + test.Trim(" \n"); + ASSERT_TRUE(test.Equals(result)) + << "Shouldn't hang with format=flowed: " << NS_ConvertUTF16toUTF8(test).get(); +} + +// Test for CJK with format=flowed; delsp=yes +TEST(PlainTextSerializer, CJKWithFlowedDelSp) +{ + nsString test; + nsString result; + + test.AssignLiteral(""); + for (uint32_t i = 0; i < 40; i++) { + // Insert Kanji (U+5341) + test.Append(0x5341); + } + test.AppendLiteral(""); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputFormatDelSp, + kDefaultWrapColumn); + + // create result case + for (uint32_t i = 0; i < 36; i++) { + result.Append(0x5341); + } + result.AppendLiteral(" \r\n"); + for (uint32_t i = 0; i < 4; i++) { + result.Append(0x5341); + } + result.AppendLiteral("\r\n"); + + ASSERT_TRUE(test.Equals(result)) + << "Wrong HTML to CJK text serialization with format=flowed; delsp=yes"; +} + +// Test for CJK with DisallowLineBreaking +TEST(PlainTextSerializer, CJKWithDisallowLineBreaking) +{ + nsString test; + nsString result; + + test.AssignLiteral(""); + for (uint32_t i = 0; i < 400; i++) { + // Insert Kanji (U+5341) + test.Append(0x5341); + } + test.AppendLiteral(""); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputDisallowLineBreaking, + kDefaultWrapColumn); + + // create result case + for (uint32_t i = 0; i < 400; i++) { + result.Append(0x5341); + } + result.AppendLiteral("\r\n"); + + ASSERT_TRUE(test.Equals(result)) + << "Wrong HTML to CJK text serialization with OutputDisallowLineBreaking"; +} + +// Test for Latin with DisallowLineBreaking +TEST(PlainTextSerializer, LatinWithDisallowLineBreaking) +{ + nsString test; + test.AssignLiteral(""); + for (uint32_t i = 0; i < 400; i++) { + // Insert á (Latin Small Letter a with Acute) (U+00E1) + test.Append(0x00E1); + } + test.AppendLiteral("\r\n"); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputDisallowLineBreaking, + kDefaultWrapColumn); + + // Create expect case. + nsString expect; + for (uint32_t i = 0; i < 400; i++) { + expect.Append(0x00E1); + } + expect.AppendLiteral(" \r\n\r\n"); + + ASSERT_TRUE(test.Equals(expect)) + << "Wrong HTML to Latin text serialization with OutputDisallowLineBreaking"; +} + +// Test for ASCII with format=flowed; and quoted lines in preformatted span. +TEST(PlainTextSerializer, PreformatFlowedQuotes) +{ + nsString test; + nsString result; + + test.AssignLiteral( + "" + "" + "> Firefox Firefox Firefox Firefox
              " + "> Firefox Firefox Firefox Firefox
              " + ">
              " + ">> Firefox Firefox Firefox Firefox
              " + ">> Firefox Firefox Firefox Firefox
              " + "
              "); + + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputFormatFlowed, + kDefaultWrapColumn); + + // create result case + result.AssignLiteral( + "> Firefox Firefox Firefox Firefox \r\n" + "> Firefox Firefox Firefox Firefox\r\n" + ">\r\n" + ">> Firefox Firefox Firefox Firefox \r\n" + ">> Firefox Firefox Firefox Firefox\r\n"); + + ASSERT_TRUE(test.Equals(result)) + << "Wrong HTML to ASCII text serialization " + "with format=flowed; and quoted " + "lines"; +} + +TEST(PlainTextSerializer, PrettyPrintedHtml) +{ + nsString test; + test.AppendLiteral("" NS_LINEBREAK "" NS_LINEBREAK + " first
              " NS_LINEBREAK " second
              " NS_LINEBREAK + "" NS_LINEBREAK ""); + + ConvertBufToPlainText(test, 0, kDefaultWrapColumn); + ASSERT_TRUE(test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) + << "Wrong prettyprinted html to text serialization"; +} + +TEST(PlainTextSerializer, PreElement) +{ + nsString test; + test.AppendLiteral("" NS_LINEBREAK "" NS_LINEBREAK + "
              " NS_LINEBREAK "  first" NS_LINEBREAK
              +                     "  second" NS_LINEBREAK "
              " NS_LINEBREAK + "" NS_LINEBREAK ""); + + ConvertBufToPlainText(test, 0, kDefaultWrapColumn); + ASSERT_TRUE(test.EqualsLiteral(" first" NS_LINEBREAK + " second" NS_LINEBREAK NS_LINEBREAK)) + << "Wrong prettyprinted html to text serialization"; +} + +TEST(PlainTextSerializer, BlockElement) +{ + nsString test; + test.AppendLiteral("" NS_LINEBREAK "" NS_LINEBREAK + "
              " NS_LINEBREAK " first" NS_LINEBREAK + "
              " NS_LINEBREAK "
              " NS_LINEBREAK + " second" NS_LINEBREAK "
              " NS_LINEBREAK + "" NS_LINEBREAK ""); + + ConvertBufToPlainText(test, 0, kDefaultWrapColumn); + ASSERT_TRUE(test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) + << "Wrong prettyprinted html to text serialization"; +} + +TEST(PlainTextSerializer, PreWrapElementForThunderbird) +{ + // This test examines the magic pre-wrap setup that Thunderbird relies on. + nsString test; + test.AppendLiteral("" NS_LINEBREAK + "" NS_LINEBREAK + "
              " NS_LINEBREAK
              +                     "  first line is too long" NS_LINEBREAK
              +                     "  second line is even loooonger  " NS_LINEBREAK
              +                     "
              " NS_LINEBREAK "" NS_LINEBREAK ""); + + const uint32_t wrapColumn = 10; + ConvertBufToPlainText(test, nsIDocumentEncoder::OutputWrap, wrapColumn); + // "\n\n first\nline is\ntoo long\n second\nline is\neven\nloooonger\n\n\n" + ASSERT_TRUE(test.EqualsLiteral( + NS_LINEBREAK NS_LINEBREAK + " first" NS_LINEBREAK "line is" NS_LINEBREAK "too long" NS_LINEBREAK + " second" NS_LINEBREAK "line is" NS_LINEBREAK "even" NS_LINEBREAK + "loooonger" NS_LINEBREAK NS_LINEBREAK NS_LINEBREAK)) + << "Wrong prettyprinted html to text serialization"; +} + +TEST(PlainTextSerializer, Simple) +{ + nsString test; + test.AppendLiteral( + "basespan" + "body"); + ConvertBufToPlainText(test, 0, kDefaultWrapColumn); + ASSERT_TRUE(test.EqualsLiteral("basespanbody")) + << "Wrong html to text serialization"; +} + +TEST(PlainTextSerializer, OneHundredAndOneOL) +{ + nsAutoString test; + test.AppendLiteral( + "" + "" + "
                                              <" + "ol>
                                                                                <" + "ol>
                                                                                                                  <" + "ol>
                                                                                                                                                    <" + "ol>
                                                                                                                                                                                      <" + "ol>
                      1. X
                      " + "" + ""); + + ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted, + kDefaultWrapColumn); + + nsAutoString expected; + expected.AppendLiteral(" 1. X" NS_LINEBREAK); + ASSERT_EQ(test, expected); +} + +TEST(PlainTextSerializer, BlockQuoteCite) +{ + nsAutoString test; + test.AppendLiteral(u"
                      hello world
                      "); + + const uint32_t wrapColumn = 10; + ConvertBufToPlainText(test, + nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputCRLineBreak | + nsIDocumentEncoder::OutputLFLineBreak, + wrapColumn); + + constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING( + "> hello \r\n" + "> world\r\n"); + + ASSERT_TRUE(test.Equals(expect)) + << "Wrong blockquote cite to text serialization"; +} diff --git a/dom/base/test/gtest/TestScheduler.cpp b/dom/base/test/gtest/TestScheduler.cpp new file mode 100644 index 0000000000..5d04926627 --- /dev/null +++ b/dom/base/test/gtest/TestScheduler.cpp @@ -0,0 +1,348 @@ +/* -*- 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 "gtest/gtest.h" +#include "mozilla/dom/CCGCScheduler.h" +#include "mozilla/TimeStamp.h" + +// This is a test for mozilla::CCGCScheduler. + +using namespace mozilla; + +static TimeDuration kOneSecond = TimeDuration::FromSeconds(1); +static TimeDuration kTenthSecond = TimeDuration::FromSeconds(0.1); +static TimeDuration kFrameDuration = TimeDuration::FromSeconds(1.0 / 60.0); + +static mozilla::TimeStamp sNow = TimeStamp::Now(); + +static mozilla::TimeStamp AdvanceTime(TimeDuration aDuration) { + sNow += aDuration; + return sNow; +} + +static TimeStamp Now() { return sNow; } + +static uint32_t sSuspected = 0; + +static uint32_t SuspectedCCObjects() { return sSuspected; } +static void SetNumSuspected(uint32_t n) { sSuspected = n; } +static void SuspectMore(uint32_t n) { sSuspected += n; } + +using CCRunnerState = mozilla::CCGCScheduler::CCRunnerState; + +class TestGC { + protected: + CCGCScheduler& mScheduler; + + public: + explicit TestGC(CCGCScheduler& aScheduler) : mScheduler(aScheduler) {} + void Run(int aNumSlices); +}; + +void TestGC::Run(int aNumSlices) { + // Make the purple buffer nearly empty so it is itself not an adequate reason + // for wanting a CC. + static_assert(3 < mozilla::kCCPurpleLimit); + SetNumSuspected(3); + + // Running the GC should not influence whether a CC is currently seen as + // needed. But the first time we run GC, it will be false; later, we will + // have run a GC and set it to true. + CCReason neededCCAtStartOfGC = + mScheduler.IsCCNeeded(Now(), SuspectedCCObjects()); + + mScheduler.NoteGCBegin(JS::GCReason::API); + + for (int slice = 0; slice < aNumSlices; slice++) { + EXPECT_TRUE(mScheduler.InIncrementalGC()); + TimeStamp idleDeadline = Now() + kTenthSecond; + js::SliceBudget budget = + mScheduler.ComputeInterSliceGCBudget(idleDeadline, Now()); + TimeDuration budgetDuration = + TimeDuration::FromMilliseconds(budget.timeBudget()); + EXPECT_NEAR(budgetDuration.ToSeconds(), 0.1, 1.e-6); + // Pretend the GC took exactly the budget. + AdvanceTime(budgetDuration); + + EXPECT_EQ(mScheduler.IsCCNeeded(Now(), SuspectedCCObjects()), + neededCCAtStartOfGC); + + // Mutator runs for 1 second. + AdvanceTime(kOneSecond); + } + + mScheduler.NoteGCEnd(); + mScheduler.SetNeedsFullGC(false); +} + +class TestCC { + protected: + CCGCScheduler& mScheduler; + + public: + explicit TestCC(CCGCScheduler& aScheduler) : mScheduler(aScheduler) {} + + void Run(int aNumSlices) { + Prepare(); + MaybePokeCC(); + TimerFires(aNumSlices); + EndCycleCollectionCallback(); + KillCCRunner(); + } + + virtual void Prepare() = 0; + virtual void MaybePokeCC(); + virtual void TimerFires(int aNumSlices); + virtual void RunSlices(int aNumSlices); + virtual void RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd, + int aSliceNum, int aNumSlices) = 0; + virtual void ForgetSkippable(); + virtual void EndCycleCollectionCallback(); + virtual void KillCCRunner(); +}; + +void TestCC::MaybePokeCC() { + // nsJSContext::MaybePokeCC + + // In all tests so far, we will be running this just after a GC. + CCReason reason = mScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()); + EXPECT_EQ(reason, CCReason::GC_FINISHED); + + mScheduler.InitCCRunnerStateMachine(CCRunnerState::ReducePurple, reason); + EXPECT_TRUE(mScheduler.IsEarlyForgetSkippable()); +} + +void TestCC::TimerFires(int aNumSlices) { + // Series of CCRunner timer fires. + CCRunnerStep step; + + while (true) { + SuspectMore(1000); + TimeStamp idleDeadline = Now() + kOneSecond; + step = + mScheduler.AdvanceCCRunner(idleDeadline, Now(), SuspectedCCObjects()); + // Should first see a series of ForgetSkippable actions. + if (step.mAction != CCRunnerAction::ForgetSkippable || + step.mParam.mRemoveChildless != KeepChildless) { + break; + } + EXPECT_EQ(step.mYield, Yield); + ForgetSkippable(); + } + + while (step.mYield == Continue) { + TimeStamp idleDeadline = Now() + kOneSecond; + step = + mScheduler.AdvanceCCRunner(idleDeadline, Now(), SuspectedCCObjects()); + } + EXPECT_EQ(step.mAction, CCRunnerAction::ForgetSkippable); + EXPECT_EQ(step.mParam.mRemoveChildless, RemoveChildless); + ForgetSkippable(); + + TimeStamp idleDeadline = Now() + kOneSecond; + step = mScheduler.AdvanceCCRunner(idleDeadline, Now(), SuspectedCCObjects()); + EXPECT_EQ(step.mAction, CCRunnerAction::CleanupContentUnbinder); + step = mScheduler.AdvanceCCRunner(idleDeadline, Now(), SuspectedCCObjects()); + EXPECT_EQ(step.mAction, CCRunnerAction::CleanupDeferred); + + mScheduler.NoteCCBegin(CCReason::API, Now(), 0, sSuspected, 0); + RunSlices(aNumSlices); +} + +void TestCC::ForgetSkippable() { + uint32_t suspectedBefore = sSuspected; + // ...ForgetSkippable would happen here... + js::SliceBudget budget = + mScheduler.ComputeForgetSkippableBudget(Now(), Now() + kTenthSecond); + EXPECT_NEAR(budget.timeBudget(), kTenthSecond.ToMilliseconds(), 1); + AdvanceTime(kTenthSecond); + mScheduler.NoteForgetSkippableComplete(Now(), suspectedBefore, + SuspectedCCObjects()); +} + +void TestCC::RunSlices(int aNumSlices) { + TimeStamp ccStartTime = Now(); + TimeStamp prevSliceEnd = ccStartTime; + for (int ccslice = 0; ccslice < aNumSlices; ccslice++) { + RunSlice(ccStartTime, prevSliceEnd, ccslice, aNumSlices); + prevSliceEnd = Now(); + } + + SetNumSuspected(0); +} + +void TestCC::EndCycleCollectionCallback() { + // nsJSContext::EndCycleCollectionCallback + CycleCollectorResults results; + results.mFreedGCed = 10; + results.mFreedJSZones = 2; + mScheduler.NoteCCEnd(results, Now(), TimeDuration()); + + // Because > 0 zones were freed. + EXPECT_TRUE(mScheduler.NeedsGCAfterCC()); +} + +void TestCC::KillCCRunner() { + // nsJSContext::KillCCRunner + mScheduler.KillCCRunner(); +} + +class TestIdleCC : public TestCC { + public: + explicit TestIdleCC(CCGCScheduler& aScheduler) : TestCC(aScheduler) {} + + void Prepare() override; + void RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd, int aSliceNum, + int aNumSlices) override; +}; + +void TestIdleCC::Prepare() { EXPECT_TRUE(!mScheduler.InIncrementalGC()); } + +void TestIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd, + int aSliceNum, int aNumSlices) { + CCRunnerStep step; + TimeStamp idleDeadline = Now() + kTenthSecond; + + // The scheduler should request a CycleCollect slice. + step = mScheduler.AdvanceCCRunner(idleDeadline, Now(), SuspectedCCObjects()); + EXPECT_EQ(step.mAction, CCRunnerAction::CycleCollect); + + // nsJSContext::RunCycleCollectorSlice + + EXPECT_FALSE(mScheduler.InIncrementalGC()); + bool preferShorter; + js::SliceBudget budget = mScheduler.ComputeCCSliceBudget( + idleDeadline, aCCStartTime, aPrevSliceEnd, Now(), &preferShorter); + // The scheduler will set the budget to our deadline (0.1sec in the future). + EXPECT_NEAR(budget.timeBudget(), kTenthSecond.ToMilliseconds(), 1); + EXPECT_FALSE(preferShorter); + + AdvanceTime(kTenthSecond); +} + +class TestNonIdleCC : public TestCC { + public: + explicit TestNonIdleCC(CCGCScheduler& aScheduler) : TestCC(aScheduler) {} + + void Prepare() override; + void RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd, int aSliceNum, + int aNumSlices) override; +}; + +void TestNonIdleCC::Prepare() { + EXPECT_TRUE(!mScheduler.InIncrementalGC()); + + // Advance time by an hour to give time for a user event in the past. + AdvanceTime(TimeDuration::FromSeconds(3600)); +} + +void TestNonIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd, + int aSliceNum, int aNumSlices) { + CCRunnerStep step; + TimeStamp nullDeadline; + + // The scheduler should tell us to run a slice of cycle collection. + step = mScheduler.AdvanceCCRunner(nullDeadline, Now(), SuspectedCCObjects()); + EXPECT_EQ(step.mAction, CCRunnerAction::CycleCollect); + + // nsJSContext::RunCycleCollectorSlice + + EXPECT_FALSE(mScheduler.InIncrementalGC()); + + bool preferShorter; + js::SliceBudget budget = mScheduler.ComputeCCSliceBudget( + nullDeadline, aCCStartTime, aPrevSliceEnd, Now(), &preferShorter); + if (aSliceNum == 0) { + // First slice of the CC, so always use the baseBudget which is + // kICCSliceBudget (3ms) for a non-idle slice. + EXPECT_NEAR(budget.timeBudget(), kICCSliceBudget.ToMilliseconds(), 0.1); + } else if (aSliceNum == 1) { + // Second slice still uses the baseBudget, since not much time has passed + // so none of the lengthening mechanisms have kicked in yet. + EXPECT_NEAR(budget.timeBudget(), kICCSliceBudget.ToMilliseconds(), 0.1); + } else if (aSliceNum == 2) { + // We're not overrunning kMaxICCDuration, so we don't go unlimited. + EXPECT_FALSE(budget.isUnlimited()); + // This slice is delayed, slice time should be increased. + EXPECT_NEAR(budget.timeBudget(), + MainThreadIdlePeriod::GetLongIdlePeriod() / 2, 0.1); + } else { + // We're not overrunning kMaxICCDuration, so we don't go unlimited. + EXPECT_FALSE(budget.isUnlimited()); + + // These slices are not delayed, but enough time has passed that the + // dominating factor is now the linear ramp up to max slice time at the + // halfway point to kMaxICCDuration. + EXPECT_TRUE(budget.timeBudget() > kICCSliceBudget.ToMilliseconds()); + EXPECT_TRUE(budget.timeBudget() <= + MainThreadIdlePeriod::GetLongIdlePeriod()); + } + EXPECT_TRUE(preferShorter); // Non-idle prefers shorter slices + + AdvanceTime(TimeDuration::FromMilliseconds(budget.timeBudget())); + if (aSliceNum == 1) { + // Delay the third slice (only). + AdvanceTime(kICCIntersliceDelay * 2); + } +} + +// Do a GC then CC then GC. +static bool BasicScenario(CCGCScheduler& aScheduler, TestGC* aTestGC, + TestCC* aTestCC) { + // Run a 10-slice incremental GC. + aTestGC->Run(10); + + // After a GC, the scheduler should decide to do a full CC regardless of the + // number of purple buffer entries. + SetNumSuspected(3); + EXPECT_EQ(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()), + CCReason::GC_FINISHED); + + // Now we should want to CC. + EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()), + CCReason::GC_FINISHED); + + // Do a 5-slice CC. + aTestCC->Run(5); + + // Not enough suspected objects to deserve a CC. + EXPECT_EQ(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()), + CCReason::NO_REASON); + EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()), + CCReason::NO_REASON); + SetNumSuspected(10000); + + // We shouldn't want to CC again yet, it's too soon. + EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()), + CCReason::NO_REASON); + AdvanceTime(mozilla::kCCDelay); + + // *Now* it's time for another CC. + EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()), + CCReason::MANY_SUSPECTED); + + // Run a 3-slice incremental GC. + EXPECT_TRUE(!aScheduler.InIncrementalGC()); + aTestGC->Run(3); + + return true; +} + +static CCGCScheduler scheduler; +static TestGC gc(scheduler); +static TestIdleCC ccIdle(scheduler); +static TestNonIdleCC ccNonIdle(scheduler); + +TEST(TestScheduler, Idle) +{ + // Cannot CC until we GC once. + EXPECT_EQ(scheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()), + CCReason::NO_REASON); + + EXPECT_TRUE(BasicScenario(scheduler, &gc, &ccIdle)); +} + +TEST(TestScheduler, NonIdle) +{ EXPECT_TRUE(BasicScenario(scheduler, &gc, &ccNonIdle)); } diff --git a/dom/base/test/gtest/TestXMLSerializerNoBreakLink.cpp b/dom/base/test/gtest/TestXMLSerializerNoBreakLink.cpp new file mode 100644 index 0000000000..a63410303e --- /dev/null +++ b/dom/base/test/gtest/TestXMLSerializerNoBreakLink.cpp @@ -0,0 +1,69 @@ +/* -*- 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 "gtest/gtest.h" +#include "nsCOMPtr.h" +#include "nsIDocumentEncoder.h" +#include "nsString.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DOMParser.h" + +using namespace mozilla; +using namespace mozilla::dom; + +// Test that serialising some DOM doesn't destroy links by word-wrapping long +// href values containing spaces. +TEST(TestXMLSerializerNoBreakLink, TestXMLSerializerNoBreakLinkMain) +{ + // Build up a stupidly-long URL with spaces. Default is to wrap at column + // 72, so we want to exceed that. + nsString longURL = u"http://www.example.com/link with spaces"_ns; + for (int i = 1; i < 125; ++i) { + longURL.Append(u' '); + longURL.Append(IntToTString(i)); + } + nsString htmlInput = + u"" + "" + "Hello Thunderbird! Link"_ns; + + // Parse HTML into a Document. + nsCOMPtr document; + { + IgnoredErrorResult rv; + RefPtr parser = DOMParser::CreateWithoutGlobal(rv); + ASSERT_FALSE(rv.Failed()); + document = parser->ParseFromString(htmlInput, SupportedType::Text_html, rv); + ASSERT_FALSE(rv.Failed()); + } + + // Serialize back in a variety of flavours and check the URL survives the + // round trip intact. + nsCString contentTypes[] = {"text/xml"_ns, "application/xml"_ns, + "application/xhtml+xml"_ns, "image/svg+xml"_ns, + "text/html"_ns}; + for (auto const& contentType : contentTypes) { + uint32_t flagsToTest[] = { + nsIDocumentEncoder::OutputFormatted, nsIDocumentEncoder::OutputWrap, + nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputWrap}; + for (uint32_t flags : flagsToTest) { + // Serialize doc back to HTML source again. + nsCOMPtr encoder = + do_createDocumentEncoder(contentType.get()); + ASSERT_TRUE(encoder); + nsresult rv = + encoder->Init(document, NS_ConvertASCIItoUTF16(contentType), flags); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + nsString parsed; + rv = encoder->EncodeToString(parsed); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + // URL is intact? + EXPECT_TRUE(parsed.Find(longURL) != kNotFound); + } + } +} diff --git a/dom/base/test/gtest/TestXPathGenerator.cpp b/dom/base/test/gtest/TestXPathGenerator.cpp new file mode 100644 index 0000000000..c9f4993179 --- /dev/null +++ b/dom/base/test/gtest/TestXPathGenerator.cpp @@ -0,0 +1,150 @@ +/* -*- 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 "XPathGenerator.h" +#include "nsString.h" + +TEST(TestXPathGenerator, TestQuoteArgumentWithoutQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"testing"); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"\'testing\'"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, TestQuoteArgumentWithSingleQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"\'testing\'"); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"\"\'testing\'\""); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, TestQuoteArgumentWithDoubleQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"\"testing\""); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"\'\"testing\"\'"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, TestQuoteArgumentWithSingleAndDoubleQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"\'testing\""); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"concat(\'\',\"\'\",\'testing\"\')"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), + NS_ConvertUTF16toUTF8(expectedResult).get()); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, + TestQuoteArgumentWithDoubleQuoteAndASequenceOfSingleQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"\'\'\'\'testing\""); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"concat(\'\',\"\'\'\'\'\",\'testing\"\')"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), + NS_ConvertUTF16toUTF8(expectedResult).get()); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, + TestQuoteArgumentWithDoubleQuoteAndTwoSequencesOfSingleQuote) +{ + nsAutoString arg; + arg.AssignLiteral(u"\'\'\'\'testing\'\'\'\'\'\'\""); + + nsAutoString expectedResult; + expectedResult.AssignLiteral( + u"concat(\'\',\"\'\'\'\'\",\'testing\',\"\'\'\'\'\'\'\",\'\"\')"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), + NS_ConvertUTF16toUTF8(expectedResult).get()); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, + TestQuoteArgumentWithDoubleQuoteAndTwoSequencesOfSingleQuoteInMiddle) +{ + nsAutoString arg; + arg.AssignLiteral(u"t\'\'\'\'estin\'\'\'\'\'\'\"g"); + + nsAutoString expectedResult; + expectedResult.AssignLiteral( + u"concat(\'t\',\"\'\'\'\'\",\'estin\',\"\'\'\'\'\'\'\",\'\"g\')"); + + nsAutoString result; + XPathGenerator::QuoteArgument(arg, result); + printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), + NS_ConvertUTF16toUTF8(expectedResult).get()); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, TestEscapeNameWithNormalCharacters) +{ + nsAutoString arg; + arg.AssignLiteral(u"testing"); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"testing"); + + nsAutoString result; + XPathGenerator::EscapeName(arg, result); + + ASSERT_TRUE(expectedResult.Equals(result)); +} + +TEST(TestXPathGenerator, TestEscapeNameWithSpecialCharacters) +{ + nsAutoString arg; + arg.AssignLiteral(u"^testing!"); + + nsAutoString expectedResult; + expectedResult.AssignLiteral(u"*[local-name()=\'^testing!\']"); + + nsAutoString result; + XPathGenerator::EscapeName(arg, result); + printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), + NS_ConvertUTF16toUTF8(expectedResult).get()); + + ASSERT_TRUE(expectedResult.Equals(result)); +} diff --git a/dom/base/test/gtest/moz.build b/dom/base/test/gtest/moz.build new file mode 100644 index 0000000000..9a767eb2ff --- /dev/null +++ b/dom/base/test/gtest/moz.build @@ -0,0 +1,21 @@ +# -*- 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/. + +UNIFIED_SOURCES += [ + "TestContentUtils.cpp", + "TestMimeType.cpp", + "TestParser.cpp", + "TestPlainTextSerializer.cpp", + "TestScheduler.cpp", + "TestXMLSerializerNoBreakLink.cpp", + "TestXPathGenerator.cpp", +] + +LOCAL_INCLUDES += ["/dom/base"] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul-gtest" diff --git a/dom/base/test/head.js b/dom/base/test/head.js new file mode 100644 index 0000000000..2b39f7a7b1 --- /dev/null +++ b/dom/base/test/head.js @@ -0,0 +1,15 @@ +async function newFocusedWindow(trigger) { + let winPromise = BrowserTestUtils.domWindowOpenedAndLoaded(); + let delayedStartupPromise = BrowserTestUtils.waitForNewWindow(); + + await trigger(); + + let win = await winPromise; + // New windows get focused after the first paint, see bug 1262946 + await BrowserTestUtils.waitForContentEvent( + win.gBrowser.selectedBrowser, + "MozAfterPaint" + ); + await delayedStartupPromise; + return win; +} diff --git a/dom/base/test/iframe1_bug1640766.html b/dom/base/test/iframe1_bug1640766.html new file mode 100644 index 0000000000..51da4f22f0 --- /dev/null +++ b/dom/base/test/iframe1_bug1640766.html @@ -0,0 +1,20 @@ + + + +Iframe 1 for Bug 1640766 + + +
                      Iframe 1
                      + + + diff --git a/dom/base/test/iframe1_bug426646.html b/dom/base/test/iframe1_bug426646.html new file mode 100644 index 0000000000..533e77ad4c --- /dev/null +++ b/dom/base/test/iframe1_bug426646.html @@ -0,0 +1 @@ +1st page diff --git a/dom/base/test/iframe1_bug431701.html b/dom/base/test/iframe1_bug431701.html new file mode 100644 index 0000000000..18ecdcb795 --- /dev/null +++ b/dom/base/test/iframe1_bug431701.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe2_bug1640766.html b/dom/base/test/iframe2_bug1640766.html new file mode 100644 index 0000000000..6a5ca30796 --- /dev/null +++ b/dom/base/test/iframe2_bug1640766.html @@ -0,0 +1,10 @@ + + + +Iframe 2 for Bug 1640766 + + +
                      Iframe 2
                      + + + diff --git a/dom/base/test/iframe2_bug426646.html b/dom/base/test/iframe2_bug426646.html new file mode 100644 index 0000000000..45e85c0f13 --- /dev/null +++ b/dom/base/test/iframe2_bug426646.html @@ -0,0 +1 @@ +2nd page diff --git a/dom/base/test/iframe2_bug431701.html b/dom/base/test/iframe2_bug431701.html new file mode 100644 index 0000000000..6c963c5455 --- /dev/null +++ b/dom/base/test/iframe2_bug431701.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe3_bug431701.html b/dom/base/test/iframe3_bug431701.html new file mode 100644 index 0000000000..c0aac38766 --- /dev/null +++ b/dom/base/test/iframe3_bug431701.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe4_bug431701.xml b/dom/base/test/iframe4_bug431701.xml new file mode 100644 index 0000000000..18ecdcb795 --- /dev/null +++ b/dom/base/test/iframe4_bug431701.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe5_bug431701.xml b/dom/base/test/iframe5_bug431701.xml new file mode 100644 index 0000000000..d761751ee1 --- /dev/null +++ b/dom/base/test/iframe5_bug431701.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe6_bug431701.xml b/dom/base/test/iframe6_bug431701.xml new file mode 100644 index 0000000000..17704b893a --- /dev/null +++ b/dom/base/test/iframe6_bug431701.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe7_bug431701.xml b/dom/base/test/iframe7_bug431701.xml new file mode 100644 index 0000000000..73757924a7 --- /dev/null +++ b/dom/base/test/iframe7_bug431701.xml @@ -0,0 +1 @@ + diff --git a/dom/base/test/iframe_bug962251.html b/dom/base/test/iframe_bug962251.html new file mode 100644 index 0000000000..2fa3a50dcf --- /dev/null +++ b/dom/base/test/iframe_bug962251.html @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dom/base/test/iframe_bug976673.html b/dom/base/test/iframe_bug976673.html new file mode 100644 index 0000000000..92c5bf76d0 --- /dev/null +++ b/dom/base/test/iframe_bug976673.html @@ -0,0 +1,26 @@ + + + + + Test for Bug 976673 + + + + + + diff --git a/dom/base/test/iframe_main_bug1022229.html b/dom/base/test/iframe_main_bug1022229.html new file mode 100644 index 0000000000..c89a8c9a9d --- /dev/null +++ b/dom/base/test/iframe_main_bug1022229.html @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/dom/base/test/iframe_meta_refresh.sjs b/dom/base/test/iframe_meta_refresh.sjs new file mode 100644 index 0000000000..264a9e0efc --- /dev/null +++ b/dom/base/test/iframe_meta_refresh.sjs @@ -0,0 +1,90 @@ +/* + * Test server for iframe refresh from meta http-equiv + */ + +const SHARED_KEY = "iframe_meta_refresh"; +const DEFAULT_STATE = { count: 0, referrers: [] }; +const REFRESH_PAGE = + "http://example.com/tests/dom/base/test/iframe_meta_refresh.sjs?action=test"; + +function createContent(refresh) { + let metaRefresh = ""; + let scriptMessage = ""; + + if (refresh) { + metaRefresh = ``; + } else { + scriptMessage = ` + `; + } + + return ` + + + + ${metaRefresh} + Test referrer of meta http-equiv refresh + + + ${scriptMessage} + + `; +} + +function handleRequest(request, response) { + let query = new URLSearchParams(request.queryString); + + let action = query.get("action"); + + var referrerLevel = "none"; + if (request.hasHeader("Referer")) { + let referrer = request.getHeader("Referer"); + if (referrer.indexOf("test_meta_refresh_referrer") > 0) { + referrerLevel = "full"; + } else if (referrer == "http://mochi.test:8888/") { + referrerLevel = "origin"; + } + } + + var state = getSharedState(SHARED_KEY); + if (state === "") { + state = DEFAULT_STATE; + } else { + state = JSON.parse(state); + } + + response.setStatusLine(request.httpVersion, 200, "OK"); + + //avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + if (action === "results") { + response.setHeader("Content-Type", "text/plain", false); + response.write(JSON.stringify(state)); + return; + } + + if (action === "reset") { + //reset server state + setSharedState(SHARED_KEY, JSON.stringify(DEFAULT_STATE)); + response.write(""); + return; + } + + if (action === "test") { + let load = query.get("load"); + state.count++; + if (state.referrers.indexOf(referrerLevel) < 0) { + state.referrers.push(referrerLevel); + } + + // Write frame content + response.write(createContent(load)); + } + + setSharedState(SHARED_KEY, JSON.stringify(state)); +} diff --git a/dom/base/test/iframe_postMessage_solidus.html b/dom/base/test/iframe_postMessage_solidus.html new file mode 100644 index 0000000000..86f12367ec --- /dev/null +++ b/dom/base/test/iframe_postMessage_solidus.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/dom/base/test/iframe_postMessages.html b/dom/base/test/iframe_postMessages.html new file mode 100644 index 0000000000..0b07456eb8 --- /dev/null +++ b/dom/base/test/iframe_postMessages.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/dom/base/test/iframe_sandbox_bug1022229.html b/dom/base/test/iframe_sandbox_bug1022229.html new file mode 100644 index 0000000000..3d70e9d7af --- /dev/null +++ b/dom/base/test/iframe_sandbox_bug1022229.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/base/test/iframe_shared_compartment2a.html b/dom/base/test/iframe_shared_compartment2a.html new file mode 100644 index 0000000000..e2451367bb --- /dev/null +++ b/dom/base/test/iframe_shared_compartment2a.html @@ -0,0 +1,2 @@ + diff --git a/dom/base/test/iframe_shared_compartment2b.html b/dom/base/test/iframe_shared_compartment2b.html new file mode 100644 index 0000000000..64d57320f8 --- /dev/null +++ b/dom/base/test/iframe_shared_compartment2b.html @@ -0,0 +1,3 @@ + diff --git a/dom/base/test/intersectionobserver_cross_domain_iframe.html b/dom/base/test/intersectionobserver_cross_domain_iframe.html new file mode 100644 index 0000000000..750ccaf6f2 --- /dev/null +++ b/dom/base/test/intersectionobserver_cross_domain_iframe.html @@ -0,0 +1,24 @@ + + + + + +
                      + + + diff --git a/dom/base/test/intersectionobserver_iframe.html b/dom/base/test/intersectionobserver_iframe.html new file mode 100644 index 0000000000..dae0da82c9 --- /dev/null +++ b/dom/base/test/intersectionobserver_iframe.html @@ -0,0 +1,17 @@ + + + + + +
                      + + diff --git a/dom/base/test/intersectionobserver_window.html b/dom/base/test/intersectionobserver_window.html new file mode 100644 index 0000000000..826b5064eb --- /dev/null +++ b/dom/base/test/intersectionobserver_window.html @@ -0,0 +1,46 @@ + + + + + +
                      + + + diff --git a/dom/base/test/invalid_accesscontrol.resource b/dom/base/test/invalid_accesscontrol.resource new file mode 100644 index 0000000000..aca66f6f8d --- /dev/null +++ b/dom/base/test/invalid_accesscontrol.resource @@ -0,0 +1,7 @@ +:this file must be enconded in utf8 +:and its Content-Type must be equal to text/event-stream + +event: message +data: 1 + + diff --git a/dom/base/test/invalid_accesscontrol.resource^headers^ b/dom/base/test/invalid_accesscontrol.resource^headers^ new file mode 100644 index 0000000000..d5bed552cb --- /dev/null +++ b/dom/base/test/invalid_accesscontrol.resource^headers^ @@ -0,0 +1,4 @@ +Access-Control-Allow-Origin: http://an.accesscrontrol.domain:80 +Content-Type: text/event-stream +Cache-Control: no-cache, must-revalidate + diff --git a/dom/base/test/jsmodules/.eslintrc.js b/dom/base/test/jsmodules/.eslintrc.js new file mode 100644 index 0000000000..25a38d20af --- /dev/null +++ b/dom/base/test/jsmodules/.eslintrc.js @@ -0,0 +1,15 @@ +"use strict"; + +module.exports = { + overrides: [ + { + // eslint-plugin-html doesn't automatically detect module sections in + // html files. Enable these as a module here. JavaScript files can use + // the mjs extension. + files: ["*.html"], + parserOptions: { + sourceType: "module", + }, + }, + ], +}; diff --git a/dom/base/test/jsmodules/ambiguous_export.mjs b/dom/base/test/jsmodules/ambiguous_export.mjs new file mode 100644 index 0000000000..0018e1bc47 --- /dev/null +++ b/dom/base/test/jsmodules/ambiguous_export.mjs @@ -0,0 +1,3 @@ +/* eslint-disable import/export */ +export * from "./exportA1.mjs"; +export * from "./exportA2.mjs"; diff --git a/dom/base/test/jsmodules/chrome.toml b/dom/base/test/jsmodules/chrome.toml new file mode 100644 index 0000000000..82d02ad4df --- /dev/null +++ b/dom/base/test/jsmodules/chrome.toml @@ -0,0 +1,94 @@ +[DEFAULT] +support-files = [ + "ambiguous_export.mjs", + "import_ambiguous.mjs", + "import_ambiguous_indirect_export.mjs", + "import_no_export.mjs", + "import_no_indirect_export.mjs", + "exportA1.mjs", + "exportA2.mjs", + "export_ambiguous.mjs", + "module_setRan.mjs", + "module_testSyntax.mjs", + "module_badSyntax.mjs", + "module_simpleImport.mjs", + "module_simpleExport.mjs", + "module_badImport.mjs", + "module_simple1.mjs", + "module_simple2.mjs", + "module_simple3.mjs", + "module_cyclic1.mjs", + "module_cyclic2.mjs", + "module_cyclic3.mjs", + "module_multiImports.mjs", + "module_multiLargeImports.mjs", + "no_export.mjs", + "no_indirect_export.mjs", + "script_simple2.js", + "module_large1.mjs", + "module_large2.mjs", + "module_large3.mjs", + "module_extractIntroType.mjs", + "iframe_extractIntroType.html", + "module_missingImport.mjs", +] + +["test_asyncInlineModules.html"] + +["test_cyclicImport.html"] + +["test_dynamicImportErrorMessage.html"] + +["test_importIntroType.html"] + +["test_importNotFound.html"] + +["test_importResolveFailed.html"] + +["test_import_errorMessage.html"] + +["test_import_meta_resolve.html"] + +["test_importedModuleMemoization.html"] + +["test_linkErrorInCommon1.html"] + +["test_linkErrorInCommon2.html"] + +["test_moduleNotFound.html"] + +["test_moduleParsedAsModule.html"] + +["test_moduleScriptsRun.html"] + +["test_multiAsyncImports.html"] + +["test_multiModuleImports.html"] + +["test_multiModuleLargeImports.html"] + +["test_multiTopLevelImports.html"] + +["test_multiTopLevelLargeImports.html"] + +["test_scriptInsertedModule.html"] + +["test_scriptModuleOrder.html"] + +["test_scriptNotParsedAsModule.html"] + +["test_simpleImport.html"] + +["test_syntaxError.html"] + +["test_syntaxErrorAsync.html"] + +["test_syntaxErrorInline.html"] + +["test_syntaxErrorInlineAsync.html"] + +["test_topLevelIntroType.html"] + +["test_toplevelModuleMemoization.html"] + +["test_typeAttrCaseInsensitive.html"] diff --git a/dom/base/test/jsmodules/exportA1.mjs b/dom/base/test/jsmodules/exportA1.mjs new file mode 100644 index 0000000000..cc798ff50d --- /dev/null +++ b/dom/base/test/jsmodules/exportA1.mjs @@ -0,0 +1 @@ +export const a = 1; diff --git a/dom/base/test/jsmodules/exportA2.mjs b/dom/base/test/jsmodules/exportA2.mjs new file mode 100644 index 0000000000..66d48fc1e6 --- /dev/null +++ b/dom/base/test/jsmodules/exportA2.mjs @@ -0,0 +1 @@ +export const a = 2; diff --git a/dom/base/test/jsmodules/export_ambiguous.mjs b/dom/base/test/jsmodules/export_ambiguous.mjs new file mode 100644 index 0000000000..cca2dfd68a --- /dev/null +++ b/dom/base/test/jsmodules/export_ambiguous.mjs @@ -0,0 +1 @@ +export { a } from "./ambiguous_export.mjs"; diff --git a/dom/base/test/jsmodules/iframe_extractIntroType.html b/dom/base/test/jsmodules/iframe_extractIntroType.html new file mode 100644 index 0000000000..26c58aea6d --- /dev/null +++ b/dom/base/test/jsmodules/iframe_extractIntroType.html @@ -0,0 +1,14 @@ + + + + diff --git a/dom/base/test/jsmodules/import_ambiguous.mjs b/dom/base/test/jsmodules/import_ambiguous.mjs new file mode 100644 index 0000000000..f5c12ff086 --- /dev/null +++ b/dom/base/test/jsmodules/import_ambiguous.mjs @@ -0,0 +1 @@ +import { a } from "./ambiguous_export.mjs"; diff --git a/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs b/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs new file mode 100644 index 0000000000..bbf9375e49 --- /dev/null +++ b/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs @@ -0,0 +1 @@ +import { a } from "./export_ambiguous.mjs"; diff --git a/dom/base/test/jsmodules/import_no_export.mjs b/dom/base/test/jsmodules/import_no_export.mjs new file mode 100644 index 0000000000..47cabac557 --- /dev/null +++ b/dom/base/test/jsmodules/import_no_export.mjs @@ -0,0 +1 @@ +import x from "./no_export.mjs"; diff --git a/dom/base/test/jsmodules/import_no_indirect_export.mjs b/dom/base/test/jsmodules/import_no_indirect_export.mjs new file mode 100644 index 0000000000..dd1ca847fc --- /dev/null +++ b/dom/base/test/jsmodules/import_no_indirect_export.mjs @@ -0,0 +1,2 @@ +/* eslint-disable import/default */ +import x from "./no_indirect_export.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bad/module_2.mjs b/dom/base/test/jsmodules/importmaps/bad/module_2.mjs new file mode 100644 index 0000000000..86c4251413 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bad/module_2.mjs @@ -0,0 +1 @@ +throw "Shouldn't load file bad/module_2.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bad/module_3.mjs b/dom/base/test/jsmodules/importmaps/bad/module_3.mjs new file mode 100644 index 0000000000..f0595118d4 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bad/module_3.mjs @@ -0,0 +1,8 @@ +// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved +import {} from "../circular_depdendency.mjs"; + +export function exportedFunction() { + throw "Wrong version of function called"; +} + +throw "Shouldn't laod file bad/module_3.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bad/module_4.mjs b/dom/base/test/jsmodules/importmaps/bad/module_4.mjs new file mode 100644 index 0000000000..93dd8245ce --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bad/module_4.mjs @@ -0,0 +1 @@ +throw "Shouldn't load file bad/module_4.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bad/module_7.mjs b/dom/base/test/jsmodules/importmaps/bad/module_7.mjs new file mode 100644 index 0000000000..8844bf862c --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bad/module_7.mjs @@ -0,0 +1 @@ +throw "Shouldn't load file bad/module_7.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs b/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs new file mode 100644 index 0000000000..07d43d115e --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unassigned-import +import {} from "./bug_1865410_module_b.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs b/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs new file mode 100644 index 0000000000..2bd6dce476 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs @@ -0,0 +1 @@ +// Empty. diff --git a/dom/base/test/jsmodules/importmaps/bug_1873417.mjs b/dom/base/test/jsmodules/importmaps/bug_1873417.mjs new file mode 100644 index 0000000000..339e6acf91 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/bug_1873417.mjs @@ -0,0 +1,2 @@ +console.log("Module loaded successfully!"); +state = "loaded"; diff --git a/dom/base/test/jsmodules/importmaps/chrome.toml b/dom/base/test/jsmodules/importmaps/chrome.toml new file mode 100644 index 0000000000..0b8afe0f25 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/chrome.toml @@ -0,0 +1,37 @@ +[DEFAULT] +support-files = [ + "external_importMap.js", + "insert_a_base_element.js", + "module_simpleImportMap.mjs", + "module_simpleImportMap_dir.mjs", + "module_simpleImportMap_remap.mjs", + "module_simpleImportMap_remap_https.mjs", + "module_simpleExport.mjs", + "module_sortedImportMap.mjs", + "scope1/module_simpleExport.mjs", + "scope1/module_simpleImportMap.mjs", + "scope1/scope2/module_simpleExport.mjs", + "scope1/scope2/module_simpleImportMap.mjs", +] + +["test_dynamic_import_reject_importMap.html"] + +["test_externalImportMap.html"] + +["test_import_meta_resolve_importMap.html"] + +["test_inline_module_reject_importMap.html"] + +["test_load_importMap_with_base.html"] + +["test_load_importMap_with_base2.html"] + +["test_module_script_reject_importMap.html"] + +["test_parse_importMap_failed.html"] + +["test_reject_multiple_importMaps.html"] + +["test_simpleImportMap.html"] + +["test_sortedImportMap.html"] diff --git a/dom/base/test/jsmodules/importmaps/circular_dependency.mjs b/dom/base/test/jsmodules/importmaps/circular_dependency.mjs new file mode 100644 index 0000000000..f28d24b75e --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/circular_dependency.mjs @@ -0,0 +1,6 @@ +// Should be remapped to good/module_3.mjs. +import { exportedFunction } from "./bad/module_3.mjs"; + +if (exportedFunction()) { + success("circular_dependency.mjs"); +} diff --git a/dom/base/test/jsmodules/importmaps/external_importMap.js b/dom/base/test/jsmodules/importmaps/external_importMap.js new file mode 100644 index 0000000000..e89d9f618f --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/external_importMap.js @@ -0,0 +1,5 @@ +let imap = { + imports: { + foo: "./foo.js", + }, +}; diff --git a/dom/base/test/jsmodules/importmaps/good/module_0.mjs b/dom/base/test/jsmodules/importmaps/good/module_0.mjs new file mode 100644 index 0000000000..5c3c5e2ab1 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_0.mjs @@ -0,0 +1 @@ +success("good/module_0.mjs"); diff --git a/dom/base/test/jsmodules/importmaps/good/module_1.mjs b/dom/base/test/jsmodules/importmaps/good/module_1.mjs new file mode 100644 index 0000000000..9b902b266a --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_1.mjs @@ -0,0 +1 @@ +success("good/module_1.mjs"); diff --git a/dom/base/test/jsmodules/importmaps/good/module_2.mjs b/dom/base/test/jsmodules/importmaps/good/module_2.mjs new file mode 100644 index 0000000000..6756465905 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_2.mjs @@ -0,0 +1 @@ +success("good/module_2.mjs"); diff --git a/dom/base/test/jsmodules/importmaps/good/module_3.mjs b/dom/base/test/jsmodules/importmaps/good/module_3.mjs new file mode 100644 index 0000000000..95450e55f7 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_3.mjs @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-unassigned-import +import {} from "../circular_dependency.mjs"; + +export function exportedFunction() { + return true; +} diff --git a/dom/base/test/jsmodules/importmaps/good/module_4.mjs b/dom/base/test/jsmodules/importmaps/good/module_4.mjs new file mode 100644 index 0000000000..eaec9eb760 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_4.mjs @@ -0,0 +1 @@ +success("good/module_4.mjs"); diff --git a/dom/base/test/jsmodules/importmaps/good/module_7.mjs b/dom/base/test/jsmodules/importmaps/good/module_7.mjs new file mode 100644 index 0000000000..6603e1300d --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/good/module_7.mjs @@ -0,0 +1 @@ +success("good/module_7.mjs"); diff --git a/dom/base/test/jsmodules/importmaps/insert_a_base_element.js b/dom/base/test/jsmodules/importmaps/insert_a_base_element.js new file mode 100644 index 0000000000..435af97d1e --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/insert_a_base_element.js @@ -0,0 +1,4 @@ +const el = document.createElement("base"); +el.href = + "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/"; +document.currentScript.after(el); diff --git a/dom/base/test/jsmodules/importmaps/mochitest.toml b/dom/base/test/jsmodules/importmaps/mochitest.toml new file mode 100644 index 0000000000..4229455722 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/mochitest.toml @@ -0,0 +1,33 @@ +[DEFAULT] +support-files = [ + "bug_1865410_module_a.mjs", + "bug_1865410_module_b.mjs", + "bug_1873417.mjs", + "module_importMap_with_external_script_0.mjs", + "module_importMap_with_external_script_1.mjs", + "module_importMap_with_external_script_2.mjs", + "module_importMap_with_external_script_3.mjs", + "module_importMap_with_external_script_4.mjs", + "module_importMap_with_external_script_5.mjs", + "module_importMap_with_external_script_5.mjs^headers^", + "module_importMap_with_external_script_6.mjs", + "module_importMap_with_external_script_6.mjs^headers^", + "module_importMap_with_external_script_7.mjs", + "bad/module_2.mjs", + "bad/module_3.mjs", + "bad/module_4.mjs", + "bad/module_7.mjs", + "good/module_0.mjs", + "good/module_1.mjs", + "good/module_2.mjs", + "good/module_3.mjs", + "good/module_4.mjs", + "good/module_7.mjs", + "circular_dependency.mjs", +] + +["test_bug_1865410.html"] + +["test_bug_1873417.html"] + +["test_importMap_with_external_script.html"] diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs new file mode 100644 index 0000000000..e2ba9dee7e --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs @@ -0,0 +1,3 @@ +// Bareword specifier should be mapped to ./good/module_0.mjs. +// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved +import {} from "bare"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs new file mode 100644 index 0000000000..9d763a678f --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs @@ -0,0 +1,3 @@ +// Missing file ./bad/module_1.mjs should be mapped to ./good/module_1.mjs. +// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved +import {} from "./bad/module_1.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs new file mode 100644 index 0000000000..f0cb539a48 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_2.mjs should be mapped to ./good/module_2.mjs. +// eslint-disable-next-line import/no-unassigned-import +import {} from "./bad/module_2.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs new file mode 100644 index 0000000000..851f6dc3bc --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs. +// eslint-disable-next-line import/no-unassigned-import +import {} from "./bad/module_3.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs new file mode 100644 index 0000000000..8f46b73123 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_4.mjs should be mapped to ./good/module_4.mjs. +// eslint-disable-next-line import/no-unassigned-import +import {} from "./bad/module_4.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs new file mode 100644 index 0000000000..ac814c5e83 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs. +//import {} from "./bad/module_3.mjs"; +throw "Error: script_5.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^ new file mode 100644 index 0000000000..4cbbbc283d --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: module_importMap_with_external_script_4.mjs diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs new file mode 100644 index 0000000000..9e02aa6bf4 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs. +//import {} from "./bad/module_3.mjs"; +throw "Error: script_6.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^ new file mode 100644 index 0000000000..9f5e36c5a2 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: module_importMap_with_external_script_5.mjs diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs new file mode 100644 index 0000000000..b602217da5 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs @@ -0,0 +1,3 @@ +// Existing file ./bad/module_7.mjs should be mapped to ./good/module_4.mjs. +// eslint-disable-next-line import/no-unassigned-import +import {} from "./bad/module_7.mjs"; diff --git a/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs new file mode 100644 index 0000000000..9714d6d0ab --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs @@ -0,0 +1 @@ +export let x = 42; diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs new file mode 100644 index 0000000000..2f7e649dce --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "simple"; + +result = x; diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs new file mode 100644 index 0000000000..3a8a2a63b8 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "dir/module_simpleExport.mjs"; + +result_dir = x + 1; diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs new file mode 100644 index 0000000000..54d22e5a5c --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "./module.mjs"; + +result_remap = x + 2; diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs new file mode 100644 index 0000000000..d9b82243b7 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "https://example.com/module.mjs"; + +result_remap_https = x + 3; diff --git a/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs new file mode 100644 index 0000000000..2b199ca272 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs @@ -0,0 +1,6 @@ +/* eslint-disable import/no-unresolved */ +import { x } from "scope1/scope2/module_simpleExport.mjs"; +import { x as y } from "scope1/scope2/scope3/scope4/module_simpleExport.mjs"; + +sorted_result = x; +sorted_result2 = y; diff --git a/dom/base/test/jsmodules/importmaps/moz.build b/dom/base/test/jsmodules/importmaps/moz.build new file mode 100644 index 0000000000..ca4ef002b0 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/moz.build @@ -0,0 +1,9 @@ +# -*- 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/. + +MOCHITEST_CHROME_MANIFESTS += ["chrome.toml"] + +MOCHITEST_MANIFESTS += ["mochitest.toml"] diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs new file mode 100644 index 0000000000..e6b0ed1c0c --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs @@ -0,0 +1 @@ +export let x = 84; diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs new file mode 100644 index 0000000000..a64a098b7b --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "simple"; + +result_scope1 = x; diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs new file mode 100644 index 0000000000..ba2bbae16b --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs @@ -0,0 +1 @@ +export let x = 126; diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs new file mode 100644 index 0000000000..00819aefd1 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/no-unresolved +import { x } from "simple"; + +result_scope2 = x; diff --git a/dom/base/test/jsmodules/importmaps/test_bug_1865410.html b/dom/base/test/jsmodules/importmaps/test_bug_1865410.html new file mode 100644 index 0000000000..a59aba368d --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_bug_1865410.html @@ -0,0 +1,27 @@ + + +Bug 1865410: Test interaction between speculative preload and import maps + + + + + +
                      + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_bug_1873417.html b/dom/base/test/jsmodules/importmaps/test_bug_1873417.html new file mode 100644 index 0000000000..9ae689be3b --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_bug_1873417.html @@ -0,0 +1,39 @@ + + +Bug 1873417: Test if import-maps will block module script execution + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html new file mode 100644 index 0000000000..96744c9317 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html @@ -0,0 +1,46 @@ + + + + Test import map should be rejected. + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_externalImportMap.html b/dom/base/test/jsmodules/importmaps/test_externalImportMap.html new file mode 100644 index 0000000000..1345f61947 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_externalImportMap.html @@ -0,0 +1,43 @@ + + +Test an external import map + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html b/dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html new file mode 100644 index 0000000000..3b21003feb --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html @@ -0,0 +1,75 @@ + + + +Test speculative preload of external script doesn't conflict with import map + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html b/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html new file mode 100644 index 0000000000..5c81dd548e --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html @@ -0,0 +1,49 @@ + + + + Test import.meta.resolve with import maps + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html new file mode 100644 index 0000000000..458601619a --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html @@ -0,0 +1,61 @@ + + + + Test import map should be rejected. + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html new file mode 100644 index 0000000000..531431fcf0 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html @@ -0,0 +1,51 @@ + + + + Test a simple import map with a base element + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html new file mode 100644 index 0000000000..7ab3fe96da --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html @@ -0,0 +1,51 @@ + + + + Test a simple import map with a script creates a base element + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html new file mode 100644 index 0000000000..88db016e3d --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html @@ -0,0 +1,45 @@ + + + + Test import map should be rejected. + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html b/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html new file mode 100644 index 0000000000..b304acd943 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html @@ -0,0 +1,40 @@ + + + + Test the error message when parsing import maps failed + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html b/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html new file mode 100644 index 0000000000..2a3498094c --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html @@ -0,0 +1,64 @@ + + + + Test the 2nd import map should be rejected. + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html b/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html new file mode 100644 index 0000000000..5323da31a9 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html @@ -0,0 +1,62 @@ + + +Test a simple import map + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html b/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html new file mode 100644 index 0000000000..f4b98fdf10 --- /dev/null +++ b/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html @@ -0,0 +1,62 @@ + + +Test a sorted import map + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/module_badImport.mjs b/dom/base/test/jsmodules/module_badImport.mjs new file mode 100644 index 0000000000..9d72b27c43 --- /dev/null +++ b/dom/base/test/jsmodules/module_badImport.mjs @@ -0,0 +1,2 @@ +/* eslint-disable import/no-unassigned-import, import/no-unresolved */ +import "invalid specifier"; diff --git a/dom/base/test/jsmodules/module_badSyntax.mjs b/dom/base/test/jsmodules/module_badSyntax.mjs new file mode 100644 index 0000000000..744158108c --- /dev/null +++ b/dom/base/test/jsmodules/module_badSyntax.mjs @@ -0,0 +1,3 @@ +// Module with a syntax error. +some invalid js syntax; +wasRun = true; diff --git a/dom/base/test/jsmodules/module_cyclic1.mjs b/dom/base/test/jsmodules/module_cyclic1.mjs new file mode 100644 index 0000000000..197a94989a --- /dev/null +++ b/dom/base/test/jsmodules/module_cyclic1.mjs @@ -0,0 +1,8 @@ +import { func2 } from "./module_cyclic2.mjs"; + +export function func1(x, y) { + if (x <= 0) { + return y; + } + return func2(x - 1, y + "1"); +} diff --git a/dom/base/test/jsmodules/module_cyclic2.mjs b/dom/base/test/jsmodules/module_cyclic2.mjs new file mode 100644 index 0000000000..7ecec80c65 --- /dev/null +++ b/dom/base/test/jsmodules/module_cyclic2.mjs @@ -0,0 +1,8 @@ +import { func3 } from "./module_cyclic3.mjs"; + +export function func2(x, y) { + if (x <= 0) { + return y; + } + return func3(x - 1, y + "2"); +} diff --git a/dom/base/test/jsmodules/module_cyclic3.mjs b/dom/base/test/jsmodules/module_cyclic3.mjs new file mode 100644 index 0000000000..9458391d2e --- /dev/null +++ b/dom/base/test/jsmodules/module_cyclic3.mjs @@ -0,0 +1,8 @@ +import { func1 } from "./module_cyclic1.mjs"; + +export function func3(x, y) { + if (x <= 0) { + return y; + } + return func1(x - 1, y + "3"); +} diff --git a/dom/base/test/jsmodules/module_extractIntroType.mjs b/dom/base/test/jsmodules/module_extractIntroType.mjs new file mode 100644 index 0000000000..a5daa8f0ef --- /dev/null +++ b/dom/base/test/jsmodules/module_extractIntroType.mjs @@ -0,0 +1,6 @@ +// Extract the introductionType for this module in conjunction with +// iframe_extractIntroType.html. +extractIntroType = function () { + // eslint-disable-next-line no-debugger + debugger; +}; diff --git a/dom/base/test/jsmodules/module_large1.mjs b/dom/base/test/jsmodules/module_large1.mjs new file mode 100644 index 0000000000..d6933d298d --- /dev/null +++ b/dom/base/test/jsmodules/module_large1.mjs @@ -0,0 +1,78 @@ +/* + * Scripts larger than 5KB may be compiled off main thread. This is such a + * script. + * + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + */ + +results.push(1); diff --git a/dom/base/test/jsmodules/module_large2.mjs b/dom/base/test/jsmodules/module_large2.mjs new file mode 100644 index 0000000000..e1b6da4c91 --- /dev/null +++ b/dom/base/test/jsmodules/module_large2.mjs @@ -0,0 +1,78 @@ +/* + * Scripts larger than 5KB may be compiled off main thread. This is such a + * script. + * + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + */ + +results.push(2); diff --git a/dom/base/test/jsmodules/module_large3.mjs b/dom/base/test/jsmodules/module_large3.mjs new file mode 100644 index 0000000000..c966a8eb20 --- /dev/null +++ b/dom/base/test/jsmodules/module_large3.mjs @@ -0,0 +1,78 @@ +/* + * Scripts larger than 5KB may be compiled off main thread. This is such a + * script. + * + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + * large large large large large large large large large large large large + */ + +results.push(3); diff --git a/dom/base/test/jsmodules/module_missingImport.mjs b/dom/base/test/jsmodules/module_missingImport.mjs new file mode 100644 index 0000000000..3b2ee2bc73 --- /dev/null +++ b/dom/base/test/jsmodules/module_missingImport.mjs @@ -0,0 +1 @@ +import { missing } from "./module_simple1.mjs"; diff --git a/dom/base/test/jsmodules/module_multiImports.mjs b/dom/base/test/jsmodules/module_multiImports.mjs new file mode 100644 index 0000000000..9fe9516f92 --- /dev/null +++ b/dom/base/test/jsmodules/module_multiImports.mjs @@ -0,0 +1,6 @@ +/* eslint-disable import/no-unassigned-import */ +import "./module_simple1.mjs"; +import "./module_simple2.mjs"; +import "./module_simple3.mjs"; + +results.push(4); diff --git a/dom/base/test/jsmodules/module_multiLargeImports.mjs b/dom/base/test/jsmodules/module_multiLargeImports.mjs new file mode 100644 index 0000000000..c4f32baf4e --- /dev/null +++ b/dom/base/test/jsmodules/module_multiLargeImports.mjs @@ -0,0 +1,6 @@ +/* eslint-disable import/no-unassigned-import */ +import "./module_large1.mjs"; +import "./module_large2.mjs"; +import "./module_large3.mjs"; + +results.push(4); diff --git a/dom/base/test/jsmodules/module_setRan.mjs b/dom/base/test/jsmodules/module_setRan.mjs new file mode 100644 index 0000000000..4804382fdd --- /dev/null +++ b/dom/base/test/jsmodules/module_setRan.mjs @@ -0,0 +1,2 @@ +// Set a global flag to indicate that this module was executed. +moduleRan = true; diff --git a/dom/base/test/jsmodules/module_simple1.mjs b/dom/base/test/jsmodules/module_simple1.mjs new file mode 100644 index 0000000000..7594ac699e --- /dev/null +++ b/dom/base/test/jsmodules/module_simple1.mjs @@ -0,0 +1 @@ +results.push(1); diff --git a/dom/base/test/jsmodules/module_simple2.mjs b/dom/base/test/jsmodules/module_simple2.mjs new file mode 100644 index 0000000000..f92a1c9d6e --- /dev/null +++ b/dom/base/test/jsmodules/module_simple2.mjs @@ -0,0 +1 @@ +results.push(2); diff --git a/dom/base/test/jsmodules/module_simple3.mjs b/dom/base/test/jsmodules/module_simple3.mjs new file mode 100644 index 0000000000..71979926e6 --- /dev/null +++ b/dom/base/test/jsmodules/module_simple3.mjs @@ -0,0 +1 @@ +results.push(3); diff --git a/dom/base/test/jsmodules/module_simpleExport.mjs b/dom/base/test/jsmodules/module_simpleExport.mjs new file mode 100644 index 0000000000..9714d6d0ab --- /dev/null +++ b/dom/base/test/jsmodules/module_simpleExport.mjs @@ -0,0 +1 @@ +export let x = 42; diff --git a/dom/base/test/jsmodules/module_simpleImport.mjs b/dom/base/test/jsmodules/module_simpleImport.mjs new file mode 100644 index 0000000000..7a9d05325b --- /dev/null +++ b/dom/base/test/jsmodules/module_simpleImport.mjs @@ -0,0 +1,3 @@ +import { x } from "./module_simpleExport.mjs"; + +result = x; diff --git a/dom/base/test/jsmodules/module_testSyntax.mjs b/dom/base/test/jsmodules/module_testSyntax.mjs new file mode 100644 index 0000000000..3d647ae0b4 --- /dev/null +++ b/dom/base/test/jsmodules/module_testSyntax.mjs @@ -0,0 +1,3 @@ +// Module that throws a syntax error if parsed as a script. +export default 1; +wasRun = true; diff --git a/dom/base/test/jsmodules/moz.build b/dom/base/test/jsmodules/moz.build new file mode 100644 index 0000000000..36ed046708 --- /dev/null +++ b/dom/base/test/jsmodules/moz.build @@ -0,0 +1,7 @@ +# -*- 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/. + +MOCHITEST_CHROME_MANIFESTS += ["chrome.toml"] diff --git a/dom/base/test/jsmodules/no_export.mjs b/dom/base/test/jsmodules/no_export.mjs new file mode 100644 index 0000000000..7d519cc264 --- /dev/null +++ b/dom/base/test/jsmodules/no_export.mjs @@ -0,0 +1 @@ +const y = 1; diff --git a/dom/base/test/jsmodules/no_indirect_export.mjs b/dom/base/test/jsmodules/no_indirect_export.mjs new file mode 100644 index 0000000000..1fcc87bf88 --- /dev/null +++ b/dom/base/test/jsmodules/no_indirect_export.mjs @@ -0,0 +1 @@ +export { a } from "./no_export.mjs"; diff --git a/dom/base/test/jsmodules/script_simple2.js b/dom/base/test/jsmodules/script_simple2.js new file mode 100644 index 0000000000..f92a1c9d6e --- /dev/null +++ b/dom/base/test/jsmodules/script_simple2.js @@ -0,0 +1 @@ +results.push(2); diff --git a/dom/base/test/jsmodules/test_asyncInlineModules.html b/dom/base/test/jsmodules/test_asyncInlineModules.html new file mode 100644 index 0000000000..47df5f1d03 --- /dev/null +++ b/dom/base/test/jsmodules/test_asyncInlineModules.html @@ -0,0 +1,36 @@ + + +Test async inline modules + + + + + + diff --git a/dom/base/test/jsmodules/test_cyclicImport.html b/dom/base/test/jsmodules/test_cyclicImport.html new file mode 100644 index 0000000000..8fb78c4f93 --- /dev/null +++ b/dom/base/test/jsmodules/test_cyclicImport.html @@ -0,0 +1,18 @@ + + +Test cyclic module imports + + + + diff --git a/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html b/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html new file mode 100644 index 0000000000..f5552d5a6b --- /dev/null +++ b/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html @@ -0,0 +1,16 @@ + + +Test the error message from import() + + + diff --git a/dom/base/test/jsmodules/test_importIntroType.html b/dom/base/test/jsmodules/test_importIntroType.html new file mode 100644 index 0000000000..f08aea1925 --- /dev/null +++ b/dom/base/test/jsmodules/test_importIntroType.html @@ -0,0 +1,22 @@ + + +Test introduction type of an imported module + + + + + diff --git a/dom/base/test/jsmodules/test_importNotFound.html b/dom/base/test/jsmodules/test_importNotFound.html new file mode 100644 index 0000000000..aac2f58bb5 --- /dev/null +++ b/dom/base/test/jsmodules/test_importNotFound.html @@ -0,0 +1,27 @@ + + +Test what happens when a module import is not found + + + + diff --git a/dom/base/test/jsmodules/test_importResolveFailed.html b/dom/base/test/jsmodules/test_importResolveFailed.html new file mode 100644 index 0000000000..8b15a1762a --- /dev/null +++ b/dom/base/test/jsmodules/test_importResolveFailed.html @@ -0,0 +1,21 @@ + + +Test error thrown when an import cannot be resolved + + + + diff --git a/dom/base/test/jsmodules/test_import_errorMessage.html b/dom/base/test/jsmodules/test_import_errorMessage.html new file mode 100644 index 0000000000..6ab0b1dd74 --- /dev/null +++ b/dom/base/test/jsmodules/test_import_errorMessage.html @@ -0,0 +1,47 @@ + + +Test module import error message + + + + + + + + + diff --git a/dom/base/test/jsmodules/test_import_meta_resolve.html b/dom/base/test/jsmodules/test_import_meta_resolve.html new file mode 100644 index 0000000000..66eedc95bc --- /dev/null +++ b/dom/base/test/jsmodules/test_import_meta_resolve.html @@ -0,0 +1,65 @@ + + + + Test import.meta.resolve + + + + + + + + + + + + + + + + + + diff --git a/dom/base/test/jsmodules/test_importedModuleMemoization.html b/dom/base/test/jsmodules/test_importedModuleMemoization.html new file mode 100644 index 0000000000..df7686fb70 --- /dev/null +++ b/dom/base/test/jsmodules/test_importedModuleMemoization.html @@ -0,0 +1,30 @@ + + +Test imported modules are momoized and only loaded once + + + + + + diff --git a/dom/base/test/jsmodules/test_linkErrorInCommon1.html b/dom/base/test/jsmodules/test_linkErrorInCommon1.html new file mode 100644 index 0000000000..251b96d367 --- /dev/null +++ b/dom/base/test/jsmodules/test_linkErrorInCommon1.html @@ -0,0 +1,32 @@ + + +Test handling of a link error in a common module + + + + + diff --git a/dom/base/test/jsmodules/test_linkErrorInCommon2.html b/dom/base/test/jsmodules/test_linkErrorInCommon2.html new file mode 100644 index 0000000000..77f0bab0b9 --- /dev/null +++ b/dom/base/test/jsmodules/test_linkErrorInCommon2.html @@ -0,0 +1,32 @@ + + +Test handling of a link error in a common module + + + + + diff --git a/dom/base/test/jsmodules/test_moduleNotFound.html b/dom/base/test/jsmodules/test_moduleNotFound.html new file mode 100644 index 0000000000..d8662c9494 --- /dev/null +++ b/dom/base/test/jsmodules/test_moduleNotFound.html @@ -0,0 +1,24 @@ + + +Test what happens when a top-level module is not found + + + + diff --git a/dom/base/test/jsmodules/test_moduleParsedAsModule.html b/dom/base/test/jsmodules/test_moduleParsedAsModule.html new file mode 100644 index 0000000000..33000271dc --- /dev/null +++ b/dom/base/test/jsmodules/test_moduleParsedAsModule.html @@ -0,0 +1,23 @@ + + +Test module script parsed as module + + + + diff --git a/dom/base/test/jsmodules/test_moduleScriptsRun.html b/dom/base/test/jsmodules/test_moduleScriptsRun.html new file mode 100644 index 0000000000..193b5ba386 --- /dev/null +++ b/dom/base/test/jsmodules/test_moduleScriptsRun.html @@ -0,0 +1,19 @@ + + +Test script elements with type="module" are run for chrome HTML + + + + + diff --git a/dom/base/test/jsmodules/test_multiAsyncImports.html b/dom/base/test/jsmodules/test_multiAsyncImports.html new file mode 100644 index 0000000000..07d9776b82 --- /dev/null +++ b/dom/base/test/jsmodules/test_multiAsyncImports.html @@ -0,0 +1,30 @@ + + +Test a loading multiple modules with the async attribute from top level + + + + + + diff --git a/dom/base/test/jsmodules/test_multiModuleImports.html b/dom/base/test/jsmodules/test_multiModuleImports.html new file mode 100644 index 0000000000..924b3bce55 --- /dev/null +++ b/dom/base/test/jsmodules/test_multiModuleImports.html @@ -0,0 +1,28 @@ + + +Test a importing multiple modules from a module + + + + diff --git a/dom/base/test/jsmodules/test_multiModuleLargeImports.html b/dom/base/test/jsmodules/test_multiModuleLargeImports.html new file mode 100644 index 0000000000..2e788e1469 --- /dev/null +++ b/dom/base/test/jsmodules/test_multiModuleLargeImports.html @@ -0,0 +1,28 @@ + + +Test importing multiple large modules which may be compiled off main thread from a module + + + + diff --git a/dom/base/test/jsmodules/test_multiTopLevelImports.html b/dom/base/test/jsmodules/test_multiTopLevelImports.html new file mode 100644 index 0000000000..1e4652e827 --- /dev/null +++ b/dom/base/test/jsmodules/test_multiTopLevelImports.html @@ -0,0 +1,30 @@ + + +Test importing multiple modules from top level + + + + + + diff --git a/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html b/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html new file mode 100644 index 0000000000..3ec7241061 --- /dev/null +++ b/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html @@ -0,0 +1,30 @@ + + +Test a importing large modules which may be compiled off main thread + + + + + + diff --git a/dom/base/test/jsmodules/test_scriptInsertedModule.html b/dom/base/test/jsmodules/test_scriptInsertedModule.html new file mode 100644 index 0000000000..09a03f3186 --- /dev/null +++ b/dom/base/test/jsmodules/test_scriptInsertedModule.html @@ -0,0 +1,20 @@ + + +Test a script-inserted module + + + diff --git a/dom/base/test/jsmodules/test_scriptModuleOrder.html b/dom/base/test/jsmodules/test_scriptModuleOrder.html new file mode 100644 index 0000000000..bec30a3350 --- /dev/null +++ b/dom/base/test/jsmodules/test_scriptModuleOrder.html @@ -0,0 +1,30 @@ + + +Test execution order of deferred scripts and modules + + + + + + diff --git a/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html b/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html new file mode 100644 index 0000000000..dbad1bc722 --- /dev/null +++ b/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html @@ -0,0 +1,23 @@ + + +Test classic script not parsed as module + + + + diff --git a/dom/base/test/jsmodules/test_simpleImport.html b/dom/base/test/jsmodules/test_simpleImport.html new file mode 100644 index 0000000000..21d02fdb90 --- /dev/null +++ b/dom/base/test/jsmodules/test_simpleImport.html @@ -0,0 +1,16 @@ + + +Test a simple module import + + + + diff --git a/dom/base/test/jsmodules/test_syntaxError.html b/dom/base/test/jsmodules/test_syntaxError.html new file mode 100644 index 0000000000..c35179579b --- /dev/null +++ b/dom/base/test/jsmodules/test_syntaxError.html @@ -0,0 +1,30 @@ + + +Test syntax errors parsing a module are reported + + + + diff --git a/dom/base/test/jsmodules/test_syntaxErrorAsync.html b/dom/base/test/jsmodules/test_syntaxErrorAsync.html new file mode 100644 index 0000000000..fedf7c1d5c --- /dev/null +++ b/dom/base/test/jsmodules/test_syntaxErrorAsync.html @@ -0,0 +1,30 @@ + + +Test syntax errors parsing an async module are reported + + + + diff --git a/dom/base/test/jsmodules/test_syntaxErrorInline.html b/dom/base/test/jsmodules/test_syntaxErrorInline.html new file mode 100644 index 0000000000..4960f5358a --- /dev/null +++ b/dom/base/test/jsmodules/test_syntaxErrorInline.html @@ -0,0 +1,34 @@ + + +Test syntax errors parsing an inline module are reported + + + + diff --git a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html new file mode 100644 index 0000000000..39b8a7354d --- /dev/null +++ b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html @@ -0,0 +1,34 @@ + + +Test syntax errors parsing an inline async module are reported + + + + diff --git a/dom/base/test/jsmodules/test_topLevelIntroType.html b/dom/base/test/jsmodules/test_topLevelIntroType.html new file mode 100644 index 0000000000..2cc7c12e09 --- /dev/null +++ b/dom/base/test/jsmodules/test_topLevelIntroType.html @@ -0,0 +1,21 @@ + + +Test introduction type of a top-level module + + + + + diff --git a/dom/base/test/jsmodules/test_toplevelModuleMemoization.html b/dom/base/test/jsmodules/test_toplevelModuleMemoization.html new file mode 100644 index 0000000000..0f1d57c6eb --- /dev/null +++ b/dom/base/test/jsmodules/test_toplevelModuleMemoization.html @@ -0,0 +1,30 @@ + + +Test toplevel modules are momoized and only loaded once + + + + + + diff --git a/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html b/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html new file mode 100644 index 0000000000..106e0f9522 --- /dev/null +++ b/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html @@ -0,0 +1,19 @@ + + +Test script element's type attribute comparision is case-insensitive + + + + + diff --git a/dom/base/test/meta_viewport/mochitest.toml b/dom/base/test/meta_viewport/mochitest.toml new file mode 100644 index 0000000000..8d7c1a8d38 --- /dev/null +++ b/dom/base/test/meta_viewport/mochitest.toml @@ -0,0 +1,102 @@ +[DEFAULT] +support-files = ["viewport_helpers.js"] + +["test_meta_viewport0.html"] + +["test_meta_viewport1.html"] + +["test_meta_viewport2.html"] + +["test_meta_viewport3.html"] + +["test_meta_viewport4.html"] + +["test_meta_viewport5.html"] + +["test_meta_viewport6.html"] + +["test_meta_viewport7.html"] + +["test_meta_viewport8.html"] + +["test_meta_viewport_auto_size_by_device_height.html"] + +["test_meta_viewport_auto_size_by_device_width.html"] + +["test_meta_viewport_auto_size_by_fixed_height_and_initial_scale_1.html"] + +["test_meta_viewport_auto_size_by_fixed_width_and_device_height.html"] + +["test_meta_viewport_auto_size_by_fixed_width_and_initial_scale_1.html"] + +["test_meta_viewport_auto_size_by_initial_scale_0_5.html"] + +["test_meta_viewport_auto_size_by_initial_scale_1.html"] + +["test_meta_viewport_auto_size_by_invalid_width.html"] + +["test_meta_viewport_auto_size_by_invalid_width_and_fixed_height.html"] + +["test_meta_viewport_change_content_among_multiple.html"] + +["test_meta_viewport_change_name.html"] + +["test_meta_viewport_change_name_among_multiple.html"] + +["test_meta_viewport_device_width.html"] + +["test_meta_viewport_device_width_with_initial_scale_0_5.html"] + +["test_meta_viewport_device_width_with_initial_scale_2.html"] + +["test_meta_viewport_empty_content_and_valid_content_tags.html"] + +["test_meta_viewport_fit.html"] + +["test_meta_viewport_fit_multiple.html"] + +["test_meta_viewport_fixed_width_and_zero_display_width.html"] + +["test_meta_viewport_initial_scale_0_5.html"] + +["test_meta_viewport_initial_scale_2.html"] + +["test_meta_viewport_initial_scale_with_trailing_characters.html"] + +["test_meta_viewport_insert_before_existing_tag.html"] + +["test_meta_viewport_maximum_scale_0.html"] + +["test_meta_viewport_maximum_scale_0_5.html"] + +["test_meta_viewport_maximum_scale_2.html"] + +["test_meta_viewport_multiple_tags.html"] + +["test_meta_viewport_negative_width_and_negative_height.html"] + +["test_meta_viewport_negative_width_and_no_height.html"] + +["test_meta_viewport_negative_width_and_valid_height.html"] + +["test_meta_viewport_no_content_and_valid_content_tags.html"] + +["test_meta_viewport_no_width_and_negative_height.html"] + +["test_meta_viewport_no_width_and_valid_height.html"] + +["test_meta_viewport_remove_node.html"] + +["test_meta_viewport_remove_node_from_multiple.html"] + +["test_meta_viewport_removing_content_attribute.html"] + +["test_meta_viewport_replace_content.html"] + +["test_meta_viewport_tiny_display_size.html"] + +["test_meta_viewport_valid_width_and_negative_height.html"] + +["test_meta_viewport_valid_width_and_no_height.html"] + +["test_meta_viewport_width_with_trailing_characters.html"] diff --git a/dom/base/test/meta_viewport/moz.build b/dom/base/test/meta_viewport/moz.build new file mode 100644 index 0000000000..3ef5d9c8cd --- /dev/null +++ b/dom/base/test/meta_viewport/moz.build @@ -0,0 +1,9 @@ +# -*- 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/. + +MOCHITEST_MANIFESTS += [ + "mochitest.toml", +] diff --git a/dom/base/test/meta_viewport/test_meta_viewport0.html b/dom/base/test/meta_viewport/test_meta_viewport0.html new file mode 100644 index 0000000000..8fef72c578 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport0.html @@ -0,0 +1,41 @@ + + + + + meta viewport test + + + + + +

                      No <meta name="viewport"> tag

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport1.html b/dom/base/test/meta_viewport/test_meta_viewport1.html new file mode 100644 index 0000000000..66dd02461e --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport1.html @@ -0,0 +1,41 @@ + + + + + meta viewport test + + + + + + +

                      width=device-width, initial-scale=1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport2.html b/dom/base/test/meta_viewport/test_meta_viewport2.html new file mode 100644 index 0000000000..e0f45813be --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport2.html @@ -0,0 +1,41 @@ + + + + + meta viewport test + + + + + + +

                      width=device-width

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport3.html b/dom/base/test/meta_viewport/test_meta_viewport3.html new file mode 100644 index 0000000000..32464bd126 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport3.html @@ -0,0 +1,43 @@ + + + + + meta viewport test + + + + + + +

                      width=320

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport4.html b/dom/base/test/meta_viewport/test_meta_viewport4.html new file mode 100644 index 0000000000..bc7f7ada55 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport4.html @@ -0,0 +1,42 @@ + + + + + meta viewport test + + + + + + +

                      initial-scale=1.0, user-scalable=no

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport5.html b/dom/base/test/meta_viewport/test_meta_viewport5.html new file mode 100644 index 0000000000..938cc052ee --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport5.html @@ -0,0 +1,24 @@ + + + + + meta viewport test + + + + + + +

                      user-scalable=NO

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport6.html b/dom/base/test/meta_viewport/test_meta_viewport6.html new file mode 100644 index 0000000000..e3ca1b72aa --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport6.html @@ -0,0 +1,47 @@ + + + + + meta viewport test + + + + + + +

                      width=2000, minimum-scale=0.75

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport7.html b/dom/base/test/meta_viewport/test_meta_viewport7.html new file mode 100644 index 0000000000..1f40c27109 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport7.html @@ -0,0 +1,71 @@ + + + + + meta viewport test + + + + + + +

                      Dynamic viewport updates

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport8.html b/dom/base/test/meta_viewport/test_meta_viewport8.html new file mode 100644 index 0000000000..4c711c9cc6 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport8.html @@ -0,0 +1,27 @@ + + + + + meta viewport test + + + + + + +

                      minimum-scale=0.01

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_height.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_height.html new file mode 100644 index 0000000000..1b6c35a602 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_height.html @@ -0,0 +1,24 @@ + + + + + device-height enables autoSize + + + + + + +

                      height=device-height

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_width.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_width.html new file mode 100644 index 0000000000..fb91f2e50c --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_device_width.html @@ -0,0 +1,24 @@ + + + + + device-width enables autoSize + + + + + + +

                      width=device-width

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_height_and_initial_scale_1.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_height_and_initial_scale_1.html new file mode 100644 index 0000000000..83346f4924 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_height_and_initial_scale_1.html @@ -0,0 +1,25 @@ + + + + + initial-scale=1 with fixed height enable autoSize + + + + + + +

                      height=400, initial-scale=1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_device_height.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_device_height.html new file mode 100644 index 0000000000..e570f80644 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_device_height.html @@ -0,0 +1,25 @@ + + + + + Fixed width and device-height disables autoSize + + + + + + +

                      width=400, height=device-height

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_initial_scale_1.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_initial_scale_1.html new file mode 100644 index 0000000000..4453b4c959 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_fixed_width_and_initial_scale_1.html @@ -0,0 +1,25 @@ + + + + + initial-scale=1 with fixed width disables autoSize + + + + + + +

                      width=400, initial-scale=1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_0_5.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_0_5.html new file mode 100644 index 0000000000..ff12b22454 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_0_5.html @@ -0,0 +1,25 @@ + + + + + initial-scale!=1 without width disables autoSize + + + + + + +

                      initial-scale!=1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_1.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_1.html new file mode 100644 index 0000000000..e86742b8f2 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_initial_scale_1.html @@ -0,0 +1,25 @@ + + + + + initial-scale=1 without width enables autoSize + + + + + + +

                      initial-scale=1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width.html new file mode 100644 index 0000000000..6c950185bc --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width.html @@ -0,0 +1,24 @@ + + + + + invalid width enables autoSize + + + + + + +

                      width=-1

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width_and_fixed_height.html b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width_and_fixed_height.html new file mode 100644 index 0000000000..db68ecb6ec --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_auto_size_by_invalid_width_and_fixed_height.html @@ -0,0 +1,25 @@ + + + + + invalid width but with fixed height disables autoSize + + + + + + +

                      width=-1,height=200

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_change_content_among_multiple.html b/dom/base/test/meta_viewport/test_meta_viewport_change_content_among_multiple.html new file mode 100644 index 0000000000..8ec88b8920 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_change_content_among_multiple.html @@ -0,0 +1,52 @@ + + + + + content attribute changes among multiple meta viewport tags + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_change_name.html b/dom/base/test/meta_viewport/test_meta_viewport_change_name.html new file mode 100644 index 0000000000..84b9c321df --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_change_name.html @@ -0,0 +1,47 @@ + + + + + name attribute changes + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_change_name_among_multiple.html b/dom/base/test/meta_viewport/test_meta_viewport_change_name_among_multiple.html new file mode 100644 index 0000000000..ca41577bbe --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_change_name_among_multiple.html @@ -0,0 +1,44 @@ + + + + + name attribute changes among multiple meta viewport tags + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_device_width.html b/dom/base/test/meta_viewport/test_meta_viewport_device_width.html new file mode 100644 index 0000000000..0e1f2f1dac --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_device_width.html @@ -0,0 +1,25 @@ + + + + + device-width in meta viewport + + + + + + +

                      width=device-width

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_0_5.html b/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_0_5.html new file mode 100644 index 0000000000..fc3192c854 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_0_5.html @@ -0,0 +1,26 @@ + + + + + device-width with initial-scale=0.5 in meta viewport + + + + + + +

                      width=device-width, initial-scale=0.5

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_2.html b/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_2.html new file mode 100644 index 0000000000..e701266e60 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_device_width_with_initial_scale_2.html @@ -0,0 +1,31 @@ + + + + + device-width with initial-scale=2 in meta viewport + + + + + + +

                      width=device-width, initial-scale=2

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_empty_content_and_valid_content_tags.html b/dom/base/test/meta_viewport/test_meta_viewport_empty_content_and_valid_content_tags.html new file mode 100644 index 0000000000..6de2e08c40 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_empty_content_and_valid_content_tags.html @@ -0,0 +1,26 @@ + + + + + a valid meta viewport tag and empty content attribute viewport tag + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_fit.html b/dom/base/test/meta_viewport/test_meta_viewport_fit.html new file mode 100644 index 0000000000..e86ad817d6 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_fit.html @@ -0,0 +1,34 @@ + + + + + meta viewport viewport-fit test + + + + + + +

                      viewport-fit=cover

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_fit_multiple.html b/dom/base/test/meta_viewport/test_meta_viewport_fit_multiple.html new file mode 100644 index 0000000000..e204bb70f6 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_fit_multiple.html @@ -0,0 +1,25 @@ + + + + + multiple meta viewport viewport-fit test + + + + + + + +

                      viewport-fit=cover

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_fixed_width_and_zero_display_width.html b/dom/base/test/meta_viewport/test_meta_viewport_fixed_width_and_zero_display_width.html new file mode 100644 index 0000000000..e649ad9fcd --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_fixed_width_and_zero_display_width.html @@ -0,0 +1,29 @@ + + + + + Fixed meta viewport width, zero display width + + + + + + +

                      Fixed meta viewport width, zero display width

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_0_5.html b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_0_5.html new file mode 100644 index 0000000000..99fb5c1d36 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_0_5.html @@ -0,0 +1,33 @@ + + + + + initial-scale=0.5 in meta viewport + + + + + + +

                      initial-scale=0.5

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_2.html b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_2.html new file mode 100644 index 0000000000..22f0adc061 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_2.html @@ -0,0 +1,26 @@ + + + + + initial-scale=2 in meta viewport + + + + + + +

                      initial-scale=2

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_with_trailing_characters.html b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_with_trailing_characters.html new file mode 100644 index 0000000000..5939691cb5 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_initial_scale_with_trailing_characters.html @@ -0,0 +1,26 @@ + + + + + initial-scale with trailing characters in meta viewport + + + + + + +

                      initial-scale=1.0/

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_insert_before_existing_tag.html b/dom/base/test/meta_viewport/test_meta_viewport_insert_before_existing_tag.html new file mode 100644 index 0000000000..e2162c81f8 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_insert_before_existing_tag.html @@ -0,0 +1,32 @@ + + + + + interting a meta viewport tag before existing one + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0.html b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0.html new file mode 100644 index 0000000000..893f3128d9 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0.html @@ -0,0 +1,28 @@ + + + + + meta viewport test + + + + + + +

                      width=device-width, minimum-scale=1, maximum-scale=0

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0_5.html b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0_5.html new file mode 100644 index 0000000000..7f17ef146e --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_0_5.html @@ -0,0 +1,29 @@ + + + + + maximum-scale=0.5 in meta viewport + + + + + + +

                      maximum-scale=0.5

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_2.html b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_2.html new file mode 100644 index 0000000000..2fe3baf27d --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_maximum_scale_2.html @@ -0,0 +1,26 @@ + + + + + maximum-scale=2 in meta viewport + + + + + + +

                      maximum-scale=2

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_multiple_tags.html b/dom/base/test/meta_viewport/test_meta_viewport_multiple_tags.html new file mode 100644 index 0000000000..816dd62061 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_multiple_tags.html @@ -0,0 +1,28 @@ + + + + + multilple meta viewport tags + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_negative_height.html b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_negative_height.html new file mode 100644 index 0000000000..e458cbc8dd --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_negative_height.html @@ -0,0 +1,27 @@ + + + + + negative width and height in meta viewport + + + + + + +

                      width=-400, height=-240

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_no_height.html b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_no_height.html new file mode 100644 index 0000000000..2369f3b4f3 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_no_height.html @@ -0,0 +1,25 @@ + + + + + negative width in meta viewport + + + + + + +

                      width=-400

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_valid_height.html b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_valid_height.html new file mode 100644 index 0000000000..579712504d --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_negative_width_and_valid_height.html @@ -0,0 +1,25 @@ + + + + + negative width and valid height in meta viewport + + + + + + +

                      width=-400, height=240

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_no_content_and_valid_content_tags.html b/dom/base/test/meta_viewport/test_meta_viewport_no_content_and_valid_content_tags.html new file mode 100644 index 0000000000..f5a78d9eec --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_no_content_and_valid_content_tags.html @@ -0,0 +1,25 @@ + + + + + a valid meta viewport tag and no content attribute viewport tag + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_negative_height.html b/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_negative_height.html new file mode 100644 index 0000000000..0e0d37812b --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_negative_height.html @@ -0,0 +1,26 @@ + + + + + negative height in meta viewport + + + + + + +

                      height=-200

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_valid_height.html b/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_valid_height.html new file mode 100644 index 0000000000..a7be88ec40 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_no_width_and_valid_height.html @@ -0,0 +1,25 @@ + + + + + valid height in meta viewport + + + + + + +

                      height=240

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_remove_node.html b/dom/base/test/meta_viewport/test_meta_viewport_remove_node.html new file mode 100644 index 0000000000..12104cdf50 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_remove_node.html @@ -0,0 +1,34 @@ + + + + + remove meta viewport node + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_remove_node_from_multiple.html b/dom/base/test/meta_viewport/test_meta_viewport_remove_node_from_multiple.html new file mode 100644 index 0000000000..b967967cc1 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_remove_node_from_multiple.html @@ -0,0 +1,44 @@ + + + + + remove a meta viewport node from multiple ones + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_removing_content_attribute.html b/dom/base/test/meta_viewport/test_meta_viewport_removing_content_attribute.html new file mode 100644 index 0000000000..784a503e9f --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_removing_content_attribute.html @@ -0,0 +1,33 @@ + + + + + removing content attribute + + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_replace_content.html b/dom/base/test/meta_viewport/test_meta_viewport_replace_content.html new file mode 100644 index 0000000000..202c62362b --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_replace_content.html @@ -0,0 +1,39 @@ + + + + + replace meta viewport content + + + + + + + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_tiny_display_size.html b/dom/base/test/meta_viewport/test_meta_viewport_tiny_display_size.html new file mode 100644 index 0000000000..8e47fc677a --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_tiny_display_size.html @@ -0,0 +1,28 @@ + + + + + meta viewport test + + + + + + +

                      width=device-width

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_negative_height.html b/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_negative_height.html new file mode 100644 index 0000000000..10bce57d87 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_negative_height.html @@ -0,0 +1,26 @@ + + + + + valid width and negative height in meta viewport + + + + + + +

                      width=400, height=-200

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_no_height.html b/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_no_height.html new file mode 100644 index 0000000000..b24ce680a7 --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_valid_width_and_no_height.html @@ -0,0 +1,26 @@ + + + + + valid width in meta viewport + + + + + + +

                      width=400

                      + + + diff --git a/dom/base/test/meta_viewport/test_meta_viewport_width_with_trailing_characters.html b/dom/base/test/meta_viewport/test_meta_viewport_width_with_trailing_characters.html new file mode 100644 index 0000000000..f3545d057b --- /dev/null +++ b/dom/base/test/meta_viewport/test_meta_viewport_width_with_trailing_characters.html @@ -0,0 +1,26 @@ + + + + + width with trailing characters in meta viewport + + + + + + +

                      width=400/

                      + + + diff --git a/dom/base/test/meta_viewport/viewport_helpers.js b/dom/base/test/meta_viewport/viewport_helpers.js new file mode 100644 index 0000000000..d4d346b5d0 --- /dev/null +++ b/dom/base/test/meta_viewport/viewport_helpers.js @@ -0,0 +1,44 @@ +function scaleRatio(scale) { + return { + set: [ + ["layout.css.devPixelsPerPx", "" + scale], + ["dom.meta-viewport.enabled", true], + ], + }; +} + +function getViewportInfo(aDisplayWidth, aDisplayHeight) { + let defaultZoom = {}, + allowZoom = {}, + minZoom = {}, + maxZoom = {}, + width = {}, + height = {}, + autoSize = {}; + + let cwu = SpecialPowers.getDOMWindowUtils(window); + cwu.getViewportInfo( + aDisplayWidth, + aDisplayHeight, + defaultZoom, + allowZoom, + minZoom, + maxZoom, + width, + height, + autoSize + ); + return { + defaultZoom: defaultZoom.value, + minZoom: minZoom.value, + maxZoom: maxZoom.value, + width: width.value, + height: height.value, + autoSize: autoSize.value, + allowZoom: allowZoom.value, + }; +} + +function fuzzeq(a, b, msg) { + ok(Math.abs(a - b) < 1e-6, msg); +} diff --git a/dom/base/test/mochitest.toml b/dom/base/test/mochitest.toml new file mode 100644 index 0000000000..6415c4b33b --- /dev/null +++ b/dom/base/test/mochitest.toml @@ -0,0 +1,1788 @@ +[DEFAULT] +tags = "condprof" +prefs = [ + "formhelper.autozoom.force-disable.test-only=true", + "plugins.rewrite_youtube_embeds=true", + "dom.domrequest.enabled=true", +] +support-files = [ + "audio.ogg", + "iframe_bug962251.html", + "iframe_bug976673.html", + "iframe_main_bug1022229.html", + "iframe_sandbox_bug1022229.html", + "file_empty.html", + "iframe_postMessage_solidus.html", + "file_setname.html", + "345339_iframe.html", + "Ahem.ttf", + "accesscontrol.resource", + "accesscontrol.resource^headers^", + "badContentType.eventsource", + "badContentType.eventsource^headers^", + "badHTTPResponseCode.eventsource", + "badHTTPResponseCode.eventsource^headers^", + "badMessageEvent.eventsource", + "badMessageEvent.eventsource^headers^", + "badMessageEvent2.eventsource", + "badMessageEvent2.eventsource^headers^", + "bug282547.sjs", + "bug298064-subframe.html", + "bug313646.txt", + "bug382113_object.html", + "bug403852_fileOpener.js", + "bug419132.html", + "bug426308-redirect.sjs", + "bug435425.sjs", + "bug435425_redirect.sjs", + "bug444322.js", + "bug444322.txt", + "bug455629-helper.svg", + "bug457746.sjs", + "bug461735-post-redirect.js", + "bug461735-redirect1.sjs", + "bug461735-redirect2.sjs", + "bug466080.sjs", + "bug466409-empty.css", + "bug466409-page.html", + "bug475156.sjs", + "bug482935.sjs", + "bug540854.sjs", + "bug578096LoadChromeScript.js", + "bug638112-response.txt", + "bug638112.sjs", + "bug696301-script-1.js", + "bug696301-script-1.js^headers^", + "bug696301-script-2.js", + "bug704320.sjs", + "bug704320_counter.sjs", + "bug819051.sjs", + "bug1576154.sjs", + "chrome/bug418986-1.js", + "copypaste.js", + "delayedServerEvents.sjs", + "eventsource_message.sjs", + "eventsource_reconnect.sjs", + "eventsource.resource", + "eventsource.resource^headers^", + "eventsource_redirect.resource", + "eventsource_redirect.resource^headers^", + "eventsource_redirect_to.resource", + "eventsource_redirect_to.resource^headers^", + "eventsource_worker.js", + "file_bug1091883_frame.html", + "file_bug1091883_subframe.html", + "file_bug1091883_target.html", + "file_bug28293.sjs", + "file_bug326337.xml", + "file_bug326337_inner.html", + "file_bug326337_outer.html", + "file_bug416317.xhtml", + "file_bug426646-1.html", + "file_bug426646-2.html", + "file_bug428847-1.xhtml", + "file_bug428847-2.xhtml", + "file_bug498897.css", + "file_bug498897.html", + "file_bug498897.html^headers^", + "file_bug503481.sjs", + "file_bug503481b_inner.html", + "file_bug541937.html", + "file_bug541937.xhtml", + "file_bug557892.html", + "file_bug562137.txt", + "file_bug590812-ref.xhtml", + "file_bug590812.xml", + "file_bug590870.html", + "file_bug601803a.html", + "file_bug601803b.html", + "file_bug604660-1.xml", + "file_bug604660-2.xsl", + "file_bug604660-3.js", + "file_bug604660-4.js", + "file_bug604660-5.xml", + "file_bug604660-6.xsl", + "file_bug622088.sjs", + "file_bug622088_inner.html", + "file_bug675121.sjs", + "file_bug687859-16.js", + "file_bug687859-16.js^headers^", + "file_bug687859-bom.js", + "file_bug687859-bom.js^headers^", + "file_bug687859-charset.js", + "file_bug687859-http.js", + "file_bug687859-http.js^headers^", + "file_bug687859-inherit.js", + "file_bug692434.xml", + "file_bug704320_preload_attr.html", + "file_bug704320_preload_common.js", + "file_bug704320_preload_reuse.html", + "file_bug704320_redirect.html", + "file_bug707142_baseline.json", + "file_bug707142_bom.json", + "file_bug707142_utf-16.json", + "file_bug708620-2.html", + "file_bug708620.html", + "file_bug753278.html", + "file_bug769117.html", + "file_bug782342.txt", + "file_bug787778.sjs", + "file_bug869432.eventsource", + "file_bug869432.eventsource^headers^", + "file_bug907892.html", + "file_bug945152.jar", + "file_bug1274806.html", + "file_current_inner_window.html", + "file_domwindowutils_animation.html", + "file_domwindowutils_dynamic_toolbar.html", + "file_focus_shadow_dom.html", + "file_general_document.html", + "file_history_document_open.html", + "file_htmlserializer_1.html", + "file_htmlserializer_1_bodyonly.html", + "file_htmlserializer_1_format.html", + "file_htmlserializer_1_linebreak.html", + "file_htmlserializer_1_links.html", + "file_htmlserializer_1_nested_body.html", + "file_htmlserializer_1_no_body.html", + "file_htmlserializer_1_noflag.html", + "file_htmlserializer_1_noformatpre.html", + "file_htmlserializer_1_raw.html", + "file_htmlserializer_1_sibling_body.html", + "file_htmlserializer_1_sibling_body_only_body.html", + "file_htmlserializer_1_wrap.html", + "file_htmlserializer_2.html", + "file_htmlserializer_2_basic.html", + "file_htmlserializer_ipv6.html", + "file_htmlserializer_ipv6_out.html", + "file_lock_orientation_with_pending_fullscreen.html", + "file_mozfiledataurl_img.jpg", + "file_restrictedEventSource.sjs", + "file_settimeout_inner.html", + "file_timer_flood.html", + "file_viewport_scroll_quirks.html", + "file_viewport_scroll_xml.xml", + "file_window_close.html", + "file_window_close_2.html", + "file_x-frame-options_main.html", + "file_x-frame-options_page.sjs", + "file_xhtmlserializer_1.xhtml", + "file_xhtmlserializer_1_bodyonly.xhtml", + "file_xhtmlserializer_1_format.xhtml", + "file_xhtmlserializer_1_linebreak.xhtml", + "file_xhtmlserializer_1_links.xhtml", + "file_xhtmlserializer_1_nested_body.xhtml", + "file_xhtmlserializer_1_no_body.xhtml", + "file_xhtmlserializer_1_noflag.xhtml", + "file_xhtmlserializer_1_noformatpre.xhtml", + "file_xhtmlserializer_1_raw.xhtml", + "file_xhtmlserializer_1_sibling_body.xhtml", + "file_xhtmlserializer_1_sibling_body_only_body.xhtml", + "file_xhtmlserializer_1_wrap.xhtml", + "file_xhtmlserializer_2.xhtml", + "file_xhtmlserializer_2_basic.xhtml", + "file_xhtmlserializer_2_enthtml.xhtml", + "file_xhtmlserializer_2_entw3c.xhtml", + "file_xhtmlserializer_2_latin1.xhtml", + "file_youtube_flash_embed.html", + "forRemoval.resource", + "forRemoval.resource^headers^", + "formReset.html", + "invalid_accesscontrol.resource", + "invalid_accesscontrol.resource^headers^", + "script-1_bug597345.sjs", + "script-2_bug597345.js", + "script_bug602838.sjs", + "send_gzip_content.sjs", + "somedatas.resource", + "somedatas.resource^headers^", + "variable_style_sheet.sjs", + "w3element_traversal.svg", + "wholeTexty-helper.xml", + "referrerHelper.js", + "file_audioLoop.html", + "file_webaudio_startstop.html", + "referrer_helper.js", + "referrer_testserver.sjs", + "script_postmessages_fileList.js", + "common_postMessages.js", + "iframe_postMessages.html", + "worker_postMessages.js", + "test_anonymousContent_style_csp.html^headers^", + "file_explicit_user_agent.sjs", + "referrer_change_server.sjs", + "file_change_policy_redirect.html", + "file_bug1198095.js", + "file_bug1250148.sjs", + "file_bug1268962.sjs", + "iframe_meta_refresh.sjs", + "!/dom/security/test/cors/file_CrossSiteXHR_server.sjs", + "!/image/test/mochitest/blue.png", + "script_bug1238440.js", + "intersectionobserver_iframe.html", + "intersectionobserver_cross_domain_iframe.html", + "intersectionobserver_window.html", + "object_bug353334.html", + "embed_bug455472.html", + "object_bug455472.html", + "iframe1_bug431701.html", + "iframe2_bug431701.html", + "iframe3_bug431701.html", + "iframe4_bug431701.xml", + "iframe5_bug431701.xml", + "iframe6_bug431701.xml", + "iframe7_bug431701.xml", + "iframe1_bug426646.html", + "iframe2_bug426646.html", + "iframe_shared_compartment2a.html", + "iframe_shared_compartment2b.html", + "file1_setting_opener.html", + "file2_setting_opener.html", + "file3_setting_opener.html", + "file4_setting_opener.html", + "PASS.html", + "FAIL.html", + "!/dom/animation/test/testcommon.js", + "!/dom/events/test/event_leak_utils.js", + "../../../toolkit/components/pdfjs/test/file_pdfjs_test.pdf", + "green.png", + "slow.sjs", +] + +["test_EventSource_redirects.html"] +skip-if = [ + "http3", + "http2", +] + +["test_Image_constructor.html"] + +["test_NodeIterator_basics_filters.xhtml"] +skip-if = ["xorigin"] # JavaScript error: http://mochi.test:8888/tests/SimpleTest/SimpleTest.js, line 76: DataCloneError: The object could not be cloned. + +["test_NodeIterator_mutations_1.xhtml"] + +["test_NodeIterator_mutations_2.html"] + +["test_NodeIterator_mutations_3.html"] + +["test_anchor_area_referrer.html"] +skip-if = [ + "http3", + "http2", +] + +["test_anchor_area_referrer_changing.html"] +skip-if = [ + "http3", + "http2", +] + +["test_anchor_area_referrer_invalid.html"] +skip-if = [ + "http3", + "http2", +] + +["test_anchor_area_referrer_rel.html"] +skip-if = [ + "http3", + "http2", +] + +["test_anonymousContent_api.html"] + +["test_anonymousContent_append_after_reflow.html"] + +["test_anonymousContent_canvas.html"] +skip-if = ["headless"] # Bug 1405867 + +["test_anonymousContent_insert.html"] + +["test_anonymousContent_manipulate_content.html"] + +["test_anonymousContent_style_csp.html"] + +["test_async_setTimeout_stack.html"] + +["test_async_setTimeout_stack_across_globals.html"] + +["test_base.xhtml"] +skip-if = [ + "http3", + "http2", +] + +["test_bug5141.html"] + +["test_bug28293.html"] + +["test_bug28293.xhtml"] + +["test_bug51034.html"] + +["test_bug116083.html"] +skip-if = ["headless"] # fails in clipboard mode + +["test_bug166235.html"] +skip-if = ["headless"] # headless != clipboard + +["test_bug199959.html"] + +["test_bug218236.html"] + +["test_bug218277.html"] + +["test_bug238409.html"] + +["test_bug254337.html"] + +["test_bug270145.xhtml"] + +["test_bug276037-1.html"] + +["test_bug276037-2.xhtml"] + +["test_bug282547.html"] + +["test_bug298064.html"] + +["test_bug300992.html"] + +["test_bug311681.xml"] + +["test_bug313646.html"] + +["test_bug320799.html"] + +["test_bug322317.html"] + +["test_bug326337.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug331959.html"] + +["test_bug333064.html"] + +["test_bug333198.html"] + +["test_bug333673.html"] + +["test_bug337631.html"] + +["test_bug338541.xhtml"] + +["test_bug338583.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug338679.html"] + +["test_bug339494.html"] + +["test_bug339494.xhtml"] + +["test_bug343596.html"] + +["test_bug345339.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug346485.html"] + +["test_bug352728.html"] + +["test_bug352728.xhtml"] + +["test_bug353334.html"] + +["test_bug355026.html"] + +["test_bug357450.html"] +support-files = ["file_bug357450.js"] + +["test_bug357450.xhtml"] + +["test_bug357450_svg.xhtml"] + +["test_bug357509.html"] + +["test_bug358660.html"] + +["test_bug362391.xhtml"] + +["test_bug364092.xhtml"] + +["test_bug364413.xhtml"] + +["test_bug366944.html"] + +["test_bug366946.html"] + +["test_bug367164.html"] + +["test_bug368972.html"] + +["test_bug371576-2.html"] + +["test_bug371576-3.html"] + +["test_bug371576-4.html"] + +["test_bug371576-5.html"] + +["test_bug372086.html"] + +["test_bug372964-2.html"] + +["test_bug372964.html"] + +["test_bug373181.xhtml"] + +["test_bug375314-2.html"] +skip-if = [ + "xorigin", # Hangs, [Exception... "Component returned failure code: 0xc1f30100 (NS_ERROR_FACTORY_EXISTS) [nsIComponentRegistrar.registerFactory]" nsresult: "0xc1f30100 (NS_ERROR_FACTORY_EXISTS)" location: "JS frame :: createChromeScript :: createChromeScript :: line 40" data: no] + "http3", + "http2", +] + +["test_bug375314.html"] + +["test_bug378969.html"] + +["test_bug380418.html"] +support-files = ["test_bug380418.html^headers^"] + +["test_bug382113.html"] + +["test_bug382871.html"] + +["test_bug384003.xhtml"] + +["test_bug390219.html"] + +["test_bug390735.html"] + +["test_bug392318.html"] + +["test_bug392511.html"] + +["test_bug393968.html"] + +["test_bug395915.html"] + +["test_bug397234.html"] + +["test_bug398243.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug401662.html"] + +["test_bug402150.html"] +support-files = ["test_bug402150.html^headers^"] + +["test_bug403841.html"] + +["test_bug403852.html"] + +["test_bug403868.xml"] + +["test_bug405182.html"] + +["test_bug409380.html"] + +["test_bug410229.html"] + +["test_bug413974.html"] + +["test_bug414190.html"] + +["test_bug415860.html"] + +["test_bug416317-1.html"] + +["test_bug416317-2.html"] + +["test_bug416383.html"] + +["test_bug417255.html"] + +["test_bug417384.html"] + +["test_bug418214.html"] + +["test_bug418986-1.html"] + +["test_bug419132.html"] + +["test_bug420609.xhtml"] + +["test_bug420700.html"] + +["test_bug421602.html"] + +["test_bug422403-1.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug422403-2.xhtml"] + +["test_bug422537.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug424212.html"] + +["test_bug424359-1.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug424359-2.html"] + +["test_bug426308.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug426646.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug428847.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug431082.html"] + +["test_bug431701.html"] + +["test_bug431833.html"] + +["test_bug433533.html"] + +["test_bug433662.html"] + +["test_bug435425.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug444322.html"] + +["test_bug444546.html"] +disabled = "Disabled for now. Mochitest is not reliable enough for these." +support-files = ["bug444546.sjs"] + +["test_bug444722.html"] + +["test_bug448993.html"] + +["test_bug450160.html"] + +["test_bug451376.html"] + +["test_bug453521.html"] + +["test_bug453736.html"] + +["test_bug454325.html"] + +["test_bug454326.html"] + +["test_bug455472.html"] + +["test_bug455629.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug456262.html"] + +["test_bug457746.html"] + +["test_bug459424.html"] + +["test_bug461555.html"] + +["test_bug461735.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug465767.html"] + +["test_bug466080.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug466409.html"] + +["test_bug466751.xhtml"] + +["test_bug469020.html"] + +["test_bug469304.html"] + +["test_bug473162-1.html"] + +["test_bug473162-2.html"] + +["test_bug475156.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug482935.html"] + +["test_bug484396.html"] + +["test_bug493881.html"] +support-files = ["test_bug493881.js"] + +["test_bug498240.html"] + +["test_bug498433.html"] + +["test_bug498897.html"] + +["test_bug499656.html"] + +["test_bug499656.xhtml"] + +["test_bug500937.html"] + +["test_bug503473.html"] +disabled = "Disabled due to making the harness time out" +support-files = ["file_bug503473-frame.sjs"] + +["test_bug503481.html"] + +["test_bug503481b.html"] + +["test_bug513194.html"] + +["test_bug514487.html"] + +["test_bug515401.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug518104.html"] +support-files = ["file_bug518104.js"] + +["test_bug527896.html"] + +["test_bug540854.html"] + +["test_bug541937.html"] + +["test_bug544642.html"] + +["test_bug545644.html"] + +["test_bug545644.xhtml"] + +["test_bug548463.html"] + +["test_bug553896.xhtml"] + +["test_bug557892.html"] + +["test_bug558726.html"] + +["test_bug559526.html"] + +["test_bug560780.html"] + +["test_bug562137.html"] + +["test_bug562169-1.html"] + +["test_bug562169-2.html"] + +["test_bug562652.html"] + +["test_bug564047.html"] + +["test_bug564863.xhtml"] + +["test_bug567350.html"] + +["test_bug574596.html"] +skip-if = ["os == 'android'"] + +["test_bug578096.html"] +skip-if = ["verify && os == 'win'"] + +["test_bug585978.html"] + +["test_bug587931.html"] + +["test_bug588990.html"] + +["test_bug590812.html"] +skip-if = [ + "verify && !debug && os == 'linux'", #bug 687032 + "http3", + "http2", +] + +["test_bug590870.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug592366.html"] + +["test_bug592829.html"] + +["test_bug597345.html"] + +["test_bug599295.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug599588.html"] + +["test_bug601803.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug602838.html"] + +["test_bug604592.html"] + +["test_bug604660.html"] + +["test_bug605982.html"] + +["test_bug606729.html"] + +["test_bug614058.html"] + +["test_bug622088.html"] + +["test_bug622117.html"] +support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_utils.js"] + +["test_bug622246.html"] +support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_utils.js"] + +["test_bug625722.html"] + +["test_bug626262.html"] + +["test_bug628938.html"] + +["test_bug631615.html"] + +["test_bug638112.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug647518.html"] + +["test_bug650001.html"] + +["test_bug650776.html"] + +["test_bug650784.html"] + +["test_bug656283.html"] + +["test_bug664916.html"] + +["test_bug666604.html"] + +["test_bug675121.html"] + +["test_bug675166.html"] + +["test_bug682463.html"] + +["test_bug682554.html"] + +["test_bug682592.html"] + +["test_bug684671.html"] + +["test_bug685798.html"] + +["test_bug686449.xhtml"] + +["test_bug687859.html"] + +["test_bug690056.html"] + +["test_bug692434.html"] + +["test_bug693615.html"] + +["test_bug693875.html"] + +["test_bug694754.xhtml"] + +["test_bug696301-1.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug696301-2.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug698381.html"] + +["test_bug698384.html"] + +["test_bug704063.html"] + +["test_bug704320-1.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug704320-2.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug704320_policyset.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug704320_policyset2.html"] + +["test_bug704320_preload.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug707142.html"] + +["test_bug708620.html"] + +["test_bug711047.html"] + +["test_bug711180.html"] + +["test_bug719533.html"] + +["test_bug726364.html"] + +["test_bug737087.html"] + +["test_bug737565.html"] + +["test_bug737612.html"] + +["test_bug738108.html"] + +["test_bug744830.html"] + +["test_bug749367.html"] + +["test_bug750096.html"] + +["test_bug753278.html"] + +["test_bug761120.html"] + +["test_bug769117.html"] + +["test_bug782342.html"] + +["test_bug787778.html"] + +["test_bug789315.html"] + +["test_bug789856.html"] + +["test_bug809003.html"] + +["test_bug810494.html"] + +["test_bug811701.html"] + +["test_bug811701.xhtml"] + +["test_bug813919.html"] + +["test_bug814576.html"] + +["test_bug819051.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug820909.html"] + +["test_bug864595.html"] + +["test_bug868999.html"] + +["test_bug869000.html"] + +["test_bug869002.html"] + +["test_bug869006.html"] + +["test_bug876282.html"] + +["test_bug891952.html"] + +["test_bug894874.html"] + +["test_bug895974.html"] + +["test_bug907892.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug913761.html"] + +["test_bug922681.html"] + +["test_bug927196.html"] + +["test_bug962251.html"] + +["test_bug976673.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug982153.html"] + +["test_bug999456.html"] + +["test_bug1022229.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1025933.html"] + +["test_bug1037687.html"] +support-files = ["test_bug1037687_subframe.html"] + +["test_bug1043106.html"] + +["test_bug1057176.html"] + +["test_bug1060938.html"] + +["test_bug1064481.html"] + +["test_bug1070015.html"] + +["test_bug1075702.html"] + +["test_bug1091883.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1100912.html"] +support-files = ["file_bug1100912.html"] + +["test_bug1101364.html"] + +["test_bug1118689.html"] + +["test_bug1126851.html"] + +["test_bug1163743.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1165501.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1187157.html"] + +["test_bug1198095.html"] + +["test_bug1222633.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1222633_link_update.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1238440.html"] + +["test_bug1250148.html"] + +["test_bug1259588.html"] + +["test_bug1268962.html"] +skip-if = [ + "http3", + "http2", +] + +["test_bug1274806.html"] + +["test_bug1295852.html"] + +["test_bug1307730.html"] + +["test_bug1308069.html"] + +["test_bug1314032.html"] + +["test_bug1318303.html"] + +["test_bug1375050.html"] + +["test_bug1381710.html"] + +["test_bug1399605.html"] + +["test_bug1404385.html"] + +["test_bug1406102.html"] + +["test_bug1421568.html"] + +["test_bug1433073.html"] +skip-if = [ + "os == 'android'", + "headless", +] + +["test_bug1472427.html"] + +["test_bug1499169.html"] +skip-if = ["os == 'android'"] # Timeouts on android due to page closing issues with embedded pdf + +["test_bug1576154.html"] + +["test_bug1632975.html"] + +["test_bug1639328.html"] +support-files = ["file_bug1639328.html"] + +["test_bug1640766.html"] +support-files = [ + "iframe1_bug1640766.html", + "iframe2_bug1640766.html", +] +skip-if = [ + "http3", + "http2", +] + +["test_bug1648887.html"] + +["test_bug1667316.html"] + +["test_bug1730284.html"] +# https://bugzilla.mozilla.org/show_bug.cgi?id=1632196 and +# https://bugzilla.mozilla.org/show_bug.cgi?id=1632438. + +["test_bug1739957.html"] +support-files = ["bug1739957.sjs"] + +["test_bug1784187.html"] + +["test_bug1799354.html"] + +["test_caretPositionFromPoint.html"] + +["test_change_policy.html"] +skip-if = [ + "http3", + "http2", +] + +["test_clearTimeoutIntervalNoArg.html"] + +["test_clipboard_nbsp.html"] + +["test_constructor-assignment.html"] + +["test_constructor.html"] + +["test_content_iterator_post_order.html"] + +["test_content_iterator_pre_order.html"] + +["test_content_iterator_subtree.html"] + +["test_copyimage.html"] +skip-if = [ + "os == 'android'", + "headless", #bug 904183 +] + +["test_copypaste.html"] +skip-if = [ + "os == 'android'", + "headless", #bug 904183 +] + +["test_copypaste.xhtml"] +skip-if = ["headless"] #bug 904183 + +["test_copypaste_disabled.html"] +support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_utils.js"] + +["test_createHTMLDocument.html"] + +["test_current_inner_window.html"] +skip-if = [ + "http3", + "http2", +] + +["test_custom_element.html"] + +["test_custom_element_reflector.html"] + +["test_data_uri.html"] + +["test_delazification_strategy.html"] +skip-if = [ + "verify", + "ccov", +] +support-files = [ + "file_delazification_strategy.html", + "file_delazification_strategy.js", +] + +["test_document.all_iteration.html"] + +["test_document.all_unqualified.html"] + +["test_document_constructor.html"] + +["test_document_importNode_document.html"] + +["test_document_wireframe.html"] +skip-if = [ + "!sessionHistoryInParent", + "http3", + "http2", +] + +["test_domparser_null_char.html"] + +["test_domparsing.html"] + +["test_domrequest.html"] + +["test_domwindowutils.html"] +skip-if = ["os == 'android'"] # Bug 1525959 + +["test_element.matches.html"] + +["test_elementTraversal.html"] + +["test_element_closest.html"] + +["test_embed_xorigin_document.html"] +skip-if = [ + "http3", + "http2", +] + +["test_encodeToStringWithMaxLength.html"] + +["test_encodeToStringWithRequiresReinitAfterOutput.html"] + +["test_eventsource_event_listener_leaks.html"] + +["test_eventsourceservice_basic.html"] +skip-if = [ + "http3", + "http2", +] + +["test_eventsourceservice_reconnect_error.html"] +skip-if = [ + "http3", + "http2", +] + +["test_eventsourceservice_status_error.html"] + +["test_eventsourceservice_worker.html"] +skip-if = [ + "http3", + "http2", +] + +["test_explicit_user_agent.html"] + +["test_find.html"] + +["test_find_bug1601118.html"] + +["test_find_bug1654683.html"] + +["test_find_nac.html"] + +["test_focus_design_mode.html"] +support-files = ["file_focus_design_mode_inner.html"] + +["test_focus_display_none_xorigin_iframe.html"] +support-files = ["file_focus_display_none_xorigin_iframe_inner.html"] +skip-if = [ + "http3", + "http2", +] + +["test_focus_keyboard_event.html"] +skip-if = [ + "http3", + "http2", +] + +["test_focus_scroll_padding_tab.html"] + +["test_focus_scrollable_fieldset.html"] + +["test_focus_scrollable_input.html"] + +["test_focus_shadow_dom.html"] + +["test_focus_shadow_dom_root.html"] + +["test_getAttribute_after_createAttribute.html"] + +["test_getElementById.html"] + +["test_getTranslationNodes.html"] + +["test_getTranslationNodes_limit.html"] + +["test_gsp-qualified.html"] + +["test_gsp-quirks.html"] + +["test_gsp-standards.html"] + +["test_history_document_open.html"] + +["test_history_state_null.html"] + +["test_html_colors_quirks.html"] + +["test_html_colors_standards.html"] + +["test_htmlcopyencoder.html"] + +["test_htmlcopyencoder.xhtml"] + +["test_iframe_event_listener_leaks.html"] + +["test_iframe_referrer.html"] +skip-if = [ + "http3", + "http2", +] + +["test_iframe_referrer_changing.html"] +skip-if = [ + "http3", + "http2", +] + +["test_iframe_referrer_invalid.html"] +skip-if = [ + "http3", + "http2", +] + +["test_innersize_scrollport.html"] + +["test_input_vsync_alignment_inner_event_loop.html"] + +["test_input_vsync_alignment_input_while_vsync.html"] + +["test_input_vsync_alignment_lower_than_normal.html"] + +["test_integer_attr_with_leading_zero.html"] + +["test_intersectionobservers.html"] +skip-if = [ + "http3", + "http2", +] + +["test_link_prefetch.html"] +skip-if = [ + "http3", + "http2", +] + +["test_link_preload.html"] +skip-if = [ + "http3", + "http2", +] + +["test_link_stylesheet.html"] +skip-if = [ + "http3", + "http2", +] + +["test_location_href_unknown_protocol.html"] +support-files = ["file_location_href_unknown_protocol.html"] + +["test_lock_orientation_after_fullscreen.html"] +skip-if = [ + "os != 'android'", # Only run on Android. +] + +["test_lock_orientation_with_pending_fullscreen.html"] +skip-if = [ + "os == 'mac'", + "os == 'linux'", + "headless", +] + +["test_meta_refresh_referrer.html"] +skip-if = [ + "http3", + "http2", +] + +["test_mozMatchesSelector.html"] + +["test_mutationobservers.html"] + +["test_named_frames.html"] + +["test_navigatorPrefOverride.html"] + +["test_navigator_cookieEnabled.html"] +skip-if = [ + "http3", + "http2", +] + +["test_navigator_hardwareConcurrency.html"] + +["test_navigator_language.html"] + +["test_nested_event_loop_spin_and_idle_tasks.html"] + +["test_nodelist_holes.html"] + +["test_openDialogChromeOnly.html"] +tags = "openwindow" + +["test_open_null_features.html"] + +["test_pasting_svg_image.html"] +skip-if = ["headless"] # Bug 1669923. + +["test_pdf_print.html"] +skip-if = [ + "os == 'android'", # We don't ship pdf.js on Android + "win11_2009 && condprof", # Bug 1843710 +] + +["test_plugin_freezing.html"] + +["test_postMessage_originAttributes.html"] +support-files = ["file_receiveMessage.html"] +skip-if = ["true"] # Uses mismatched OriginAttributes for iframe (bug 1616353) + +["test_postMessage_solidus.html"] +skip-if = [ + "http3", + "http2", +] + +["test_postMessages_broadcastChannel.html"] + +["test_postMessages_messagePort.html"] + +["test_postMessages_window.html"] +skip-if = [ + "http3", + "http2", +] + +["test_postMessages_workers.html"] + +["test_processing_instruction_update_stylesheet.xhtml"] + +["test_progress_events_for_gzip_data.html"] +skip-if = ["tsan"] # Bug 1621323 + +["test_pushState_structuredclone.html"] +scheme = "https" + +["test_range_bounds.html"] + +["test_reentrant_flush.html"] + +["test_root_iframe.html"] + +["test_sandbox_and_document_uri.html"] +support-files = ["file_sandbox_and_document_uri.html"] + +["test_screen_orientation.html"] + +["test_script_loader_crossorigin_data_url.html"] + +["test_script_loader_js_cache.html"] +disabled = "https://bugzilla.mozilla.org/show_bug.cgi?id=1853173" +skip-if = ["verify"] +support-files = [ + "file_js_cache.html", + "file_js_cache_with_sri.html", + "file_js_cache_module.html", + "file_js_cache.js", + "file_module_js_cache.html", + "file_module_js_cache_with_sri.html", + "file_module_js_cache_no_module.html", + "file_module_js_cache.mjs", + "file_js_cache_save_after_load.html", + "file_js_cache_save_after_load.js", + "file_js_cache_syntax_error.html", + "file_js_cache_syntax_error.js", +] + +["test_script_loader_js_cache_frames.html"] +skip-if = ["verify"] +support-files = [ + "file_script_module_frames_relay.js", + "file_script_module_frames_element.html", + "file_script_module_frames_element_save.html", + "file_script_module_frames_element_load.html", + "file_script_module_frames_element_shared.mjs", + "file_script_module_frames_import.html", + "file_script_module_frames_import_save.html", + "file_script_module_frames_import_save.mjs", + "file_script_module_frames_import_load.html", + "file_script_module_frames_import_load.mjs", + "file_script_module_frames_import_shared.mjs", + "file_script_module_frames_dynamic.html", + "file_script_module_frames_dynamic_save.html", + "file_script_module_frames_dynamic_save.mjs", + "file_script_module_frames_dynamic_load.html", + "file_script_module_frames_dynamic_load.mjs", + "file_script_module_frames_dynamic_shared.mjs", +] + +["test_script_loader_js_cache_module.html"] +disabled = "https://bugzilla.mozilla.org/show_bug.cgi?id=1853173" +skip-if = ["verify"] +support-files = [ + "file_script_module_single.html", + "file_script_module_single.mjs", + "file_script_module_import.html", + "file_script_module_import.mjs", + "file_script_module_import_imported.mjs", + "file_script_module_import_multi.html", + "file_script_module_import_multi.mjs", + "file_script_module_import_multi_imported_once.mjs", + "file_script_module_import_multi_imported_twice.mjs", + "file_script_module_import_multi_elems.html", + "file_script_module_import_multi_elems_1.mjs", + "file_script_module_import_multi_elems_2.mjs", + "file_script_module_import_multi_elems_imported_once_1.mjs", + "file_script_module_import_multi_elems_imported_once_2.mjs", + "file_script_module_import_multi_elems_imported_once_3.mjs", + "file_script_module_import_multi_elems_imported_twice.mjs", + "file_script_module_import_and_element.html", + "file_script_module_import_and_element.mjs", + "file_script_module_import_and_element_imported_1.mjs", + "file_script_module_import_and_element_imported_2.mjs", + "file_script_module_import_and_element_imported_3.mjs", + "file_script_module_element_and_import.html", + "file_script_module_element_and_import.mjs", + "file_script_module_element_and_import_imported_1.mjs", + "file_script_module_element_and_import_imported_2.mjs", + "file_script_module_element_and_import_imported_3.mjs", + "file_script_module_dynamic_import.html", + "file_script_module_dynamic_import.mjs", + "file_script_module_dynamic_import_imported.mjs", + "file_script_module_dynamic_and_element.html", + "file_script_module_dynamic_and_element.mjs", + "file_script_module_dynamic_and_element_imported_1.mjs", + "file_script_module_dynamic_and_element_imported_2.mjs", + "file_script_module_dynamic_and_element_imported_3.mjs", + "file_script_module_element_and_dynamic.html", + "file_script_module_element_and_dynamic.mjs", + "file_script_module_element_and_dynamic_imported_1.mjs", + "file_script_module_element_and_dynamic_imported_2.mjs", + "file_script_module_element_and_dynamic_imported_3.mjs", + "file_script_module_dynamic_and_static.html", + "file_script_module_dynamic_and_static.mjs", + "file_script_module_dynamic_and_static_imported_1.mjs", + "file_script_module_dynamic_and_static_imported_2.mjs", + "file_script_module_dynamic_and_static_imported_3.mjs", + "file_script_module_static_and_dynamic.html", + "file_script_module_static_and_dynamic.mjs", + "file_script_module_static_and_dynamic_imported_1.mjs", + "file_script_module_static_and_dynamic_imported_2.mjs", + "file_script_module_static_and_dynamic_imported_3.mjs", +] + +["test_script_loader_js_cache_module_sri.html"] +disabled = "https://bugzilla.mozilla.org/show_bug.cgi?id=1853173" +skip-if = ["verify"] +support-files = [ + "file_script_module_sri_basic.html", + "file_script_module_sri_basic_prep.html", + "file_script_module_sri_basic.mjs", + "file_script_module_sri_fallback.html", + "file_script_module_sri_fallback_prep.html", + "file_script_module_sri_fallback.mjs", + "file_script_module_sri_fallback_failure.html", + "file_script_module_sri_fallback_failure_prep.html", + "file_script_module_sri_fallback_failure.mjs", + "file_script_module_sri_elem_elem_1.html", + "file_script_module_sri_elem_elem_1_prep.html", + "file_script_module_sri_elem_elem_1.mjs", + "file_script_module_sri_elem_elem_2.html", + "file_script_module_sri_elem_elem_2_prep.html", + "file_script_module_sri_elem_elem_2.mjs", + "file_script_module_sri_elem_import.html", + "file_script_module_sri_elem_import_prep.html", + "file_script_module_sri_elem_import.mjs", + "file_script_module_sri_elem_import_imported.mjs", + "file_script_module_sri_import_elem.html", + "file_script_module_sri_import_elem_prep.html", + "file_script_module_sri_import_elem.mjs", + "file_script_module_sri_import_elem_imported.mjs", + "file_script_module_sri_import_elem_nopreload.html", + "file_script_module_sri_import_elem_nopreload_prep.html", + "file_script_module_sri_import_elem_nopreload.mjs", + "file_script_module_sri_import_elem_nopreload_imported.mjs", + "file_script_module_sri_elem_dynamic.html", + "file_script_module_sri_elem_dynamic_prep.html", + "file_script_module_sri_elem_dynamic.mjs", + "file_script_module_sri_elem_dynamic_imported.mjs", + "file_script_module_sri_dynamic_elem.html", + "file_script_module_sri_dynamic_elem_prep.html", + "file_script_module_sri_dynamic_elem.mjs", + "file_script_module_sri_dynamic_elem_imported.mjs", + "file_script_module_sri_dynamic_elem_nopreload.html", + "file_script_module_sri_dynamic_elem_nopreload_prep.html", + "file_script_module_sri_dynamic_elem_nopreload.mjs", + "file_script_module_sri_dynamic_elem_nopreload_imported.mjs", +] + +["test_setInterval_from_start.html"] + +["test_setInterval_uncatchable_exception.html"] +skip-if = ["debug == false"] + +["test_setTimeoutWith0.html"] + +["test_settimeout_extra_arguments.html"] + +["test_settimeout_inner.html"] + +["test_setting_opener.html"] + +["test_shared_compartment1.html"] +skip-if = [ + "http3", + "http2", +] + +["test_shared_compartment2.html"] +skip-if = [ + "http3", + "http2", +] + +["test_structuredclone_backref.html"] + +["test_structuredclone_error.html"] + +["test_style_cssText.html"] + +["test_suppressed_events_and_scrolling.html"] +support-files = ["file_suppressed_events_and_scrolling.html"] + +["test_suppressed_events_nested_iframe.html"] +skip-if = [ + "os == 'android'", + "http3", + "http2", +] +support-files = [ + "file_suppressed_events_top_xhr.html", + "file_suppressed_events_top_modalstate.html", + "file_suppressed_events_top.html", + "file_suppressed_events_middle.html", + "file_suppressed_events_inner.html", + "!/gfx/layers/apz/test/mochitest/apz_test_utils.js", +] + +["test_suppressed_microtasks.html"] +skip-if = [ + "debug", + "asan", + "verify", + "os == 'android'", # The test needs to run reasonably fast. +] + +["test_text_wholeText.html"] + +["test_textnode_normalize_in_selection.html"] + +["test_textnode_split_in_selection.html"] + +["test_timeout_clamp.html"] + +["test_timer_flood.html"] + +["test_title.html"] +support-files = ["file_title.xhtml"] + +["test_toScreenRect.html"] +support-files = ["file_toScreenRect.html"] + +["test_treewalker_nextsibling.xml"] + +["test_user_select.html"] +skip-if = ["os == 'android'"] # Bug 1791049 + +["test_viewport_metrics_on_landscape_content.html"] +support-files = ["file_viewport_metrics_on_landscape_content.html"] + +["test_viewport_scroll.html"] + +["test_viewsource_forbidden_in_object.html"] + +["test_w3element_traversal.html"] + +["test_w3element_traversal.xhtml"] + +["test_w3element_traversal_svg.html"] + +["test_warning_for_blocked_cross_site_request.html"] +skip-if = [ + "http3", + "http2", +] + +["test_window_close.html"] + +["test_window_constructor.html"] + +["test_window_content.html"] + +["test_window_cross_origin_props.html"] +skip-if = [ + "http3", + "http2", +] + +["test_window_define_nonconfigurable.html"] + +["test_window_define_symbol.html"] + +["test_window_element_enumeration.html"] + +["test_window_enumeration.html"] + +["test_window_extensible.html"] + +["test_window_focus_by_close_and_open.html"] +support-files = ["file_window_focus_by_close_and_open.html"] + +["test_window_indexing.html"] + +["test_window_keys.html"] + +["test_window_named_frame_enumeration.html"] +skip-if = [ + "http3", + "http2", +] + +["test_window_own_props.html"] + +["test_window_proto.html"] + +["test_writable-replaceable.html"] + +["test_x-frame-options.html"] +skip-if = [ + "os == 'android' && debug", + "xorigin", # JavaScript error: http://mochi.test:8888/tests/dom/base/test/test_x-frame-options.html, line 48: TypeError: can't access property "textContent", this.content.document.getElementById(...) is null, JavaScript error: resource://gre/modules/ProcessSelector.jsm, line 56: TypeError: can't access property "tabCount", process is null + "http3", + "http2", +] + +["test_youtube_flash_embed.html"] +skip-if = [ + "http3", + "http2", + "os == 'linux' && debug" #Bug 1870499 and other bugs with crashes after this test start +] +# Please keep alphabetical order. diff --git a/dom/base/test/moz.build b/dom/base/test/moz.build new file mode 100644 index 0000000000..374e735b88 --- /dev/null +++ b/dom/base/test/moz.build @@ -0,0 +1,44 @@ +# -*- 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/. + +XPCSHELL_TESTS_MANIFESTS += [ + "unit/xpcshell.toml", + "unit_ipc/xpcshell.toml", +] + +MOCHITEST_MANIFESTS += [ + "mochitest.toml", +] + +MOCHITEST_CHROME_MANIFESTS += [ + "chrome.toml", + "chrome/chrome.toml", +] + +BROWSER_CHROME_MANIFESTS += [ + "browser.toml", + "fmm/browser.toml", +] + +TEST_DIRS += [ + "fullscreen", + "gtest", + "jsmodules", + "jsmodules/importmaps", + "useractivation", + "meta_viewport", +] + +TEST_HARNESS_FILES.testing.mochitest.tests.dom.base.test.chrome += [ + "chrome/bug421622-referer.sjs", + "chrome/bug884693.sjs", + "chrome/nochrome_bug1346936.html", + "chrome/nochrome_bug1346936.js", + "chrome/nochrome_bug1346936.js^headers^", + "chrome/nochrome_bug765993.html", + "chrome/nochrome_bug765993.js", + "chrome/nochrome_bug765993.js^headers^", +] diff --git a/dom/base/test/object_bug353334.html b/dom/base/test/object_bug353334.html new file mode 100644 index 0000000000..8e73c916c6 --- /dev/null +++ b/dom/base/test/object_bug353334.html @@ -0,0 +1 @@ +test diff --git a/dom/base/test/object_bug455472.html b/dom/base/test/object_bug455472.html new file mode 100644 index 0000000000..b2f3ae4f44 --- /dev/null +++ b/dom/base/test/object_bug455472.html @@ -0,0 +1 @@ + diff --git a/dom/base/test/red.png b/dom/base/test/red.png new file mode 100644 index 0000000000..a6e195d59c Binary files /dev/null and b/dom/base/test/red.png differ diff --git a/dom/base/test/referrerHelper.js b/dom/base/test/referrerHelper.js new file mode 100644 index 0000000000..da3097b849 --- /dev/null +++ b/dom/base/test/referrerHelper.js @@ -0,0 +1,343 @@ +/** + * Listen for notifications from the child. + * These are sent in case of error, or when the loads we await have completed. + */ +window.addEventListener("message", function (event) { + if (event.data == "childLoadComplete") { + // all loads happen, continue the test. + advance(); + } else if (event.data == "childOverload") { + // too many loads happened in a test frame, abort. + ok(false, "Too many load handlers called in test."); + SimpleTest.finish(); + } else if (event.data.indexOf("fail-") == 0) { + // something else failed in the test frame, abort. + ok(false, "Child failed the test with error " + event.data.substr(5)); + SimpleTest.finish(); + } +}); + +/** + * helper to perform an XHR. + */ +function doXHR(url, onSuccess, onFail) { + var xhr = new XMLHttpRequest(); + xhr.onload = function () { + if (xhr.status == 200) { + onSuccess(xhr); + } else { + onFail(xhr); + } + }; + xhr.open("GET", url, true); + xhr.send(null); +} + +/** + * This triggers state-resetting on the counter server. + */ +function resetCounter() { + doXHR( + "/tests/dom/base/test/bug704320_counter.sjs?reset", + advance, + function (xhr) { + ok(false, "Need to be able to reset the request counter"); + SimpleTest.finish(); + } + ); +} + +/** + * Grabs the results via XHR and passes to checker. + */ +function checkIndividualResults(testname, expected) { + doXHR( + "/tests/dom/base/test/bug704320_counter.sjs?results", + function (xhr) { + var results = JSON.parse(xhr.responseText); + info(xhr.responseText); + + ok( + "img" in results, + testname + " test: some image loads required in results object." + ); + is( + results.img.count, + 2, + testname + " Test: Expected 2 loads for image requests." + ); + + expected.forEach(function (ref) { + ok( + results.img.referrers.includes(ref), + testname + + " Test: Expected " + + ref + + " referrer policy in test, results were " + + JSON.stringify(results.img.referrers) + + "." + ); + }); + advance(); + }, + function (xhr) { + ok(false, "Can't get results from the counter server."); + SimpleTest.finish(); + } + ); +} + +/** + * Grabs the results via XHR and checks them + */ +function checkExpectedGlobalResults(testName) { + var url = "bug704320.sjs?action=get-test-results"; + doXHR( + url, + function (xhr) { + var response = JSON.parse(xhr.response); + + for (type in response) { + for (scheme in response[type]) { + for (policy in response[type][scheme]) { + var expectedResult = + EXPECTED_RESULTS[type] === undefined + ? EXPECTED_RESULTS.default[scheme][policy] + : EXPECTED_RESULTS[type][scheme][policy]; + is( + response[type][scheme][policy], + expectedResult, + type + " " + scheme + " " + policy + ); + } + } + } + advance(testName); + }, + function (xhr) { + ok(false, "Can't get results from the counter server."); + SimpleTest.finish(); + } + ); +} + +var EXPECTED_RESULTS = { + // From docshell/base/nsDocShell.cpp: + // "If the document containing the hyperlink being audited was not retrieved + // over an encrypted connection and its address does not have the same + // origin as "ping URL", send a referrer." + "link-ping": { + // Same-origin + "http-to-http": { + "no-referrer": "", + "unsafe-url": "", + origin: "", + "origin-when-cross-origin": "", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + "http-to-https": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url", + origin: "http://example.com/", + "origin-when-cross-origin": "http://example.com/", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade", + "same-origin": "", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": "http://example.com/", + }, + // Encrypted and not same-origin + "https-to-http": { + "no-referrer": "", + "unsafe-url": "", + origin: "", + "origin-when-cross-origin": "", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + // Encrypted + "https-to-https": { + "no-referrer": "", + "unsafe-url": "", + origin: "", + "origin-when-cross-origin": "", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + }, + // form is tested in a 2nd level iframe. + form: { + "http-to-http": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=form", + origin: "http://example.com/", + "origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=form", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=form", + "same-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin&type=form", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin&type=form", + }, + "http-to-https": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=form", + origin: "http://example.com/", + "origin-when-cross-origin": "http://example.com/", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=form", + "same-origin": "", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": "http://example.com/", + }, + "https-to-http": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=form", + origin: "https://example.com/", + "origin-when-cross-origin": "https://example.com/", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + "https-to-https": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=form", + origin: "https://example.com/", + "origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=form", + "no-referrer-when-downgrade": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=form", + "same-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin&type=form", + "strict-origin": "https://example.com/", + "strict-origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin&type=form", + }, + }, + // window.location is tested in a 2nd level iframe. + "window.location": { + "http-to-http": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=window.location", + origin: "http://example.com/", + "origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=window.location", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=window.location", + "same-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin&type=window.location", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin&type=window.location", + }, + "http-to-https": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=window.location", + origin: "http://example.com/", + "origin-when-cross-origin": "http://example.com/", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location", + "same-origin": "", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": "http://example.com/", + }, + "https-to-http": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=window.location", + origin: "https://example.com/", + "origin-when-cross-origin": "https://example.com/", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + "https-to-https": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=window.location", + origin: "https://example.com/", + "origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=window.location", + "no-referrer-when-downgrade": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location", + "same-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin&type=window.location", + "strict-origin": "https://example.com/", + "strict-origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin&type=window.location", + }, + }, + default: { + "http-to-http": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url", + origin: "http://example.com/", + "origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade", + "same-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin", + }, + "http-to-https": { + "no-referrer": "", + "unsafe-url": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url", + origin: "http://example.com/", + "origin-when-cross-origin": "http://example.com/", + "no-referrer-when-downgrade": + "http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade", + "same-origin": "", + "strict-origin": "http://example.com/", + "strict-origin-when-cross-origin": "http://example.com/", + }, + "https-to-http": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url", + origin: "https://example.com/", + "origin-when-cross-origin": "https://example.com/", + "no-referrer-when-downgrade": "", + "same-origin": "", + "strict-origin": "", + "strict-origin-when-cross-origin": "", + }, + "https-to-https": { + "no-referrer": "", + "unsafe-url": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url", + origin: "https://example.com/", + "origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin", + "no-referrer-when-downgrade": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade", + "same-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin", + "strict-origin": "https://example.com/", + "strict-origin-when-cross-origin": + "https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin", + }, + }, +}; diff --git a/dom/base/test/referrer_change_server.sjs b/dom/base/test/referrer_change_server.sjs new file mode 100644 index 0000000000..4cc11bb044 --- /dev/null +++ b/dom/base/test/referrer_change_server.sjs @@ -0,0 +1,169 @@ +var BASE_URL = "example.com/tests/dom/base/test/referrer_change_server.sjs"; + +function createTestUrl(aPolicy, aAction, aName) { + return ( + "http://" + + BASE_URL + + "?" + + "action=" + + aAction + + "&" + + "policy=" + + aPolicy + + "&" + + "name=" + + aName + + "&" + + "type=link" + ); +} + +function createTest(aMetaPolicy, aReferrerPolicy, aName) { + return ( + "\n\ + " + + '' + + "" + + '' + + aReferrerPolicy + + "" + + "\n\ + \n\ + " + ); +} + +function createTest2(aMetaPolicy, aReferrerPolicy, aName) { + return ( + "\n\ + " + + '' + + "" + + '' + + aReferrerPolicy + + "" + + "\n\ + \n\ + " + ); +} + +function handleRequest(request, response) { + var sharedKey = "referrer_change_server.sjs"; + var params = request.queryString.split("&"); + var action = params[0].split("=")[1]; + + if (action === "resetState") { + var state = getSharedState(sharedKey); + state = {}; + setSharedState(sharedKey, JSON.stringify(state)); + response.write(""); + return; + } + if (action === "test") { + // ?action=test&policy=origin&name=name + var policy = params[1].split("=")[1]; + var name = params[2].split("=")[1]; + var type = params[3].split("=")[1]; + var result = getSharedState(sharedKey); + + if (result === "") { + result = {}; + } else { + result = JSON.parse(result); + } + + if (!result.tests) { + result.tests = {}; + } + + var referrerLevel = "none"; + var test = {}; + if (request.hasHeader("Referer")) { + let referrer = request.getHeader("Referer"); + if (referrer.indexOf("referrer_change_server") > 0) { + referrerLevel = "full"; + } else if (referrer == "http://mochi.test:8888") { + referrerLevel = "origin"; + } + test.referrer = request.getHeader("Referer"); + } else { + test.referrer = ""; + } + test.policy = referrerLevel; + test.expected = policy; + + result.tests[name] = test; + + setSharedState(sharedKey, JSON.stringify(result)); + + // forward link click to redirect URL to finish test + if (type === "link") { + var loc = + "https://example.com/tests/dom/base/test/file_change_policy_redirect.html"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + } + + return; + } + if (action === "get-test-results") { + // ?action=get-result + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(getSharedState(sharedKey)); + return; + } + if (action === "generate-policy-test") { + // ?action=generate-policy-test&referrerPolicy=b64-encoded-string&name=name&newPolicy=b64-encoded-string + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + var referrerPolicy = unescape(params[1].split("=")[1]); + var name = unescape(params[2].split("=")[1]); + var newPolicy = params[3].split("=")[1]; + + response.write(createTest(referrerPolicy, newPolicy, name)); + return; + } + if (action === "generate-policy-test2") { + // ?action=generate-policy-test2&referrerPolicy=b64-encoded-string&name=name&newPolicy=b64-encoded-string + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + var referrerPolicy = unescape(params[1].split("=")[1]); + var name = unescape(params[2].split("=")[1]); + var newPolicy = params[3].split("=")[1]; + + response.write(createTest2(referrerPolicy, newPolicy, name)); + return; + } + + response.write("I don't know action " + action); +} diff --git a/dom/base/test/referrer_header.sjs b/dom/base/test/referrer_header.sjs new file mode 100644 index 0000000000..29c324b8f6 --- /dev/null +++ b/dom/base/test/referrer_header.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) { + response.setHeader("Referrer-Policy", "same-origin"); + response.write( + 'Loaded' + ); +} diff --git a/dom/base/test/referrer_helper.js b/dom/base/test/referrer_helper.js new file mode 100644 index 0000000000..ad24a027e7 --- /dev/null +++ b/dom/base/test/referrer_helper.js @@ -0,0 +1,129 @@ +// This helper expects these globals to be defined. +/* global PARAMS, SJS, testCases */ + +/* + * common functionality for iframe, anchor, and area referrer attribute tests + */ +const GET_RESULT = SJS + "ACTION=get-test-results"; +const RESET_STATE = SJS + "ACTION=resetState"; + +SimpleTest.waitForExplicitFinish(); +var advance = function () { + tests.next(); +}; + +/** + * Listen for notifications from the child. + * These are sent in case of error, or when the loads we await have completed. + */ +window.addEventListener("message", function (event) { + if (event.data == "childLoadComplete") { + // all loads happen, continue the test. + advance(); + } +}); + +/** + * helper to perform an XHR + * to do checkIndividualResults and resetState + */ +function doXHR(aUrl, onSuccess, onFail) { + // The server is at http[s]://example.com so we need cross-origin XHR. + var xhr = new XMLHttpRequest({ mozSystem: true }); + xhr.responseType = "json"; + xhr.onload = function () { + onSuccess(xhr); + }; + xhr.onerror = function () { + onFail(xhr); + }; + xhr.open("GET", "http" + aUrl, true); + xhr.send(null); +} + +/** + * Grabs the results via XHR and passes to checker. + */ +function checkIndividualResults(aTestname, aExpectedReferrer, aName) { + var onload = xhr => { + var results = xhr.response; + info(JSON.stringify(xhr.response)); + ok(aName in results, aName + " tests have to be performed."); + is( + results[aName].policy, + aExpectedReferrer, + aTestname + + " --- " + + results[aName].policy + + " (" + + results[aName].referrer + + ")" + ); + advance(); + }; + var onerror = xhr => { + ok(false, "Can't get results from the counter server."); + SimpleTest.finish(); + }; + doXHR(GET_RESULT, onload, onerror); +} + +function resetState() { + doXHR(RESET_STATE, advance, function (xhr) { + ok(false, "error in reset state"); + SimpleTest.finish(); + }); +} + +/** + * testing if referrer header is sent correctly + */ +var tests = (function* () { + yield SpecialPowers.pushPrefEnv( + { set: [["security.mixed_content.block_active_content", false]] }, + advance + ); + yield SpecialPowers.pushPrefEnv( + { set: [["network.http.referer.disallowRelaxingDefault", false]] }, + advance + ); + yield SpecialPowers.pushPermissions( + [{ type: "systemXHR", allow: true, context: document }], + advance + ); + + var iframe = document.getElementById("testframe"); + + for (var j = 0; j < testCases.length; j++) { + if (testCases[j].PREFS) { + yield SpecialPowers.pushPrefEnv({ set: testCases[j].PREFS }, advance); + } + + var actions = testCases[j].ACTION; + var subTests = testCases[j].TESTS; + for (var k = 0; k < actions.length; k++) { + var actionString = actions[k]; + for (var i = 0; i < subTests.length; i++) { + yield resetState(); + var searchParams = new URLSearchParams(); + searchParams.append("ACTION", actionString); + searchParams.append("NAME", subTests[i].NAME); + for (var l of PARAMS) { + if (subTests[i][l]) { + searchParams.append(l, subTests[i][l]); + } + } + var schemeFrom = subTests[i].SCHEME_FROM || "http"; + yield (iframe.src = schemeFrom + SJS + searchParams.toString()); + yield checkIndividualResults( + subTests[i].DESC, + subTests[i].RESULT, + subTests[i].NAME + ); + } + } + } + + // complete. + SimpleTest.finish(); +})(); diff --git a/dom/base/test/referrer_testserver.sjs b/dom/base/test/referrer_testserver.sjs new file mode 100644 index 0000000000..7a1476004e --- /dev/null +++ b/dom/base/test/referrer_testserver.sjs @@ -0,0 +1,691 @@ +/* + * Test server for iframe, anchor, and area referrer attributes. + * https://bugzilla.mozilla.org/show_bug.cgi?id=1175736 + * Also server for further referrer tests such as redirecting tests + * bug 1174913, bug 1175736, bug 1184781 + */ + +const SJS = "referrer_testserver.sjs?"; +const SJS_PATH = "/tests/dom/base/test/"; +const BASE_ORIGIN = "example.com"; +const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS; +const SHARED_KEY = SJS; +const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS; +const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS; + +const IMG_BYTES = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + + "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" +); + +function createTestUrl( + aPolicy, + aAction, + aName, + aType, + aSchemeFrom, + aSchemeTo, + crossOrigin, + referrerPolicyHeader +) { + var schemeTo = aSchemeTo || "http"; + var schemeFrom = aSchemeFrom || "http"; + var rpHeader = referrerPolicyHeader || ""; + var url = schemeTo + "://"; + url += crossOrigin ? CROSS_ORIGIN_URL : BASE_URL; + url += + "ACTION=" + + aAction + + "&" + + "policy=" + + aPolicy + + "&" + + "NAME=" + + aName + + "&" + + "type=" + + aType + + "&" + + "RP_HEADER=" + + rpHeader + + "&" + + "SCHEME_FROM=" + + schemeFrom; + return url; +} + +// test page using iframe referrer attribute +// if aParams are set this creates a test where the iframe url is a redirect +function createIframeTestPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aParams, + aSchemeFrom, + aSchemeTo, + aChangingMethod +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = ``; + } + var changeString = ""; + if (aChangingMethod === "setAttribute") { + changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; + } else if (aChangingMethod === "property") { + changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`; + } + var iFrameString = ``; + var iframeUrl = ""; + if (aParams) { + aParams.delete("ACTION"); + aParams.append("ACTION", "redirectIframe"); + iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); + } else { + iframeUrl = createTestUrl( + aAttributePolicy, + "test", + aName, + "iframe", + aSchemeFrom, + aSchemeTo + ); + } + + return ` + + + ${metaString} + + + ${iFrameString} + + + `; +} + +function buildAnchorString( + aMetaPolicy, + aReferrerPolicy, + aName, + aRelString, + aSchemeFrom, + aSchemeTo +) { + if (aReferrerPolicy) { + return `${aReferrerPolicy}`; + } + return `link`; +} + +function buildAreaString( + aMetaPolicy, + aReferrerPolicy, + aName, + aRelString, + aSchemeFrom, + aSchemeTo +) { + var result = `image`; + result += ``; + if (aReferrerPolicy) { + result += `theArea`; + } else { + result += `theArea`; + } + result += ``; + + return result; +} + +// test page using anchor or area referrer attribute +function createAETestPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aRel, + aStringBuilder, + aSchemeFrom, + aSchemeTo, + aChangingMethod +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = ``; + } + var changeString = ""; + if (aChangingMethod === "setAttribute") { + changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; + } else if (aChangingMethod === "property") { + changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`; + } + var relString = ""; + if (aRel) { + relString = `rel="noreferrer"`; + } + var elementString = aStringBuilder( + aMetaPolicy, + aAttributePolicy, + aName, + relString, + aSchemeFrom, + aSchemeTo + ); + + return ` + + ${metaString} + + ${elementString} + + + `; +} + +// test page using anchor target=_blank rel=noopener +function createTargetBlankRefferer( + aMetaPolicy, + aName, + aSchemeFrom, + aSchemeTo, + aRpHeader +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = ``; + } + var elementString = `link`; + + return ` + + ${metaString} + + ${elementString} + + + `; +} + +// creates test page with img that is a redirect +function createRedirectImgTestCase(aParams, aAttributePolicy) { + var metaString = ""; + if (aParams.has("META_POLICY")) { + metaString = ``; + } + aParams.delete("ACTION"); + aParams.append("ACTION", "redirectImg"); + var imgUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); + + return ` + + + + ${metaString} + Test referrer policies on redirect (img) + + + + + + `; +} + +// test page using link referrer attribute +function createLinkPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aRel, + aStringBuilder, + aSchemeFrom, + aSchemeTo, + aTestType +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = ``; + } + + var changeString = ""; + var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy; + var elementString = aStringBuilder( + policy, + aName, + aRel, + aSchemeFrom, + aSchemeTo, + aTestType + ); + + if (aTestType === "setAttribute") { + changeString = `var link = document.getElementById("test_link"); + link.setAttribute("referrerpolicy", "${aNewAttributePolicy}"); + link.href = "${createTestUrl( + policy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}";`; + } else if (aTestType === "property") { + changeString = `var link = document.getElementById("test_link"); + link.referrerPolicy = "${aNewAttributePolicy}"; + link.href = "${createTestUrl( + policy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}";`; + } + + return ` + + + ${metaString} + + + ${elementString} + + + `; +} + +function createFetchUserControlRPTestCase( + aName, + aSchemeFrom, + aSchemeTo, + crossOrigin +) { + var srcUrl = createTestUrl( + "", + "test", + aName, + "fetch", + aSchemeFrom, + aSchemeTo, + crossOrigin + ); + + return ` + + + + Test user control referrer policies + + + + + `; +} + +function buildLinkString( + aPolicy, + aName, + aRel, + aSchemeFrom, + aSchemeTo, + aTestType +) { + var href = ""; + var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`; + var policy = ""; + var asString = ""; + var relString = ""; + + if (aRel) { + relString = `rel="${aRel}"`; + } + + if (aPolicy) { + policy = `referrerpolicy=${aPolicy}`; + } + + if (aRel == "preload") { + asString = 'as="image"'; + } + + if (!aTestType) { + href = `href=${createTestUrl( + aPolicy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}`; + } + + return ``; +} + +// eslint-disable-next-line complexity +function handleRequest(request, response) { + var params = new URLSearchParams(request.queryString); + var action = params.get("ACTION"); + var schemeFrom = params.get("SCHEME_FROM") || "http"; + var schemeTo = params.get("SCHEME_TO") || "http"; + var crossOrigin = params.get("CROSS_ORIGIN") || false; + var referrerPolicyHeader = params.get("RP_HEADER") || ""; + + response.setHeader("Access-Control-Allow-Origin", "*", false); + if (referrerPolicyHeader) { + response.setHeader("Referrer-Policy", referrerPolicyHeader, false); + } + + if (action === "resetState") { + setSharedState(SHARED_KEY, "{}"); + response.write(""); + return; + } + if (action === "get-test-results") { + // ?action=get-result + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(getSharedState(SHARED_KEY)); + return; + } + if (action === "redirect") { + response.write( + '' + ); + return; + } + if (action === "redirectImg") { + params.delete("ACTION"); + params.append("ACTION", "test"); + params.append("type", "img"); + // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect + response.setStatusLine("1.1", 302, "found"); + response.setHeader( + "Location", + "http://" + CROSS_ORIGIN_URL + params.toString(), + false + ); + return; + } + if (action === "redirectIframe") { + params.delete("ACTION"); + params.append("ACTION", "test"); + params.append("type", "iframe"); + // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect + response.setStatusLine("1.1", 302, "found"); + response.setHeader( + "Location", + "http://" + CROSS_ORIGIN_URL + params.toString(), + false + ); + return; + } + if (action === "test") { + // ?action=test&policy=origin&name=name + var policy = params.get("policy"); + var name = params.get("NAME"); + var type = params.get("type"); + var result = getSharedState(SHARED_KEY); + + result = result ? JSON.parse(result) : {}; + + var referrerLevel = "none"; + var test = {}; + if (request.hasHeader("Referer")) { + var referrer = request.getHeader("Referer"); + if (referrer.indexOf("referrer_testserver") > 0) { + referrerLevel = "full"; + } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) { + referrerLevel = "origin"; + } else { + // this is never supposed to happen + referrerLevel = "other-origin"; + } + test.referrer = referrer; + } else { + test.referrer = ""; + } + test.policy = referrerLevel; + test.expected = policy; + + result[name] = test; + + setSharedState(SHARED_KEY, JSON.stringify(result)); + + if (type === "img" || type == "link_element_preload") { + // return image + response.setHeader("Content-Type", "image/png"); + response.write(IMG_BYTES); + return; + } + if (type === "iframe") { + // return iframe page + response.write("I am the iframe"); + return; + } + if (type === "link") { + // forward link click to redirect URL to finish test + var loc = "http://" + BASE_URL + "ACTION=redirect"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + } + return; + } + + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + + // parse test arguments and start test + var attributePolicy = params.get("ATTRIBUTE_POLICY") || ""; + var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || ""; + var metaPolicy = params.get("META_POLICY") || ""; + var rel = params.get("REL") || ""; + var name = params.get("NAME"); + + // anchor & area + var _getPage = createAETestPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + rel + ); + var _getAnchorPage = _getPage.bind( + null, + buildAnchorString, + schemeFrom, + schemeTo + ); + var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo); + + // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder + if (action === "generate-anchor-policy-test") { + response.write(_getAnchorPage()); + return; + } + if (action === "generate-anchor-changing-policy-test-set-attribute") { + response.write(_getAnchorPage("setAttribute")); + return; + } + if (action === "generate-anchor-changing-policy-test-property") { + response.write(_getAnchorPage("property")); + return; + } + if (action === "generate-area-policy-test") { + response.write(_getAreaPage()); + return; + } + if (action === "generate-area-changing-policy-test-set-attribute") { + response.write(_getAreaPage("setAttribute")); + return; + } + if (action === "generate-area-changing-policy-test-property") { + response.write(_getAreaPage("property")); + return; + } + if (action === "generate-anchor-target-blank-policy-test") { + response.write( + createTargetBlankRefferer( + metaPolicy, + name, + schemeFrom, + schemeTo, + referrerPolicyHeader + ) + ); + return; + } + + // iframe + _getPage = createIframeTestPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + "", + schemeFrom, + schemeTo + ); + + // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod + if (action === "generate-iframe-policy-test") { + response.write(_getPage()); + return; + } + if (action === "generate-iframe-changing-policy-test-set-attribute") { + response.write(_getPage("setAttribute")); + return; + } + if (action === "generate-iframe-changing-policy-test-property") { + response.write(_getPage("property")); + return; + } + + // redirect tests with img and iframe + if (action === "generate-img-redirect-policy-test") { + response.write(createRedirectImgTestCase(params, attributePolicy)); + return; + } + if (action === "generate-iframe-redirect-policy-test") { + response.write( + createIframeTestPageUsingRefferer( + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + params, + schemeFrom, + schemeTo + ) + ); + return; + } + + var _getPage = createLinkPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + rel + ); + var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo); + + // link + if (action === "generate-link-policy-test") { + response.write(_getLinkPage()); + return; + } + if (action === "generate-link-policy-test-set-attribute") { + response.write(_getLinkPage("setAttribute")); + return; + } + if (action === "generate-link-policy-test-property") { + response.write(_getLinkPage("property")); + return; + } + + if (action === "generate-fetch-user-control-policy-test") { + response.write( + createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin) + ); + return; + } + + response.write("I don't know action " + action); +} diff --git a/dom/base/test/reftest/mixed-bmp-png.ico b/dom/base/test/reftest/mixed-bmp-png.ico new file mode 100644 index 0000000000..32e2c4995c Binary files /dev/null and b/dom/base/test/reftest/mixed-bmp-png.ico differ diff --git a/dom/base/test/reftest/reftest.list b/dom/base/test/reftest/reftest.list new file mode 100644 index 0000000000..8aa3f3b949 --- /dev/null +++ b/dom/base/test/reftest/reftest.list @@ -0,0 +1,7 @@ +== test_bug920877.html test_bug920877-ref.html +HTTP == test_xmlPrettyPrint_csp.xml test_xmlPrettyPrint_csp-ref.xml +# Ordinarily, reftests use a browser.viewport.desktopWidth of 800px, same as the +# size of the reftest document. This test however needs something more representative +# of a real mobile device, where the desktop viewport width doesn't match the +# width of the device screen. +test-pref(dom.meta-viewport.enabled,true) test-pref(browser.viewport.desktopWidth,1200) == test_bug1525662.txt test_bug1525662-ref.html diff --git a/dom/base/test/reftest/test_bug1525662-ref.html b/dom/base/test/reftest/test_bug1525662-ref.html new file mode 100644 index 0000000000..063daf7615 --- /dev/null +++ b/dom/base/test/reftest/test_bug1525662-ref.html @@ -0,0 +1,15 @@ + + + + + +
                      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras ac velit sed tellus facilisis euismod. Proin vel nulla vel turpis tristique dignissim. Donec lacus ipsum, eleifend ut, volutpat a, ultrices adipiscing, arcu. Etiam ligula dolor, adipiscing ut, porta vitae, bibendum non, dolor. Mauris ligula. Sed placerat tincidunt elit. Vestibulum non libero. Curabitur cursus tortor id sem. Integer consectetuer auctor lacus. Proin nisl nisi, pulvinar eget, pharetra at, aliquam eu, velit. Morbi fringilla. Quisque faucibus, mauris posuere vulputate interdum, lectus libero sollicitudin tellus, sit amet ultrices enim purus ac mauris. Pellentesque sit amet mauris eu ante aliquet egestas. Mauris dapibus, velit consectetuer tristique luctus, enim augue pulvinar libero, fringilla dictum lectus felis eu ligula. In ac lorem.
                      +
                      +Integer laoreet. Ut ultricies arcu nec est. Aenean varius nisl ut odio. Nullam arcu. Vestibulum non pede. Proin vel est. Nam condimentum fermentum dui. Donec at arcu. Donec at libero adipiscing odio mattis dapibus. Suspendisse libero neque, faucibus sed, facilisis et, convallis sit amet, justo. Duis purus tortor, ornare ac, convallis ut, pretium et, tellus. Nam accumsan, ipsum eget accumsan mollis, sapien dolor adipiscing metus, id tincidunt ipsum metus sed nulla. Praesent hendrerit lectus eget tortor. Morbi id lectus et elit ultrices hendrerit. Cras gravida velit sed mauris. Proin lacinia tempus est. Sed sapien tortor, fringilla vel, elementum in, volutpat ac, ante. Vivamus eu tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
                      +
                      +Mauris in sem ac felis pretium placerat. Donec tempus cursus sem. Aliquam scelerisque porttitor sem. Curabitur consectetuer, pede vitae aliquam aliquet, sapien lacus vehicula neque, ut rhoncus nibh neque sed velit. In rhoncus, nulla eu dignissim egestas, diam nibh hendrerit mauris, condimentum laoreet sapien arcu quis mi. Sed euismod sem. Nulla non ligula sed lacus tempor molestie. Quisque varius. In hac habitasse platea dictumst. Sed felis ipsum, consequat et, blandit vitae, tincidunt id, quam. Nunc nunc. Duis gravida. In massa neque, cursus quis, rutrum sed, semper quis, erat. Donec enim. Suspendisse condimentum eros vel elit. Vestibulum adipiscing erat id lorem. Maecenas enim dui, cursus a, pulvinar ac, rutrum sed, sem. Suspendisse gravida ante vel lectus.
                      +
                      +Vestibulum molestie, ante at dignissim venenatis, pede urna dictum arcu, vel ullamcorper ligula eros eget metus. Pellentesque nec nisl. Morbi ut nibh. Aenean mauris. Mauris rutrum justo nec velit. Nunc condimentum tortor id augue. Quisque semper massa eget nibh. Maecenas ac odio pretium lorem tincidunt faucibus. Sed congue. Cras sit amet orci ut ligula cursus congue. Etiam laoreet lacus sit amet tortor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus accumsan. Ut gravida urna hendrerit leo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
                      +
                      + + diff --git a/dom/base/test/reftest/test_bug1525662.txt b/dom/base/test/reftest/test_bug1525662.txt new file mode 100644 index 0000000000..33fd1fd851 --- /dev/null +++ b/dom/base/test/reftest/test_bug1525662.txt @@ -0,0 +1,7 @@ +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras ac velit sed tellus facilisis euismod. Proin vel nulla vel turpis tristique dignissim. Donec lacus ipsum, eleifend ut, volutpat a, ultrices adipiscing, arcu. Etiam ligula dolor, adipiscing ut, porta vitae, bibendum non, dolor. Mauris ligula. Sed placerat tincidunt elit. Vestibulum non libero. Curabitur cursus tortor id sem. Integer consectetuer auctor lacus. Proin nisl nisi, pulvinar eget, pharetra at, aliquam eu, velit. Morbi fringilla. Quisque faucibus, mauris posuere vulputate interdum, lectus libero sollicitudin tellus, sit amet ultrices enim purus ac mauris. Pellentesque sit amet mauris eu ante aliquet egestas. Mauris dapibus, velit consectetuer tristique luctus, enim augue pulvinar libero, fringilla dictum lectus felis eu ligula. In ac lorem. + +Integer laoreet. Ut ultricies arcu nec est. Aenean varius nisl ut odio. Nullam arcu. Vestibulum non pede. Proin vel est. Nam condimentum fermentum dui. Donec at arcu. Donec at libero adipiscing odio mattis dapibus. Suspendisse libero neque, faucibus sed, facilisis et, convallis sit amet, justo. Duis purus tortor, ornare ac, convallis ut, pretium et, tellus. Nam accumsan, ipsum eget accumsan mollis, sapien dolor adipiscing metus, id tincidunt ipsum metus sed nulla. Praesent hendrerit lectus eget tortor. Morbi id lectus et elit ultrices hendrerit. Cras gravida velit sed mauris. Proin lacinia tempus est. Sed sapien tortor, fringilla vel, elementum in, volutpat ac, ante. Vivamus eu tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; + +Mauris in sem ac felis pretium placerat. Donec tempus cursus sem. Aliquam scelerisque porttitor sem. Curabitur consectetuer, pede vitae aliquam aliquet, sapien lacus vehicula neque, ut rhoncus nibh neque sed velit. In rhoncus, nulla eu dignissim egestas, diam nibh hendrerit mauris, condimentum laoreet sapien arcu quis mi. Sed euismod sem. Nulla non ligula sed lacus tempor molestie. Quisque varius. In hac habitasse platea dictumst. Sed felis ipsum, consequat et, blandit vitae, tincidunt id, quam. Nunc nunc. Duis gravida. In massa neque, cursus quis, rutrum sed, semper quis, erat. Donec enim. Suspendisse condimentum eros vel elit. Vestibulum adipiscing erat id lorem. Maecenas enim dui, cursus a, pulvinar ac, rutrum sed, sem. Suspendisse gravida ante vel lectus. + +Vestibulum molestie, ante at dignissim venenatis, pede urna dictum arcu, vel ullamcorper ligula eros eget metus. Pellentesque nec nisl. Morbi ut nibh. Aenean mauris. Mauris rutrum justo nec velit. Nunc condimentum tortor id augue. Quisque semper massa eget nibh. Maecenas ac odio pretium lorem tincidunt faucibus. Sed congue. Cras sit amet orci ut ligula cursus congue. Etiam laoreet lacus sit amet tortor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus accumsan. Ut gravida urna hendrerit leo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. diff --git a/dom/base/test/reftest/test_bug920877-ref.html b/dom/base/test/reftest/test_bug920877-ref.html new file mode 100644 index 0000000000..1a593e5849 --- /dev/null +++ b/dom/base/test/reftest/test_bug920877-ref.html @@ -0,0 +1,20 @@ + + + + + diff --git a/dom/base/test/reftest/test_bug920877.html b/dom/base/test/reftest/test_bug920877.html new file mode 100644 index 0000000000..18bae4009e --- /dev/null +++ b/dom/base/test/reftest/test_bug920877.html @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/dom/base/test/reftest/test_xmlPrettyPrint_csp-ref.xml b/dom/base/test/reftest/test_xmlPrettyPrint_csp-ref.xml new file mode 100644 index 0000000000..7b3c180912 --- /dev/null +++ b/dom/base/test/reftest/test_xmlPrettyPrint_csp-ref.xml @@ -0,0 +1,4 @@ + + + This is an XML document + diff --git a/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml b/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml new file mode 100644 index 0000000000..7b3c180912 --- /dev/null +++ b/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml @@ -0,0 +1,4 @@ + + + This is an XML document + diff --git a/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml^headers^ b/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml^headers^ new file mode 100644 index 0000000000..93d453bd3b --- /dev/null +++ b/dom/base/test/reftest/test_xmlPrettyPrint_csp.xml^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'none'; diff --git a/dom/base/test/script-1_bug597345.sjs b/dom/base/test/script-1_bug597345.sjs new file mode 100644 index 0000000000..7beb3283fc --- /dev/null +++ b/dom/base/test/script-1_bug597345.sjs @@ -0,0 +1,20 @@ +// timer has to be alive so it can't be eaten by the GC. +var timer; + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/javascript", false); + // The "stray" open comment at the end of the write is important! + response.write( + "document.write(\" + + + Test for Bug 338583 + + + + + + +Mozilla Bug 716841 +

                      + +
                      +
                      +
                      + + + + diff --git a/dom/base/test/test_Image_constructor.html b/dom/base/test/test_Image_constructor.html new file mode 100644 index 0000000000..4c4bb70e54 --- /dev/null +++ b/dom/base/test/test_Image_constructor.html @@ -0,0 +1,32 @@ + + + + + + + + Test for Bug 862702 + + + + + +Mozilla Bug 862702 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_NodeIterator_basics_filters.xhtml b/dom/base/test/test_NodeIterator_basics_filters.xhtml new file mode 100644 index 0000000000..768782dc2a --- /dev/null +++ b/dom/base/test/test_NodeIterator_basics_filters.xhtml @@ -0,0 +1,178 @@ + + + + DOM Traversal: NodeIterator: Basics and Filters + + + + +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_NodeIterator_mutations_1.xhtml b/dom/base/test/test_NodeIterator_mutations_1.xhtml new file mode 100644 index 0000000000..5f6dc2f861 --- /dev/null +++ b/dom/base/test/test_NodeIterator_mutations_1.xhtml @@ -0,0 +1,204 @@ + + + + DOM Traversal: NodeIterator: Mutations (1/x) + + + + +

                      + +
                      +
                      diff --git a/dom/base/test/test_NodeIterator_mutations_2.html b/dom/base/test/test_NodeIterator_mutations_2.html new file mode 100644 index 0000000000..47d7b8b5e4 --- /dev/null +++ b/dom/base/test/test_NodeIterator_mutations_2.html @@ -0,0 +1,112 @@ + + + + + DOM Traversal: NodeIterator: Mutations (2/x) + + + +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_NodeIterator_mutations_3.html b/dom/base/test/test_NodeIterator_mutations_3.html new file mode 100644 index 0000000000..3eb23ee3ce --- /dev/null +++ b/dom/base/test/test_NodeIterator_mutations_3.html @@ -0,0 +1,160 @@ + + + + DOM Traversal: NodeIterator: Mutations (3/x) + + + +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_anchor_area_referrer.html b/dom/base/test/test_anchor_area_referrer.html new file mode 100644 index 0000000000..7e6992b404 --- /dev/null +++ b/dom/base/test/test_anchor_area_referrer.html @@ -0,0 +1,127 @@ + + + + + Test anchor and area policy attribute for Bug 1174913 + + + + + + + + + + + + + diff --git a/dom/base/test/test_anchor_area_referrer_changing.html b/dom/base/test/test_anchor_area_referrer_changing.html new file mode 100644 index 0000000000..e8d6c249fb --- /dev/null +++ b/dom/base/test/test_anchor_area_referrer_changing.html @@ -0,0 +1,66 @@ + + + + + Test anchor and area policy attribute for Bug 1174913 + + + + + + + + + + + + + diff --git a/dom/base/test/test_anchor_area_referrer_invalid.html b/dom/base/test/test_anchor_area_referrer_invalid.html new file mode 100644 index 0000000000..f5687b7180 --- /dev/null +++ b/dom/base/test/test_anchor_area_referrer_invalid.html @@ -0,0 +1,74 @@ + + + + + Test anchor and area policy attribute for Bug 1174913 + + + + + + + + + + + + + diff --git a/dom/base/test/test_anchor_area_referrer_rel.html b/dom/base/test/test_anchor_area_referrer_rel.html new file mode 100644 index 0000000000..71cd4f6390 --- /dev/null +++ b/dom/base/test/test_anchor_area_referrer_rel.html @@ -0,0 +1,50 @@ + + + + + Test anchor and area policy attribute for Bug 1174913 + + + + + + + + + + + + + diff --git a/dom/base/test/test_anchor_target_blank_referrer.html b/dom/base/test/test_anchor_target_blank_referrer.html new file mode 100644 index 0000000000..b494c28017 --- /dev/null +++ b/dom/base/test/test_anchor_target_blank_referrer.html @@ -0,0 +1,136 @@ + + + + + Test anchor target=_blank rel=noopener referrer header for Bug 1502678 + + + + + + + + + + + + + diff --git a/dom/base/test/test_anonymousContent_api.html b/dom/base/test/test_anonymousContent_api.html new file mode 100644 index 0000000000..ee37c202d1 --- /dev/null +++ b/dom/base/test/test_anonymousContent_api.html @@ -0,0 +1,30 @@ + + + +Test for Bug 1020244 - Test the chrome-only AnonymousContent API + + +Mozilla Bug 1020244 + diff --git a/dom/base/test/test_anonymousContent_append_after_reflow.html b/dom/base/test/test_anonymousContent_append_after_reflow.html new file mode 100644 index 0000000000..0bdca2c502 --- /dev/null +++ b/dom/base/test/test_anonymousContent_append_after_reflow.html @@ -0,0 +1,35 @@ + + + + +Test for Bug 1020244 - Make sure anonymous content still works after a reflow (after the canvasframe has been reconstructed) + + +
                      +
                      text content
                      +
                      + diff --git a/dom/base/test/test_anonymousContent_canvas.html b/dom/base/test/test_anonymousContent_canvas.html new file mode 100644 index 0000000000..d5a5a1e6c4 --- /dev/null +++ b/dom/base/test/test_anonymousContent_canvas.html @@ -0,0 +1,48 @@ + + + + +Test for Bug 1212477 - Needs a way to access to <canvas>'s context (2d, webgl) from Anonymous Content API + + +Mozilla Bug 1212477 +
                      +
                      text content
                      + + + +
                      + diff --git a/dom/base/test/test_anonymousContent_insert.html b/dom/base/test/test_anonymousContent_insert.html new file mode 100644 index 0000000000..ce73a1521f --- /dev/null +++ b/dom/base/test/test_anonymousContent_insert.html @@ -0,0 +1,42 @@ + + + + +Test for Bug 1020244 - Insert content using the AnonymousContent API, several times, and don't remove it + + +Mozilla Bug 1020244 +
                      +
                      text content
                      +
                      + diff --git a/dom/base/test/test_anonymousContent_manipulate_content.html b/dom/base/test/test_anonymousContent_manipulate_content.html new file mode 100644 index 0000000000..e67bfdfea6 --- /dev/null +++ b/dom/base/test/test_anonymousContent_manipulate_content.html @@ -0,0 +1,41 @@ + + + + +Test for Bug 1020244 - Manipulate content created with the AnonymousContent API + + +Mozilla Bug 1020244 +
                      +
                      text content
                      +
                      + diff --git a/dom/base/test/test_anonymousContent_style_csp.html b/dom/base/test/test_anonymousContent_style_csp.html new file mode 100644 index 0000000000..2aa82a6b2a --- /dev/null +++ b/dom/base/test/test_anonymousContent_style_csp.html @@ -0,0 +1,23 @@ + + + + +Test for Bug 1185351 - Make sure that we don't enforce CSP on styles for AnonymousContent + + +
                      +
                      text content
                      +
                      + diff --git a/dom/base/test/test_anonymousContent_style_csp.html^headers^ b/dom/base/test/test_anonymousContent_style_csp.html^headers^ new file mode 100644 index 0000000000..b7b3c8a4f9 --- /dev/null +++ b/dom/base/test/test_anonymousContent_style_csp.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' diff --git a/dom/base/test/test_anonymousContent_xul_window.xhtml b/dom/base/test/test_anonymousContent_xul_window.xhtml new file mode 100644 index 0000000000..b81f827075 --- /dev/null +++ b/dom/base/test/test_anonymousContent_xul_window.xhtml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/base/test/test_async_setTimeout_stack.html b/dom/base/test/test_async_setTimeout_stack.html new file mode 100644 index 0000000000..773a923be3 --- /dev/null +++ b/dom/base/test/test_async_setTimeout_stack.html @@ -0,0 +1,60 @@ + + + + + + Test for Bug 1142577 - Async stacks for setTimeout + + + + + Mozilla Bug 1142577 +
                      
                      +  
                      +
                      +
                      diff --git a/dom/base/test/test_async_setTimeout_stack_across_globals.html b/dom/base/test/test_async_setTimeout_stack_across_globals.html
                      new file mode 100644
                      index 0000000000..358aa21abe
                      --- /dev/null
                      +++ b/dom/base/test/test_async_setTimeout_stack_across_globals.html
                      @@ -0,0 +1,60 @@
                      +
                      +
                      +
                      +
                      +  
                      +  Test for Bug 1142577 - Async stacks for setTimeout
                      +  
                      +  
                      +
                      +
                      +  Mozilla Bug 1142577
                      +  
                      
                      +  
                      +  
                      +
                      +
                      diff --git a/dom/base/test/test_base.xhtml b/dom/base/test/test_base.xhtml
                      new file mode 100644
                      index 0000000000..b61bc72f68
                      --- /dev/null
                      +++ b/dom/base/test/test_base.xhtml
                      @@ -0,0 +1,39 @@
                      +
                      +
                      +  Test for base URIs
                      +  
                      +  
                      +  
                      +
                      +
                      +

                      text

                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_blockParsing.html b/dom/base/test/test_blockParsing.html new file mode 100644 index 0000000000..af4c8aaac5 --- /dev/null +++ b/dom/base/test/test_blockParsing.html @@ -0,0 +1,136 @@ + + + + Test for document.blockParsing + + + + + + + diff --git a/dom/base/test/test_blocking_image.html b/dom/base/test/test_blocking_image.html new file mode 100644 index 0000000000..e579d9f025 --- /dev/null +++ b/dom/base/test/test_blocking_image.html @@ -0,0 +1,87 @@ + + + + + Test for Bug 1267075 + + + + + +Mozilla Bug 1267075 +
                      +
                      +
                      +

                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1008126.html b/dom/base/test/test_bug1008126.html new file mode 100644 index 0000000000..414f2727ec --- /dev/null +++ b/dom/base/test/test_bug1008126.html @@ -0,0 +1,62 @@ + + + + + + + Test for Bug 1008126 + + + + +Mozilla Bug 1008126 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1016960.html b/dom/base/test/test_bug1016960.html new file mode 100644 index 0000000000..d801a1dba5 --- /dev/null +++ b/dom/base/test/test_bug1016960.html @@ -0,0 +1,30 @@ + + + + + + Test for Bug 1016960 + + + + + +Mozilla Bug 1016960 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1022229.html b/dom/base/test/test_bug1022229.html new file mode 100644 index 0000000000..7663cc22d0 --- /dev/null +++ b/dom/base/test/test_bug1022229.html @@ -0,0 +1,33 @@ + + + + + + Test for Bug 1022229 + + + + + +Mozilla Bug 1022229 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1025933.html b/dom/base/test/test_bug1025933.html new file mode 100644 index 0000000000..e578ebef20 --- /dev/null +++ b/dom/base/test/test_bug1025933.html @@ -0,0 +1,41 @@ + + + + + + Test for Bug 1025933 + + + + + +Mozilla Bug 1025933 +

                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1037687.html b/dom/base/test/test_bug1037687.html new file mode 100644 index 0000000000..62f886c837 --- /dev/null +++ b/dom/base/test/test_bug1037687.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 1037687 + + + + +Mozilla Bug 1037687 +

                      + +
                      +
                      + + + diff --git a/dom/base/test/test_bug1037687_subframe.html b/dom/base/test/test_bug1037687_subframe.html new file mode 100644 index 0000000000..4258f772b6 --- /dev/null +++ b/dom/base/test/test_bug1037687_subframe.html @@ -0,0 +1,46 @@ + + + + + + +
                      + + diff --git a/dom/base/test/test_bug1043106.html b/dom/base/test/test_bug1043106.html new file mode 100644 index 0000000000..42d6cfff57 --- /dev/null +++ b/dom/base/test/test_bug1043106.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 1043106 + + + + + Mozilla Bug 1043106 + + + + diff --git a/dom/base/test/test_bug1057176.html b/dom/base/test/test_bug1057176.html new file mode 100644 index 0000000000..e9e516ac1e --- /dev/null +++ b/dom/base/test/test_bug1057176.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 1057176 + + + + + +Mozilla Bug 1057176 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1060938.html b/dom/base/test/test_bug1060938.html new file mode 100644 index 0000000000..451ed0d6fb --- /dev/null +++ b/dom/base/test/test_bug1060938.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 1060938 + + + + + + Mozilla Bug 1060938 +

                      + +
                      +  
                      +  
                      +
                      diff --git a/dom/base/test/test_bug1064481.html b/dom/base/test/test_bug1064481.html
                      new file mode 100644
                      index 0000000000..9ce32f4d49
                      --- /dev/null
                      +++ b/dom/base/test/test_bug1064481.html
                      @@ -0,0 +1,24 @@
                      +
                      +
                      +
                      +
                      +  
                      +  Test for Bug 1064481
                      +  
                      +  
                      +
                      +
                      +  Mozilla Bug 1064481
                      +  
                      +  
                      +
                      +
                      diff --git a/dom/base/test/test_bug1070015.html b/dom/base/test/test_bug1070015.html
                      new file mode 100644
                      index 0000000000..5debff4dc0
                      --- /dev/null
                      +++ b/dom/base/test/test_bug1070015.html
                      @@ -0,0 +1,53 @@
                      +
                      +
                      +
                      +
                      +  Test for Bug 1070015
                      +  
                      +  
                      +  
                      +
                      +
                      +Mozilla Bug 1070015
                      +

                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1075702.html b/dom/base/test/test_bug1075702.html new file mode 100644 index 0000000000..a3842a21a5 --- /dev/null +++ b/dom/base/test/test_bug1075702.html @@ -0,0 +1,77 @@ + + + + + + Test for Bug 1075702 + + + + + + Mozilla Bug 1075702 +

                      + +
                      +
                      +
                      +
                      diff --git a/dom/base/test/test_bug1091883.html b/dom/base/test/test_bug1091883.html
                      new file mode 100644
                      index 0000000000..fd2558d89c
                      --- /dev/null
                      +++ b/dom/base/test/test_bug1091883.html
                      @@ -0,0 +1,89 @@
                      +
                      +
                      +
                      +
                      +  
                      +  
                      +  Test for Bug 1091883
                      +  
                      +  
                      +
                      +
                      +

                      Mozilla Bug 1091883

                      +

                      Results

                      +
                      Running...
                      + + + + + diff --git a/dom/base/test/test_bug1100912.html b/dom/base/test/test_bug1100912.html new file mode 100644 index 0000000000..9887f1facb --- /dev/null +++ b/dom/base/test/test_bug1100912.html @@ -0,0 +1,35 @@ + + + + + + Test for Bug 1100912 + + + + + +Mozilla Bug 1100912 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1101364.html b/dom/base/test/test_bug1101364.html new file mode 100644 index 0000000000..f3794d3dd0 --- /dev/null +++ b/dom/base/test/test_bug1101364.html @@ -0,0 +1,93 @@ + + + + +Test for Bug 1101364 + + + + + + + + + + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1118689.html b/dom/base/test/test_bug1118689.html new file mode 100644 index 0000000000..e073b6fcfa --- /dev/null +++ b/dom/base/test/test_bug1118689.html @@ -0,0 +1,40 @@ + + + + + + Test for Bug 1118689 + + + + + +Mozilla Bug 1118689 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1120222.html b/dom/base/test/test_bug1120222.html new file mode 100644 index 0000000000..f4f1bf8faa --- /dev/null +++ b/dom/base/test/test_bug1120222.html @@ -0,0 +1,31 @@ + + + + + + Test document-title-changed observer + + + + + + + diff --git a/dom/base/test/test_bug1126851.html b/dom/base/test/test_bug1126851.html new file mode 100644 index 0000000000..117aabb530 --- /dev/null +++ b/dom/base/test/test_bug1126851.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 1126851 + + + + + +Mozilla Bug 1126851 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug116083.html b/dom/base/test/test_bug116083.html new file mode 100644 index 0000000000..a1736d6cce --- /dev/null +++ b/dom/base/test/test_bug116083.html @@ -0,0 +1,120 @@ + + + + + Test for Bug 116083 + + + + + +Mozilla Bug 116083 +
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      foo bar
                      +
                      bar baz
                      +
                      bar baz
                      +
                      bar baz
                      +
                      bar baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar

                      !


                      baz
                      +
                      foo
                      bar
                      baz
                      qux
                      +
                      foo
                      bar
                      baz
                      qux
                      +
                      foo

                      +
                      foo

                      +
                      foo

                      bar
                      +
                      foo

                      bar
                      +
                      foo
                      bar
                      +
                      foo
                      bar
                      +
                      foo
                      bar
                      baz
                      +
                      foo
                      bar
                      baz
                      +


                      foo
                      +


                      foo
                      +
                      foo
                      bar
                      +
                      foo
                      bar
                      +
                      foo
                      bar
                      +
                      foo
                      bar
                      +
                      foo bar
                      +
                      + + + diff --git a/dom/base/test/test_bug1163743.html b/dom/base/test/test_bug1163743.html new file mode 100644 index 0000000000..1965909284 --- /dev/null +++ b/dom/base/test/test_bug1163743.html @@ -0,0 +1,44 @@ + + + + + + + Test policies for Bug 1163743 + + + + + + + + + + + + + diff --git a/dom/base/test/test_bug1165501.html b/dom/base/test/test_bug1165501.html new file mode 100644 index 0000000000..d0f98a9b05 --- /dev/null +++ b/dom/base/test/test_bug1165501.html @@ -0,0 +1,51 @@ + + + + + + + Test policies for Bug 1165501 + + + + + + + + + + + + + diff --git a/dom/base/test/test_bug1187157.html b/dom/base/test/test_bug1187157.html new file mode 100644 index 0000000000..d96c11e635 --- /dev/null +++ b/dom/base/test/test_bug1187157.html @@ -0,0 +1,30 @@ + + + + + + Test for Bug 1187157 + + + + +Mozilla Bug 1187157 +
                      + + + + + diff --git a/dom/base/test/test_bug1198095.html b/dom/base/test/test_bug1198095.html new file mode 100644 index 0000000000..bcc005d897 --- /dev/null +++ b/dom/base/test/test_bug1198095.html @@ -0,0 +1,71 @@ + + + + + Test for Bug 1198095 + + + + + +Mozilla Bug 1198095 + +
                      +
                      +
                      + diff --git a/dom/base/test/test_bug1222633.html b/dom/base/test/test_bug1222633.html new file mode 100644 index 0000000000..229aa5e35c --- /dev/null +++ b/dom/base/test/test_bug1222633.html @@ -0,0 +1,110 @@ + + + + + Test for Bug 1222633 + + + + +Mozilla Bug 1222633 +

                      + + + + diff --git a/dom/base/test/test_bug1222633_link_update.html b/dom/base/test/test_bug1222633_link_update.html new file mode 100644 index 0000000000..a398f648b7 --- /dev/null +++ b/dom/base/test/test_bug1222633_link_update.html @@ -0,0 +1,127 @@ + + + + + Test for Bug 1222633 + + + + +Mozilla Bug 1222633 +

                      + + + + diff --git a/dom/base/test/test_bug1238440.html b/dom/base/test/test_bug1238440.html new file mode 100644 index 0000000000..528b337c00 --- /dev/null +++ b/dom/base/test/test_bug1238440.html @@ -0,0 +1,88 @@ + + + + + Test - bug 1238440 + + + + + + + + diff --git a/dom/base/test/test_bug1250148.html b/dom/base/test/test_bug1250148.html new file mode 100644 index 0000000000..b32124ded6 --- /dev/null +++ b/dom/base/test/test_bug1250148.html @@ -0,0 +1,64 @@ + + + + + + Test for Bug 1250148 - FormData and HTML submission compatibility + + + + +
                      + + + diff --git a/dom/base/test/test_bug1259588.html b/dom/base/test/test_bug1259588.html new file mode 100644 index 0000000000..40a272f905 --- /dev/null +++ b/dom/base/test/test_bug1259588.html @@ -0,0 +1,13 @@ + + +Test for Bug 1259588 + + +
                      + diff --git a/dom/base/test/test_bug1268962.html b/dom/base/test/test_bug1268962.html new file mode 100644 index 0000000000..54f99f8456 --- /dev/null +++ b/dom/base/test/test_bug1268962.html @@ -0,0 +1,104 @@ + + + + + Test for Bug 1268962 + + + + +Mozilla Bug 1268962 +

                      + + + + diff --git a/dom/base/test/test_bug1274806.html b/dom/base/test/test_bug1274806.html new file mode 100644 index 0000000000..c8ccb0bc65 --- /dev/null +++ b/dom/base/test/test_bug1274806.html @@ -0,0 +1,31 @@ + + + + + + Test for Bug 1274806 + + + + + +Mozilla Bug 1274806 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1295852.html b/dom/base/test/test_bug1295852.html new file mode 100644 index 0000000000..a4991c6149 --- /dev/null +++ b/dom/base/test/test_bug1295852.html @@ -0,0 +1,19 @@ + + +Bug 1295852 + + + + diff --git a/dom/base/test/test_bug1307730.html b/dom/base/test/test_bug1307730.html new file mode 100644 index 0000000000..e0cad741f9 --- /dev/null +++ b/dom/base/test/test_bug1307730.html @@ -0,0 +1,44 @@ + + + + + Test for Bug 1307730 + + + + +Mozilla Bug 1307730 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1308069.html b/dom/base/test/test_bug1308069.html new file mode 100644 index 0000000000..2775ff1b7e --- /dev/null +++ b/dom/base/test/test_bug1308069.html @@ -0,0 +1,87 @@ + + + + +Bug 1308069 + + + + +Mozilla Bug 1308069 + + + diff --git a/dom/base/test/test_bug1314032.html b/dom/base/test/test_bug1314032.html new file mode 100644 index 0000000000..693eba2f62 --- /dev/null +++ b/dom/base/test/test_bug1314032.html @@ -0,0 +1,38 @@ + + + + + Test for Bug 1314032 + + + + +Mozilla Bug 1243846 +

                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1318303.html b/dom/base/test/test_bug1318303.html new file mode 100644 index 0000000000..2db8420ffc --- /dev/null +++ b/dom/base/test/test_bug1318303.html @@ -0,0 +1,47 @@ + + + + + + Test for Bug 1318303 + + + + + + diff --git a/dom/base/test/test_bug1375050.html b/dom/base/test/test_bug1375050.html new file mode 100644 index 0000000000..5f598d7469 --- /dev/null +++ b/dom/base/test/test_bug1375050.html @@ -0,0 +1,33 @@ + + + + + + Test for Bug 1375050 + + + + + +Mozilla Bug 1375050 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1381710.html b/dom/base/test/test_bug1381710.html new file mode 100644 index 0000000000..97531d1426 --- /dev/null +++ b/dom/base/test/test_bug1381710.html @@ -0,0 +1,40 @@ + + + + + Test for Mozilla Bug 1381710 + + + + +Mozilla Bug 1381710 +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1399605.html b/dom/base/test/test_bug1399605.html new file mode 100644 index 0000000000..a8e0c6453d --- /dev/null +++ b/dom/base/test/test_bug1399605.html @@ -0,0 +1,32 @@ + + + + + Test for Bug 1399605 + + + + +Mozilla Bug 1399605 +

                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1404385.html b/dom/base/test/test_bug1404385.html new file mode 100644 index 0000000000..828a44918f --- /dev/null +++ b/dom/base/test/test_bug1404385.html @@ -0,0 +1,31 @@ + + + + + Test for Bug 1404385 + + + + +Mozilla Bug 1404385 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1406102.html b/dom/base/test/test_bug1406102.html new file mode 100644 index 0000000000..a561f1e8b6 --- /dev/null +++ b/dom/base/test/test_bug1406102.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 1406102 + + + + + +Mozilla Bug 1406102 +

                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1421568.html b/dom/base/test/test_bug1421568.html new file mode 100644 index 0000000000..f4864c81c1 --- /dev/null +++ b/dom/base/test/test_bug1421568.html @@ -0,0 +1,48 @@ + + + + + + Test for Bug 1421568 + + + + + +Mozilla Bug 1421568 +

                      +
                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1433073.html b/dom/base/test/test_bug1433073.html new file mode 100644 index 0000000000..7fe91aa287 --- /dev/null +++ b/dom/base/test/test_bug1433073.html @@ -0,0 +1,89 @@ + + + + + Test bug 1433073 + + + + + + +Mozilla Bug 1433073 +

                      +
                      + + + + + + + + + + + +
                      xy
                      uv
                      +
                      + + diff --git a/dom/base/test/test_bug1472427.html b/dom/base/test/test_bug1472427.html new file mode 100644 index 0000000000..902b9cd05b --- /dev/null +++ b/dom/base/test/test_bug1472427.html @@ -0,0 +1,89 @@ + + + + + + Test for Bug 1472427 + + + + + + +Mozilla Bug 1472427 +

                      + +
                      +
                      + + diff --git a/dom/base/test/test_bug1499169.html b/dom/base/test/test_bug1499169.html new file mode 100644 index 0000000000..7d5141797d --- /dev/null +++ b/dom/base/test/test_bug1499169.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 1499169 + + + + + + + Mozilla Bug 1499169 + + + diff --git a/dom/base/test/test_bug1576154.html b/dom/base/test/test_bug1576154.html new file mode 100644 index 0000000000..eca8db6275 --- /dev/null +++ b/dom/base/test/test_bug1576154.html @@ -0,0 +1,36 @@ + + + + + Test for Bug 1576154 + + + + + +Mozilla Bug 1576154 +

                      + + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1632975.html b/dom/base/test/test_bug1632975.html new file mode 100644 index 0000000000..8b54ca47a5 --- /dev/null +++ b/dom/base/test/test_bug1632975.html @@ -0,0 +1,54 @@ + + + + + Test for Bug 1632975 + + + + + + +Mozilla Bug 1632975 +

                      + + + diff --git a/dom/base/test/test_bug1639328.html b/dom/base/test/test_bug1639328.html new file mode 100644 index 0000000000..567b97ddb5 --- /dev/null +++ b/dom/base/test/test_bug1639328.html @@ -0,0 +1,89 @@ + + +Test for bug 1639328 + + + + + + + + + + + + + + + + diff --git a/dom/base/test/test_bug1640766.html b/dom/base/test/test_bug1640766.html new file mode 100644 index 0000000000..ea77c99e59 --- /dev/null +++ b/dom/base/test/test_bug1640766.html @@ -0,0 +1,67 @@ + + + + + Test for Bug 1640766 + + + + +Mozilla Bug 1640766 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1648887.html b/dom/base/test/test_bug1648887.html new file mode 100644 index 0000000000..a185086137 --- /dev/null +++ b/dom/base/test/test_bug1648887.html @@ -0,0 +1,34 @@ + + + + +Test for Bug 1648887 + + + + +Mozilla Bug 1648887 +

                      + + +
                      + + diff --git a/dom/base/test/test_bug166235.html b/dom/base/test/test_bug166235.html new file mode 100644 index 0000000000..0431e204c2 --- /dev/null +++ b/dom/base/test/test_bug166235.html @@ -0,0 +1,156 @@ + + + + + Test for Bug 166235 + + + + +Mozilla Bug 166235 and Bug 816298 +

                      This text should be copied.

                      +

                      This text should NOT be copied.

                      +

                      This text should NOT be copied.

                      +

                      This text should NOT be copied.

                      +

                      This text should NOT be copied.

                      +

                      This text should be copied.

                      + + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug1667316.html b/dom/base/test/test_bug1667316.html new file mode 100644 index 0000000000..7836931ee3 --- /dev/null +++ b/dom/base/test/test_bug1667316.html @@ -0,0 +1,147 @@ + + + + + Test for Bug 1667316 + + + + +Mozilla Bug 1667316 +

                      + + + + diff --git a/dom/base/test/test_bug1730284.html b/dom/base/test/test_bug1730284.html new file mode 100644 index 0000000000..84e4230a13 --- /dev/null +++ b/dom/base/test/test_bug1730284.html @@ -0,0 +1,71 @@ + + +Test for bug 1730284 (throttling of same-origin iframes) + + + + + + + + +
                      +
                      + +
                      + + + + + diff --git a/dom/base/test/test_bug1739957.html b/dom/base/test/test_bug1739957.html new file mode 100644 index 0000000000..fdfe1e3861 --- /dev/null +++ b/dom/base/test/test_bug1739957.html @@ -0,0 +1,40 @@ + + + + + Importing a node should respect sandbox + + + + + +

                      + + +
                      
                      +
                      +
                      diff --git a/dom/base/test/test_bug1784187.html b/dom/base/test/test_bug1784187.html
                      new file mode 100644
                      index 0000000000..6f9f782e3e
                      --- /dev/null
                      +++ b/dom/base/test/test_bug1784187.html
                      @@ -0,0 +1,38 @@
                      +
                      +
                      +
                      +
                      +  Test for Bug 1784187
                      +  
                      +  
                      +  
                      +
                      +
                      +
                      +Mozilla Bug 1784187
                      +

                      + + + + diff --git a/dom/base/test/test_bug1799354.html b/dom/base/test/test_bug1799354.html new file mode 100644 index 0000000000..ba2177d576 --- /dev/null +++ b/dom/base/test/test_bug1799354.html @@ -0,0 +1,77 @@ + + + + + Test bug 1799354 + + + + + +

                      + +
                      
                      +
                      +
                      diff --git a/dom/base/test/test_bug199959.html b/dom/base/test/test_bug199959.html
                      new file mode 100644
                      index 0000000000..e807646c10
                      --- /dev/null
                      +++ b/dom/base/test/test_bug199959.html
                      @@ -0,0 +1,39 @@
                      +
                      +
                      +
                      +
                      +  Test for Bug 199959
                      +  
                      +  
                      +
                      +
                      +Mozilla Bug 199959
                      +

                      + +
                      +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug218236.html b/dom/base/test/test_bug218236.html new file mode 100644 index 0000000000..d691ad4418 --- /dev/null +++ b/dom/base/test/test_bug218236.html @@ -0,0 +1,139 @@ + + + + + Test for Bug 218236 + + + + +Mozilla Bug 218236 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug218277.html b/dom/base/test/test_bug218277.html new file mode 100644 index 0000000000..bcad1dafd7 --- /dev/null +++ b/dom/base/test/test_bug218277.html @@ -0,0 +1,28 @@ + + + + + Test for Bug 218277 + + + + +Mozilla Bug 218277 +

                      +
                      + +
                      +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug238409.html b/dom/base/test/test_bug238409.html new file mode 100644 index 0000000000..ac0b261548 --- /dev/null +++ b/dom/base/test/test_bug238409.html @@ -0,0 +1,45 @@ + + + + + Test for Bug 238409 + + + + +Mozilla Bug 238409 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug254337.html b/dom/base/test/test_bug254337.html new file mode 100644 index 0000000000..1c68b18c14 --- /dev/null +++ b/dom/base/test/test_bug254337.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 254337 + + + + +Mozilla Bug 254337 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug270145.xhtml b/dom/base/test/test_bug270145.xhtml new file mode 100644 index 0000000000..ebf89ef5ca --- /dev/null +++ b/dom/base/test/test_bug270145.xhtml @@ -0,0 +1,51 @@ + + + + Test the html copy encoder with XHTML + + + + +Mozilla Bug 270145 +

                      +
                      +

                      +
                      +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug276037-1.html b/dom/base/test/test_bug276037-1.html new file mode 100644 index 0000000000..2216480337 --- /dev/null +++ b/dom/base/test/test_bug276037-1.html @@ -0,0 +1,105 @@ + + + + + Test for Bug 276037 + + + + +Mozilla Bug 276037 +

                      + +
                      +
                      +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +
                      + + + diff --git a/dom/base/test/test_bug276037-2.xhtml b/dom/base/test/test_bug276037-2.xhtml new file mode 100644 index 0000000000..d0155a4168 --- /dev/null +++ b/dom/base/test/test_bug276037-2.xhtml @@ -0,0 +1,106 @@ + + + + Test for Bug 276037 + + + + +Mozilla Bug 276037 +

                      + +
                      +
                      +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +

                      Static text in span.

                      + +
                      + + + diff --git a/dom/base/test/test_bug282547.html b/dom/base/test/test_bug282547.html new file mode 100644 index 0000000000..4c310a2724 --- /dev/null +++ b/dom/base/test/test_bug282547.html @@ -0,0 +1,104 @@ + + + + + Test for Bug 282547 + + + + +Mozilla Bug 282547 +

                      + + + + + + diff --git a/dom/base/test/test_bug28293.html b/dom/base/test/test_bug28293.html new file mode 100644 index 0000000000..332c75e42b --- /dev/null +++ b/dom/base/test/test_bug28293.html @@ -0,0 +1,86 @@ + + + + + Test for Bug 28293 + + + + + +Mozilla Bug 28293 + + + + + + + + + + + + + diff --git a/dom/base/test/test_bug28293.xhtml b/dom/base/test/test_bug28293.xhtml new file mode 100644 index 0000000000..47d73a01b4 --- /dev/null +++ b/dom/base/test/test_bug28293.xhtml @@ -0,0 +1,87 @@ + + + + Test for Bug 28293 + + + + + +Mozilla Bug 28293 + + + + + + + + + + + + + diff --git a/dom/base/test/test_bug298064.html b/dom/base/test/test_bug298064.html new file mode 100644 index 0000000000..6fd21e5129 --- /dev/null +++ b/dom/base/test/test_bug298064.html @@ -0,0 +1,32 @@ + + + + + Test for Bug 298064 + + + + +Mozilla Bug 298064 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug300992.html b/dom/base/test/test_bug300992.html new file mode 100644 index 0000000000..c9059bea85 --- /dev/null +++ b/dom/base/test/test_bug300992.html @@ -0,0 +1,45 @@ + + + + + Test for Bug 300992 + + + + +Mozilla Bug 300992 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug311681.xml b/dom/base/test/test_bug311681.xml new file mode 100644 index 0000000000..23efcb4688 --- /dev/null +++ b/dom/base/test/test_bug311681.xml @@ -0,0 +1,103 @@ + + + + Test for Bug 311681 + + + + +Mozilla Bug 311681 + +

                      + +
                      +
                      + + + diff --git a/dom/base/test/test_bug313646.html b/dom/base/test/test_bug313646.html new file mode 100644 index 0000000000..55bb760978 --- /dev/null +++ b/dom/base/test/test_bug313646.html @@ -0,0 +1,62 @@ + + + + + Test for Bug 313646 + + + + +Mozilla Bug 313646 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug320799.html b/dom/base/test/test_bug320799.html new file mode 100644 index 0000000000..dd7f598a0f --- /dev/null +++ b/dom/base/test/test_bug320799.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 320799 + + + + +Mozilla Bug 320799 +

                      + + + + +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug322317.html b/dom/base/test/test_bug322317.html new file mode 100644 index 0000000000..d4e7b6f853 --- /dev/null +++ b/dom/base/test/test_bug322317.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 322317 + + + + +Mozilla Bug 322317 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug326337.html b/dom/base/test/test_bug326337.html new file mode 100644 index 0000000000..fc789018cb --- /dev/null +++ b/dom/base/test/test_bug326337.html @@ -0,0 +1,35 @@ + + + + + Test for Bug 326337 + + + + +Mozilla Bug 326337 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug331959.html b/dom/base/test/test_bug331959.html new file mode 100644 index 0000000000..c098c55d7b --- /dev/null +++ b/dom/base/test/test_bug331959.html @@ -0,0 +1,151 @@ + + + + + Test for Bug 331959 + + + + + +Mozilla Bug 331959 +

                      + + + + + + +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug333064.html b/dom/base/test/test_bug333064.html new file mode 100644 index 0000000000..65cc893a42 --- /dev/null +++ b/dom/base/test/test_bug333064.html @@ -0,0 +1,59 @@ + + + + + Test for Bug 333064 + + + + + +Mozilla Bug 333064 +

                      + +
                      +
                      +
                      안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안안
                      + +
                      +
                      + + + + + diff --git a/dom/base/test/test_bug333198.html b/dom/base/test/test_bug333198.html new file mode 100644 index 0000000000..e1c09000e8 --- /dev/null +++ b/dom/base/test/test_bug333198.html @@ -0,0 +1,84 @@ + + + + + Test for Bug 333198 + + + + + +
                      +Mozilla Bug 333198 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug333673.html b/dom/base/test/test_bug333673.html new file mode 100644 index 0000000000..2e8547b56c --- /dev/null +++ b/dom/base/test/test_bug333673.html @@ -0,0 +1,30 @@ + + + + + Test for Bug 333673 + + + + +Mozilla Bug 333673 +

                      + +
                      +
                      +
                      + + diff --git a/dom/base/test/test_bug337631.html b/dom/base/test/test_bug337631.html new file mode 100644 index 0000000000..ad8d4e3d5a --- /dev/null +++ b/dom/base/test/test_bug337631.html @@ -0,0 +1,99 @@ + + + + + Test for Bug 337631 + + + + +Mozilla Bug 337631 +

                      +
                      + +foo + +

                      adsfasdf

                      + +
                      +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug338541.xhtml b/dom/base/test/test_bug338541.xhtml new file mode 100644 index 0000000000..9a83332a13 --- /dev/null +++ b/dom/base/test/test_bug338541.xhtml @@ -0,0 +1,49 @@ + + + + Test for Bug 338541 + + + + +Mozilla Bug 338541 +

                      +
                      +
                      +
                      + + + + diff --git a/dom/base/test/test_bug338583.html b/dom/base/test/test_bug338583.html new file mode 100644 index 0000000000..1316128484 --- /dev/null +++ b/dom/base/test/test_bug338583.html @@ -0,0 +1,666 @@ + + + + + + Test for Bug 338583 + + + + + + +Mozilla Bug 338583 +

                      + +
                      +
                      +
                      + Wait please... + + diff --git a/dom/base/test/test_bug338679.html b/dom/base/test/test_bug338679.html new file mode 100644 index 0000000000..bcc214f349 --- /dev/null +++ b/dom/base/test/test_bug338679.html @@ -0,0 +1,82 @@ + + + + +Bug 338679: correct reporting of newValue/prevValue in + DOMAttrModified events + + + + +Bug + 338679: correct reporting of newValue/prevValue in + DOMAttrModified events + +
                      + + + + diff --git a/dom/base/test/test_bug339494.html b/dom/base/test/test_bug339494.html new file mode 100644 index 0000000000..dbf81f5e98 --- /dev/null +++ b/dom/base/test/test_bug339494.html @@ -0,0 +1,59 @@ + + + + + Test for Bug 339494 + + + + +Mozilla Bug 339494 +

                      + +
                      +
                      +
                      + + + diff --git a/dom/base/test/test_bug339494.xhtml b/dom/base/test/test_bug339494.xhtml new file mode 100644 index 0000000000..985d78b368 --- /dev/null +++ b/dom/base/test/test_bug339494.xhtml @@ -0,0 +1,58 @@ + + + + Test for Bug 339494 + + + + +Mozilla Bug 339494 +

                      +