| File: | root/firefox-clang/dom/base/nsContentUtils.cpp |
| Warning: | line 12282, column 7 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
| 4 | ||||
| 5 | /* A namespace class for static layout utilities. */ | |||
| 6 | ||||
| 7 | #include "nsContentUtils.h" | |||
| 8 | ||||
| 9 | #include <fmt/format.h> | |||
| 10 | ||||
| 11 | #include <algorithm> | |||
| 12 | #include <cstddef> | |||
| 13 | #include <cstdint> | |||
| 14 | #include <cstdlib> | |||
| 15 | #include <cstring> | |||
| 16 | #include <functional> | |||
| 17 | #include <new> | |||
| 18 | #include <utility> | |||
| 19 | ||||
| 20 | #include "BrowserChild.h" | |||
| 21 | #include "CharacterDataBuffer.h" | |||
| 22 | #include "DecoderTraits.h" | |||
| 23 | #include "ErrorList.h" | |||
| 24 | #include "HTMLSplitOnSpacesTokenizer.h" | |||
| 25 | #include "ImageOps.h" | |||
| 26 | #include "InProcessBrowserChildMessageManager.h" | |||
| 27 | #include "MainThreadUtils.h" | |||
| 28 | #include "PLDHashTable.h" | |||
| 29 | #include "ReferrerInfo.h" | |||
| 30 | #include "ScopedNSSTypes.h" | |||
| 31 | #include "ThirdPartyUtil.h" | |||
| 32 | #include "Units.h" | |||
| 33 | #include "chrome/common/ipc_message.h" | |||
| 34 | #include "gfxDrawable.h" | |||
| 35 | #include "harfbuzz/hb.h" | |||
| 36 | #include "imgICache.h" | |||
| 37 | #include "imgIContainer.h" | |||
| 38 | #include "imgILoader.h" | |||
| 39 | #include "imgIRequest.h" | |||
| 40 | #include "imgLoader.h" | |||
| 41 | #include "js/Array.h" | |||
| 42 | #include "js/ArrayBuffer.h" | |||
| 43 | #include "js/BuildId.h" | |||
| 44 | #include "js/GCAPI.h" | |||
| 45 | #include "js/Id.h" | |||
| 46 | #include "js/JSON.h" | |||
| 47 | #include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty | |||
| 48 | #include "js/PropertyDescriptor.h" | |||
| 49 | #include "js/Realm.h" | |||
| 50 | #include "js/RegExp.h" | |||
| 51 | #include "js/RegExpFlags.h" | |||
| 52 | #include "js/RootingAPI.h" | |||
| 53 | #include "js/TypeDecls.h" | |||
| 54 | #include "js/Value.h" | |||
| 55 | #include "js/Wrapper.h" | |||
| 56 | #include "jsapi.h" | |||
| 57 | #include "jsfriendapi.h" | |||
| 58 | #include "mozAutoDocUpdate.h" | |||
| 59 | #include "mozIDOMWindow.h" | |||
| 60 | #include "mozilla/AlreadyAddRefed.h" | |||
| 61 | #include "mozilla/ArrayIterator.h" | |||
| 62 | #include "mozilla/AsyncEventDispatcher.h" | |||
| 63 | #include "mozilla/AtomArray.h" | |||
| 64 | #include "mozilla/Atomics.h" | |||
| 65 | #include "mozilla/Attributes.h" | |||
| 66 | #include "mozilla/AutoRestore.h" | |||
| 67 | #include "mozilla/BackgroundHangMonitor.h" | |||
| 68 | #include "mozilla/Base64.h" | |||
| 69 | #include "mozilla/BasePrincipal.h" | |||
| 70 | #include "mozilla/BasicEvents.h" | |||
| 71 | #include "mozilla/BloomFilter.h" | |||
| 72 | #include "mozilla/CORSMode.h" | |||
| 73 | #include "mozilla/CallState.h" | |||
| 74 | #include "mozilla/CheckedInt.h" | |||
| 75 | #include "mozilla/ClearOnShutdown.h" | |||
| 76 | #include "mozilla/Components.h" | |||
| 77 | #include "mozilla/ContentBlockingAllowList.h" | |||
| 78 | #include "mozilla/CycleCollectedJSContext.h" | |||
| 79 | #include "mozilla/DOMEventTargetHelper.h" | |||
| 80 | #include "mozilla/DebugOnly.h" | |||
| 81 | #include "mozilla/ErrorResult.h" | |||
| 82 | #include "mozilla/EventDispatcher.h" | |||
| 83 | #include "mozilla/EventListenerManager.h" | |||
| 84 | #include "mozilla/EventQueue.h" | |||
| 85 | #include "mozilla/EventStateManager.h" | |||
| 86 | #include "mozilla/FOGIPC.h" | |||
| 87 | #include "mozilla/FlowMarkers.h" | |||
| 88 | #include "mozilla/FlushType.h" | |||
| 89 | #include "mozilla/HTMLEditor.h" | |||
| 90 | #include "mozilla/HangAnnotations.h" | |||
| 91 | #include "mozilla/IMEStateManager.h" | |||
| 92 | #include "mozilla/InputEventOptions.h" | |||
| 93 | #include "mozilla/Latin1.h" | |||
| 94 | #include "mozilla/Likely.h" | |||
| 95 | #include "mozilla/LoadInfo.h" | |||
| 96 | #include "mozilla/Logging.h" | |||
| 97 | #include "mozilla/ManualNAC.h" | |||
| 98 | #include "mozilla/Maybe.h" | |||
| 99 | #include "mozilla/MediaFeatureChange.h" | |||
| 100 | #include "mozilla/MouseEvents.h" | |||
| 101 | #include "mozilla/NullPrincipal.h" | |||
| 102 | #include "mozilla/OriginAttributes.h" | |||
| 103 | #include "mozilla/Preferences.h" | |||
| 104 | #include "mozilla/PresShell.h" | |||
| 105 | #include "mozilla/ProfilerRunnable.h" | |||
| 106 | #include "mozilla/RangeBoundary.h" | |||
| 107 | #include "mozilla/RefPtr.h" | |||
| 108 | #include "mozilla/Result.h" | |||
| 109 | #include "mozilla/ScopeExit.h" | |||
| 110 | #include "mozilla/ScrollContainerFrame.h" | |||
| 111 | #include "mozilla/ShutdownPhase.h" | |||
| 112 | #include "mozilla/Span.h" | |||
| 113 | #include "mozilla/StaticAnalysisFunctions.h" | |||
| 114 | #include "mozilla/StaticPrefs_browser.h" | |||
| 115 | #include "mozilla/StaticPrefs_clipboard.h" | |||
| 116 | #include "mozilla/StaticPrefs_dom.h" | |||
| 117 | #include "mozilla/StaticPrefs_network.h" | |||
| 118 | #include "mozilla/StaticPrefs_pdfjs.h" | |||
| 119 | #include "mozilla/dom/ReportDeliver.h" | |||
| 120 | #include "mozilla/extensions/WebExtensionPolicy.h" | |||
| 121 | #include "nsIOService.h" | |||
| 122 | #include "nsMenuPopupFrame.h" | |||
| 123 | #include "nsObjectLoadingContent.h" | |||
| 124 | #ifdef FUZZING | |||
| 125 | # include "mozilla/StaticPrefs_fuzzing.h" | |||
| 126 | #endif | |||
| 127 | #include "mozilla/StaticPrefs_nglayout.h" | |||
| 128 | #include "mozilla/StaticPrefs_privacy.h" | |||
| 129 | #include "mozilla/StaticPrefs_test.h" | |||
| 130 | #include "mozilla/StaticPrefs_ui.h" | |||
| 131 | #include "mozilla/StaticPtr.h" | |||
| 132 | #include "mozilla/TextControlState.h" | |||
| 133 | #include "mozilla/TextEditor.h" | |||
| 134 | #include "mozilla/TextEvents.h" | |||
| 135 | #include "mozilla/TextUtils.h" | |||
| 136 | #include "mozilla/Tokenizer.h" | |||
| 137 | #include "mozilla/UniquePtr.h" | |||
| 138 | #include "mozilla/ViewportUtils.h" | |||
| 139 | #include "mozilla/dom/AncestorIterator.h" | |||
| 140 | #include "mozilla/dom/AutoEntryScript.h" | |||
| 141 | #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h" | |||
| 142 | #include "mozilla/dom/AutocompleteInfoBinding.h" | |||
| 143 | #include "mozilla/dom/BindingDeclarations.h" | |||
| 144 | #include "mozilla/dom/BindingUtils.h" | |||
| 145 | #include "mozilla/dom/BlobImpl.h" | |||
| 146 | #include "mozilla/dom/BlobURLProtocolHandler.h" | |||
| 147 | #include "mozilla/dom/BorrowedAttrInfo.h" | |||
| 148 | #include "mozilla/dom/BrowserBridgeParent.h" | |||
| 149 | #include "mozilla/dom/BrowserParent.h" | |||
| 150 | #include "mozilla/dom/BrowsingContext.h" | |||
| 151 | #include "mozilla/dom/BrowsingContextGroup.h" | |||
| 152 | #include "mozilla/dom/CacheExpirationTime.h" | |||
| 153 | #include "mozilla/dom/CallbackFunction.h" | |||
| 154 | #include "mozilla/dom/CallbackObject.h" | |||
| 155 | #include "mozilla/dom/ChildIterator.h" | |||
| 156 | #include "mozilla/dom/ChromeMessageBroadcaster.h" | |||
| 157 | #include "mozilla/dom/ContentChild.h" | |||
| 158 | #include "mozilla/dom/ContentFrameMessageManager.h" | |||
| 159 | #include "mozilla/dom/ContentParent.h" | |||
| 160 | #include "mozilla/dom/CustomElementRegistry.h" | |||
| 161 | #include "mozilla/dom/CustomElementRegistryBinding.h" | |||
| 162 | #include "mozilla/dom/CustomElementTypes.h" | |||
| 163 | #include "mozilla/dom/DOMArena.h" | |||
| 164 | #include "mozilla/dom/DOMException.h" | |||
| 165 | #include "mozilla/dom/DOMExceptionBinding.h" | |||
| 166 | #include "mozilla/dom/DOMSecurityMonitor.h" | |||
| 167 | #include "mozilla/dom/DOMTypes.h" | |||
| 168 | #include "mozilla/dom/DataTransfer.h" | |||
| 169 | #include "mozilla/dom/DeprecationReportBody.h" | |||
| 170 | #include "mozilla/dom/DocGroup.h" | |||
| 171 | #include "mozilla/dom/Document.h" | |||
| 172 | #include "mozilla/dom/DocumentFragment.h" | |||
| 173 | #include "mozilla/dom/DocumentInlines.h" | |||
| 174 | #include "mozilla/dom/DocumentOrShadowRoot.h" | |||
| 175 | #include "mozilla/dom/Element.h" | |||
| 176 | #include "mozilla/dom/ElementBinding.h" | |||
| 177 | #include "mozilla/dom/ElementInlines.h" | |||
| 178 | #include "mozilla/dom/Event.h" | |||
| 179 | #include "mozilla/dom/EventTarget.h" | |||
| 180 | #include "mozilla/dom/FileBlobImpl.h" | |||
| 181 | #include "mozilla/dom/FileSystemSecurity.h" | |||
| 182 | #include "mozilla/dom/FilteredNodeIterator.h" | |||
| 183 | #include "mozilla/dom/FormData.h" | |||
| 184 | #include "mozilla/dom/FragmentOrElement.h" | |||
| 185 | #include "mozilla/dom/FromParser.h" | |||
| 186 | #include "mozilla/dom/FunctionBinding.h" | |||
| 187 | #include "mozilla/dom/HTMLElement.h" | |||
| 188 | #include "mozilla/dom/HTMLFormElement.h" | |||
| 189 | #include "mozilla/dom/HTMLImageElement.h" | |||
| 190 | #include "mozilla/dom/HTMLInputElement.h" | |||
| 191 | #include "mozilla/dom/HTMLTemplateElement.h" | |||
| 192 | #include "mozilla/dom/HTMLTextAreaElement.h" | |||
| 193 | #include "mozilla/dom/IPCBlob.h" | |||
| 194 | #include "mozilla/dom/IPCBlobUtils.h" | |||
| 195 | #include "mozilla/dom/MessageBroadcaster.h" | |||
| 196 | #include "mozilla/dom/MessageListenerManager.h" | |||
| 197 | #include "mozilla/dom/MessagePort.h" | |||
| 198 | #include "mozilla/dom/MimeType.h" | |||
| 199 | #include "mozilla/dom/MouseEventBinding.h" | |||
| 200 | #include "mozilla/dom/MutationObservers.h" | |||
| 201 | #include "mozilla/dom/NameSpaceConstants.h" | |||
| 202 | #include "mozilla/dom/NodeBinding.h" | |||
| 203 | #include "mozilla/dom/NodeInfo.h" | |||
| 204 | #include "mozilla/dom/PBrowser.h" | |||
| 205 | #include "mozilla/dom/PContentChild.h" | |||
| 206 | #include "mozilla/dom/PrototypeList.h" | |||
| 207 | #include "mozilla/dom/ReferrerPolicyBinding.h" | |||
| 208 | #include "mozilla/dom/ReportingUtils.h" | |||
| 209 | #include "mozilla/dom/Sanitizer.h" | |||
| 210 | #include "mozilla/dom/ScriptLoader.h" | |||
| 211 | #include "mozilla/dom/ScriptSettings.h" | |||
| 212 | #include "mozilla/dom/Selection.h" | |||
| 213 | #include "mozilla/dom/ShadowRoot.h" | |||
| 214 | #include "mozilla/dom/Text.h" | |||
| 215 | #include "mozilla/dom/TrustedHTML.h" | |||
| 216 | #include "mozilla/dom/TrustedTypeUtils.h" | |||
| 217 | #include "mozilla/dom/TrustedTypesConstants.h" | |||
| 218 | #include "mozilla/dom/UserActivation.h" | |||
| 219 | #include "mozilla/dom/ViewTransition.h" | |||
| 220 | #include "mozilla/dom/WindowBinding.h" | |||
| 221 | #include "mozilla/dom/WindowContext.h" | |||
| 222 | #include "mozilla/dom/WindowGlobalChild.h" | |||
| 223 | #include "mozilla/dom/WindowGlobalParent.h" | |||
| 224 | #include "mozilla/dom/WorkerCommon.h" | |||
| 225 | #include "mozilla/dom/WorkerPrivate.h" | |||
| 226 | #include "mozilla/dom/WorkerRunnable.h" | |||
| 227 | #include "mozilla/dom/XULCommandEvent.h" | |||
| 228 | #include "mozilla/fallible.h" | |||
| 229 | #include "mozilla/gfx/2D.h" | |||
| 230 | #include "mozilla/gfx/BaseMargin.h" | |||
| 231 | #include "mozilla/gfx/BasePoint.h" | |||
| 232 | #include "mozilla/gfx/BaseSize.h" | |||
| 233 | #include "mozilla/gfx/DataSurfaceHelpers.h" | |||
| 234 | #include "mozilla/gfx/Point.h" | |||
| 235 | #include "mozilla/gfx/Rect.h" | |||
| 236 | #include "mozilla/gfx/Types.h" | |||
| 237 | #include "mozilla/glean/GleanPings.h" | |||
| 238 | #include "mozilla/htmlaccel/htmlaccelEnabled.h" | |||
| 239 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 240 | # include "mozilla/htmlaccel/htmlaccelNotInline.h" | |||
| 241 | #endif | |||
| 242 | #include "mozilla/dom/ContentList.h" | |||
| 243 | #include "mozilla/intl/LocaleService.h" | |||
| 244 | #include "mozilla/ipc/ProtocolUtils.h" | |||
| 245 | #include "mozilla/net/ChannelClassifierUtils.h" | |||
| 246 | #include "mozilla/widget/IMEData.h" | |||
| 247 | #include "nsAboutProtocolUtils.h" | |||
| 248 | #include "nsArrayUtils.h" | |||
| 249 | #include "nsAtomHashKeys.h" | |||
| 250 | #include "nsAttrName.h" | |||
| 251 | #include "nsAttrValue.h" | |||
| 252 | #include "nsAttrValueInlines.h" | |||
| 253 | #include "nsBaseHashtable.h" | |||
| 254 | #include "nsCCUncollectableMarker.h" | |||
| 255 | #include "nsCOMPtr.h" | |||
| 256 | #include "nsCRT.h" | |||
| 257 | #include "nsCRTGlue.h" | |||
| 258 | #include "nsCanvasFrame.h" | |||
| 259 | #include "nsCaseTreatment.h" | |||
| 260 | #include "nsCharSeparatedTokenizer.h" | |||
| 261 | #include "nsCharTraits.h" | |||
| 262 | #include "nsCompatibility.h" | |||
| 263 | #include "nsComponentManagerUtils.h" | |||
| 264 | #include "nsContainerFrame.h" | |||
| 265 | #include "nsContentCreatorFunctions.h" | |||
| 266 | #include "nsContentDLF.h" | |||
| 267 | #include "nsContentListDeclarations.h" | |||
| 268 | #include "nsContentPolicyUtils.h" | |||
| 269 | #include "nsCoord.h" | |||
| 270 | #include "nsCycleCollectionNoteChild.h" | |||
| 271 | #include "nsDOMMutationObserver.h" | |||
| 272 | #include "nsDOMString.h" | |||
| 273 | #include "nsDebug.h" | |||
| 274 | #include "nsDocShell.h" | |||
| 275 | #include "nsDocShellCID.h" | |||
| 276 | #include "nsError.h" | |||
| 277 | #include "nsFocusManager.h" | |||
| 278 | #include "nsFrameList.h" | |||
| 279 | #include "nsFrameLoader.h" | |||
| 280 | #include "nsFrameLoaderOwner.h" | |||
| 281 | #include "nsGenericHTMLElement.h" | |||
| 282 | #include "nsGkAtoms.h" | |||
| 283 | #include "nsGlobalWindowInner.h" | |||
| 284 | #include "nsGlobalWindowOuter.h" | |||
| 285 | #include "nsHTMLDocument.h" | |||
| 286 | #include "nsHTMLTags.h" | |||
| 287 | #include "nsHashKeys.h" | |||
| 288 | #include "nsHtml5StringParser.h" | |||
| 289 | #include "nsIAboutModule.h" | |||
| 290 | #include "nsIAnonymousContentCreator.h" | |||
| 291 | #include "nsIAppShell.h" | |||
| 292 | #include "nsIArray.h" | |||
| 293 | #include "nsIAsyncVerifyRedirectCallback.h" | |||
| 294 | #include "nsIBidiKeyboard.h" | |||
| 295 | #include "nsIBrowser.h" | |||
| 296 | #include "nsICacheInfoChannel.h" | |||
| 297 | #include "nsICachingChannel.h" | |||
| 298 | #include "nsICategoryManager.h" | |||
| 299 | #include "nsIChannel.h" | |||
| 300 | #include "nsIChannelEventSink.h" | |||
| 301 | #include "nsIClassifiedChannel.h" | |||
| 302 | #include "nsIConsoleService.h" | |||
| 303 | #include "nsIContent.h" | |||
| 304 | #include "nsIContentInlines.h" | |||
| 305 | #include "nsIContentPolicy.h" | |||
| 306 | #include "nsIContentSecurityPolicy.h" | |||
| 307 | #include "nsIContentSink.h" | |||
| 308 | #include "nsIDOMWindowUtils.h" | |||
| 309 | #include "nsIDocShell.h" | |||
| 310 | #include "nsIDocShellTreeItem.h" | |||
| 311 | #include "nsIDocumentEncoder.h" | |||
| 312 | #include "nsIDocumentLoaderFactory.h" | |||
| 313 | #include "nsIDocumentViewer.h" | |||
| 314 | #include "nsIDragService.h" | |||
| 315 | #include "nsIDragSession.h" | |||
| 316 | #include "nsIFile.h" | |||
| 317 | #include "nsIFocusManager.h" | |||
| 318 | #include "nsIFormControl.h" | |||
| 319 | #include "nsIFragmentContentSink.h" | |||
| 320 | #include "nsIFrame.h" | |||
| 321 | #include "nsIGlobalObject.h" | |||
| 322 | #include "nsIHttpChannel.h" | |||
| 323 | #include "nsIHttpChannelInternal.h" | |||
| 324 | #include "nsIIOService.h" | |||
| 325 | #include "nsIImageLoadingContent.h" | |||
| 326 | #include "nsIInputStream.h" | |||
| 327 | #include "nsIInterfaceRequestor.h" | |||
| 328 | #include "nsIInterfaceRequestorUtils.h" | |||
| 329 | #include "nsILoadContext.h" | |||
| 330 | #include "nsILoadGroup.h" | |||
| 331 | #include "nsILoadInfo.h" | |||
| 332 | #include "nsIMIMEService.h" | |||
| 333 | #include "nsINetUtil.h" | |||
| 334 | #include "nsINode.h" | |||
| 335 | #include "nsIObjectLoadingContent.h" | |||
| 336 | #include "nsIObserver.h" | |||
| 337 | #include "nsIObserverService.h" | |||
| 338 | #include "nsIParserUtils.h" | |||
| 339 | #include "nsIPermissionManager.h" | |||
| 340 | #include "nsIPrincipal.h" | |||
| 341 | #include "nsIProperties.h" | |||
| 342 | #include "nsIProtocolHandler.h" | |||
| 343 | #include "nsIRequest.h" | |||
| 344 | #include "nsIRunnable.h" | |||
| 345 | #include "nsIScreen.h" | |||
| 346 | #include "nsIScriptError.h" | |||
| 347 | #include "nsIScriptGlobalObject.h" | |||
| 348 | #include "nsIScriptObjectPrincipal.h" | |||
| 349 | #include "nsIScriptSecurityManager.h" | |||
| 350 | #include "nsISerialEventTarget.h" | |||
| 351 | #include "nsIStreamConverter.h" | |||
| 352 | #include "nsIStreamConverterService.h" | |||
| 353 | #include "nsIStringBundle.h" | |||
| 354 | #include "nsISupports.h" | |||
| 355 | #include "nsISupportsPrimitives.h" | |||
| 356 | #include "nsISupportsUtils.h" | |||
| 357 | #include "nsITransferable.h" | |||
| 358 | #include "nsIURI.h" | |||
| 359 | #include "nsIURIMutator.h" | |||
| 360 | #include "nsTHashMap.h" | |||
| 361 | #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) | |||
| 362 | # include "nsIURIWithSpecialOrigin.h" | |||
| 363 | #endif | |||
| 364 | #include "nsIUserIdleServiceInternal.h" | |||
| 365 | #include "nsIWeakReferenceUtils.h" | |||
| 366 | #include "nsIWebNavigation.h" | |||
| 367 | #include "nsIWebNavigationInfo.h" | |||
| 368 | #include "nsIWidget.h" | |||
| 369 | #include "nsIWindowMediator.h" | |||
| 370 | #include "nsIXPConnect.h" | |||
| 371 | #include "nsJSPrincipals.h" | |||
| 372 | #include "nsJSUtils.h" | |||
| 373 | #include "nsLayoutUtils.h" | |||
| 374 | #include "nsLiteralString.h" | |||
| 375 | #include "nsMargin.h" | |||
| 376 | #include "nsMimeTypes.h" | |||
| 377 | #include "nsNameSpaceManager.h" | |||
| 378 | #include "nsNetCID.h" | |||
| 379 | #include "nsNetUtil.h" | |||
| 380 | #include "nsNodeInfoManager.h" | |||
| 381 | #include "nsPIDOMWindow.h" | |||
| 382 | #include "nsPIDOMWindowInlines.h" | |||
| 383 | #include "nsParser.h" | |||
| 384 | #include "nsParserConstants.h" | |||
| 385 | #include "nsPoint.h" | |||
| 386 | #include "nsPointerHashKeys.h" | |||
| 387 | #include "nsPresContext.h" | |||
| 388 | #include "nsQueryFrame.h" | |||
| 389 | #include "nsQueryObject.h" | |||
| 390 | #include "nsRange.h" | |||
| 391 | #include "nsReadableUtils.h" | |||
| 392 | #include "nsRefPtrHashtable.h" | |||
| 393 | #include "nsSandboxFlags.h" | |||
| 394 | #include "nsScriptSecurityManager.h" | |||
| 395 | #include "nsServiceManagerUtils.h" | |||
| 396 | #include "nsStreamUtils.h" | |||
| 397 | #include "nsString.h" | |||
| 398 | #include "nsStringBundle.h" | |||
| 399 | #include "nsStringFlags.h" | |||
| 400 | #include "nsStringFwd.h" | |||
| 401 | #include "nsStringIterator.h" | |||
| 402 | #include "nsStringStream.h" | |||
| 403 | #include "nsTArray.h" | |||
| 404 | #include "nsTLiteralString.h" | |||
| 405 | #include "nsTPromiseFlatString.h" | |||
| 406 | #include "nsTStringRepr.h" | |||
| 407 | #include "nsTextNode.h" | |||
| 408 | #include "nsThreadManager.h" | |||
| 409 | #include "nsThreadUtils.h" | |||
| 410 | #include "nsTreeSanitizer.h" | |||
| 411 | #include "nsUGenCategory.h" | |||
| 412 | #include "nsURLHelper.h" | |||
| 413 | #include "nsUnicodeProperties.h" | |||
| 414 | #include "nsVariant.h" | |||
| 415 | #include "nsWhitespaceTokenizer.h" | |||
| 416 | #include "nsWidgetsCID.h" | |||
| 417 | #include "nsXPCOM.h" | |||
| 418 | #include "nsXPCOMCID.h" | |||
| 419 | #include "nsXULAppAPI.h" | |||
| 420 | #include "nsXULElement.h" | |||
| 421 | #include "nsXULPopupManager.h" | |||
| 422 | #include "nscore.h" | |||
| 423 | #include "prinrval.h" | |||
| 424 | #include "xpcprivate.h" | |||
| 425 | #include "xpcpublic.h" | |||
| 426 | ||||
| 427 | #if defined(XP_WIN) | |||
| 428 | // Undefine LoadImage to prevent naming conflict with Windows. | |||
| 429 | # undef LoadImage | |||
| 430 | #endif | |||
| 431 | ||||
| 432 | extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end, | |||
| 433 | const char** next, char16_t* result); | |||
| 434 | extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware, | |||
| 435 | const char** colon); | |||
| 436 | ||||
| 437 | using namespace mozilla::dom; | |||
| 438 | using namespace mozilla::ipc; | |||
| 439 | using namespace mozilla::gfx; | |||
| 440 | using namespace mozilla::layers; | |||
| 441 | using namespace mozilla::widget; | |||
| 442 | using namespace mozilla; | |||
| 443 | ||||
| 444 | const char kLoadAsData[] = "loadAsData"; | |||
| 445 | ||||
| 446 | nsIXPConnect* nsContentUtils::sXPConnect; | |||
| 447 | nsIScriptSecurityManager* nsContentUtils::sSecurityManager; | |||
| 448 | nsIPrincipal* nsContentUtils::sSystemPrincipal; | |||
| 449 | nsIPrincipal* nsContentUtils::sNullSubjectPrincipal; | |||
| 450 | nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal; | |||
| 451 | nsIConsoleService* nsContentUtils::sConsoleService; | |||
| 452 | ||||
| 453 | static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable; | |||
| 454 | static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable; | |||
| 455 | static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents; | |||
| 456 | nsIStringBundleService* nsContentUtils::sStringBundleService; | |||
| 457 | ||||
| 458 | static constexpr size_t kPropertiesFileCount = | |||
| 459 | static_cast<size_t>(PropertiesFile::COUNT); | |||
| 460 | ||||
| 461 | static StaticRefPtr<nsIStringBundle> sStringBundles[kPropertiesFileCount]; | |||
| 462 | ||||
| 463 | nsIContentPolicy* nsContentUtils::sContentPolicyService; | |||
| 464 | bool nsContentUtils::sTriedToGetContentPolicy = false; | |||
| 465 | StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard; | |||
| 466 | uint32_t nsContentUtils::sScriptBlockerCount = 0; | |||
| 467 | uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0; | |||
| 468 | AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = | |||
| 469 | nullptr; | |||
| 470 | uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0; | |||
| 471 | nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr; | |||
| 472 | ||||
| 473 | bool nsContentUtils::sIsHandlingKeyBoardEvent = false; | |||
| 474 | ||||
| 475 | nsString* nsContentUtils::sShiftText = nullptr; | |||
| 476 | nsString* nsContentUtils::sControlText = nullptr; | |||
| 477 | nsString* nsContentUtils::sCommandOrWinText = nullptr; | |||
| 478 | nsString* nsContentUtils::sAltText = nullptr; | |||
| 479 | nsString* nsContentUtils::sModifierSeparator = nullptr; | |||
| 480 | ||||
| 481 | bool nsContentUtils::sInitialized = false; | |||
| 482 | #ifndef RELEASE_OR_BETA | |||
| 483 | bool nsContentUtils::sBypassCSSOMOriginCheck = false; | |||
| 484 | #endif | |||
| 485 | ||||
| 486 | nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr; | |||
| 487 | nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr; | |||
| 488 | ||||
| 489 | nsContentUtils::UserInteractionObserver* | |||
| 490 | nsContentUtils::sUserInteractionObserver = nullptr; | |||
| 491 | ||||
| 492 | nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr; | |||
| 493 | nsParser* nsContentUtils::sXMLFragmentParser = nullptr; | |||
| 494 | nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr; | |||
| 495 | bool nsContentUtils::sFragmentParsingActive = false; | |||
| 496 | ||||
| 497 | mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog( | |||
| 498 | "nsResistFingerprinting"); | |||
| 499 | mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump"); | |||
| 500 | // Log when "input" and "beforeinput" events are dispatched or enqueued with | |||
| 501 | // InputEvent:3,sync. | |||
| 502 | mozilla::LazyLogModule gInputEventLog("InputEvent"); | |||
| 503 | ||||
| 504 | int32_t nsContentUtils::sInnerOrOuterWindowCount = 0; | |||
| 505 | uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0; | |||
| 506 | ||||
| 507 | #define INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 508 | aResultType, aMethodName, aTreeKind, ...) \ | |||
| 509 | template aResultType aMethodName<aTreeKind>(__VA_ARGS__); | |||
| 510 | ||||
| 511 | #define INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS( \ | |||
| 512 | aResultType, aMethodName, aTreeKind, ...) \ | |||
| 513 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 514 | aResultType, aMethodName, aTreeKind, const RangeBoundary&, \ | |||
| 515 | const RangeBoundary&, __VA_ARGS__) \ | |||
| 516 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 517 | aResultType, aMethodName, aTreeKind, const RangeBoundary&, \ | |||
| 518 | const RawRangeBoundary&, __VA_ARGS__) \ | |||
| 519 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 520 | aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \ | |||
| 521 | const RangeBoundary&, __VA_ARGS__) \ | |||
| 522 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 523 | aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \ | |||
| 524 | const RawRangeBoundary&, __VA_ARGS__) \ | |||
| 525 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 526 | aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \ | |||
| 527 | const ConstRawRangeBoundary&, __VA_ARGS__) \ | |||
| 528 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 529 | aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \ | |||
| 530 | const RangeBoundary&, __VA_ARGS__) \ | |||
| 531 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 532 | aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \ | |||
| 533 | const RawRangeBoundary&, __VA_ARGS__) \ | |||
| 534 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 535 | aResultType, aMethodName, aTreeKind, const RangeBoundary&, \ | |||
| 536 | const ConstRawRangeBoundary&, __VA_ARGS__) \ | |||
| 537 | INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \ | |||
| 538 | aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \ | |||
| 539 | const ConstRawRangeBoundary&, __VA_ARGS__) | |||
| 540 | ||||
| 541 | INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>, | |||
| 542 | nsContentUtils::ComparePoints, | |||
| 543 | TreeKind::DOM, | |||
| 544 | NodeIndexCache*); | |||
| 545 | INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>, | |||
| 546 | nsContentUtils::ComparePoints, | |||
| 547 | TreeKind::ShadowIncludingDOM, | |||
| 548 | NodeIndexCache*); | |||
| 549 | INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>, | |||
| 550 | nsContentUtils::ComparePoints, | |||
| 551 | TreeKind::Flat, | |||
| 552 | NodeIndexCache*); | |||
| 553 | INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>, | |||
| 554 | nsContentUtils::ComparePoints, | |||
| 555 | TreeKind::FlatForSelection, | |||
| 556 | NodeIndexCache*); | |||
| 557 | ||||
| 558 | #undef INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS | |||
| 559 | #undef INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM | |||
| 560 | ||||
| 561 | // Subset of | |||
| 562 | // http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name | |||
| 563 | enum AutocompleteUnsupportedFieldName : uint8_t { | |||
| 564 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ | |||
| 565 | eAutocompleteUnsupportedFieldName_##name_, | |||
| 566 | #include "AutocompleteFieldList.h" | |||
| 567 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME | |||
| 568 | }; | |||
| 569 | ||||
| 570 | enum AutocompleteNoPersistFieldName : uint8_t { | |||
| 571 | #define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ | |||
| 572 | eAutocompleteNoPersistFieldName_##name_, | |||
| 573 | #include "AutocompleteFieldList.h" | |||
| 574 | #undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME | |||
| 575 | }; | |||
| 576 | ||||
| 577 | enum AutocompleteUnsupportFieldContactHint : uint8_t { | |||
| 578 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ | |||
| 579 | eAutocompleteUnsupportedFieldContactHint_##name_, | |||
| 580 | #include "AutocompleteFieldList.h" | |||
| 581 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT | |||
| 582 | }; | |||
| 583 | ||||
| 584 | enum AutocompleteFieldName : uint8_t { | |||
| 585 | #define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_, | |||
| 586 | #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ | |||
| 587 | AUTOCOMPLETE_FIELD_NAME(name_, value_) | |||
| 588 | #include "AutocompleteFieldList.h" | |||
| 589 | #undef AUTOCOMPLETE_FIELD_NAME | |||
| 590 | #undef AUTOCOMPLETE_CONTACT_FIELD_NAME | |||
| 591 | }; | |||
| 592 | ||||
| 593 | enum AutocompleteFieldHint : uint8_t { | |||
| 594 | #define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_, | |||
| 595 | #include "AutocompleteFieldList.h" | |||
| 596 | #undef AUTOCOMPLETE_FIELD_HINT | |||
| 597 | }; | |||
| 598 | ||||
| 599 | enum AutocompleteFieldContactHint : uint8_t { | |||
| 600 | #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ | |||
| 601 | eAutocompleteFieldContactHint_##name_, | |||
| 602 | #include "AutocompleteFieldList.h" | |||
| 603 | #undef AUTOCOMPLETE_FIELD_CONTACT_HINT | |||
| 604 | }; | |||
| 605 | ||||
| 606 | enum AutocompleteCredentialType : uint8_t { | |||
| 607 | #define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ | |||
| 608 | eAutocompleteCredentialType_##name_, | |||
| 609 | #include "AutocompleteFieldList.h" | |||
| 610 | #undef AUTOCOMPLETE_CREDENTIAL_TYPE | |||
| 611 | }; | |||
| 612 | ||||
| 613 | enum AutocompleteCategory { | |||
| 614 | #define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_, | |||
| 615 | #include "AutocompleteFieldList.h" | |||
| 616 | #undef AUTOCOMPLETE_CATEGORY | |||
| 617 | }; | |||
| 618 | ||||
| 619 | static constexpr nsAttrValue::EnumTableEntry | |||
| 620 | kAutocompleteUnsupportedFieldNameTable[]{ | |||
| 621 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ | |||
| 622 | {value_, eAutocompleteUnsupportedFieldName_##name_}, | |||
| 623 | #include "AutocompleteFieldList.h" | |||
| 624 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME | |||
| 625 | }; | |||
| 626 | ||||
| 627 | static constexpr nsAttrValue::EnumTableEntry | |||
| 628 | kAutocompleteNoPersistFieldNameTable[] = { | |||
| 629 | #define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ | |||
| 630 | {value_, eAutocompleteNoPersistFieldName_##name_}, | |||
| 631 | #include "AutocompleteFieldList.h" | |||
| 632 | #undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME | |||
| 633 | }; | |||
| 634 | static constexpr nsAttrValue::EnumTableEntry | |||
| 635 | kAutocompleteUnsupportedContactFieldHintTable[] = { | |||
| 636 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ | |||
| 637 | {value_, eAutocompleteUnsupportedFieldContactHint_##name_}, | |||
| 638 | #include "AutocompleteFieldList.h" | |||
| 639 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT | |||
| 640 | }; | |||
| 641 | ||||
| 642 | static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldNameTable[] = { | |||
| 643 | #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \ | |||
| 644 | {value_, eAutocompleteFieldName_##name_}, | |||
| 645 | #include "AutocompleteFieldList.h" | |||
| 646 | #undef AUTOCOMPLETE_FIELD_NAME | |||
| 647 | }; | |||
| 648 | ||||
| 649 | static constexpr nsAttrValue::EnumTableEntry | |||
| 650 | kAutocompleteContactFieldNameTable[] = { | |||
| 651 | #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ | |||
| 652 | {value_, eAutocompleteFieldName_##name_}, | |||
| 653 | #include "AutocompleteFieldList.h" | |||
| 654 | #undef AUTOCOMPLETE_CONTACT_FIELD_NAME | |||
| 655 | }; | |||
| 656 | ||||
| 657 | static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldHintTable[] = { | |||
| 658 | #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \ | |||
| 659 | {value_, eAutocompleteFieldHint_##name_}, | |||
| 660 | #include "AutocompleteFieldList.h" | |||
| 661 | #undef AUTOCOMPLETE_FIELD_HINT | |||
| 662 | }; | |||
| 663 | ||||
| 664 | static constexpr nsAttrValue::EnumTableEntry | |||
| 665 | kAutocompleteContactFieldHintTable[] = { | |||
| 666 | #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ | |||
| 667 | {value_, eAutocompleteFieldContactHint_##name_}, | |||
| 668 | #include "AutocompleteFieldList.h" | |||
| 669 | #undef AUTOCOMPLETE_FIELD_CONTACT_HINT | |||
| 670 | }; | |||
| 671 | ||||
| 672 | static constexpr nsAttrValue::EnumTableEntry | |||
| 673 | kAutocompleteCredentialTypeTable[] = { | |||
| 674 | #define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ | |||
| 675 | {value_, eAutocompleteCredentialType_##name_}, | |||
| 676 | #include "AutocompleteFieldList.h" | |||
| 677 | #undef AUTOCOMPLETE_CREDENTIAL_TYPE | |||
| 678 | }; | |||
| 679 | ||||
| 680 | namespace { | |||
| 681 | ||||
| 682 | // Non-owning list of the managers nodes store themselves; the managers remove | |||
| 683 | // themselves from it when deleted. Documents keep their manager in | |||
| 684 | // Document::mListenerManager and are not in this list. | |||
| 685 | constinit DoublyLinkedList<EventListenerManager> sNodeEventListenerManagers; | |||
| 686 | ||||
| 687 | // A global hashtable to for keeping the arena alive for cross docGroup node | |||
| 688 | // adoption. | |||
| 689 | static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>* | |||
| 690 | sDOMArenaHashtable; | |||
| 691 | ||||
| 692 | class SameOriginCheckerImpl final : public nsIChannelEventSink, | |||
| 693 | public nsIInterfaceRequestor { | |||
| 694 | ~SameOriginCheckerImpl() = default; | |||
| 695 | ||||
| 696 | NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread ; public: | |||
| 697 | NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel , nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback *callback) override; | |||
| 698 | NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * * result) override; | |||
| 699 | }; | |||
| 700 | ||||
| 701 | } // namespace | |||
| 702 | ||||
| 703 | void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) { | |||
| 704 | // Note: Document::SuppressEventHandling will also automatically suppress | |||
| 705 | // event handling for any in-process sub-documents. However, since we need | |||
| 706 | // to deal with cases where remote BrowsingContexts may be interleaved | |||
| 707 | // with in-process ones, we still need to walk the entire tree ourselves. | |||
| 708 | // This may be slightly redundant in some cases, but since event handling | |||
| 709 | // suppressions maintain a count of current blockers, it does not cause | |||
| 710 | // any problems. | |||
| 711 | aDoc->SuppressEventHandling(); | |||
| 712 | } | |||
| 713 | ||||
| 714 | void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) { | |||
| 715 | aDoc->UnsuppressEventHandlingAndFireEvents(true); | |||
| 716 | } | |||
| 717 | ||||
| 718 | AutoSuppressEventHandling::~AutoSuppressEventHandling() { | |||
| 719 | UnsuppressDocuments(); | |||
| 720 | } | |||
| 721 | ||||
| 722 | void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) { | |||
| 723 | AutoSuppressEventHandling::SuppressDocument(aDoc); | |||
| 724 | if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) { | |||
| 725 | win->Suspend(); | |||
| 726 | mWindows.AppendElement(win); | |||
| 727 | } | |||
| 728 | } | |||
| 729 | ||||
| 730 | AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() { | |||
| 731 | for (const auto& win : mWindows) { | |||
| 732 | win->Resume(); | |||
| 733 | } | |||
| 734 | } | |||
| 735 | ||||
| 736 | // The following structs are used by CommonAncestors. They must have: | |||
| 737 | // NodeType, Get(), ComputeChildIndex(), GetChildCount() and CanComputeIndex(). | |||
| 738 | // If CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount() | |||
| 739 | // is not used by CommonAncestors to assert the odd result. | |||
| 740 | ||||
| 741 | /** | |||
| 742 | * GetParentNodeForComparison is used for implementing | |||
| 743 | * nsContentUtils::ComparePoints and its relatives and helpers. | |||
| 744 | */ | |||
| 745 | template <TreeKind aKind> | |||
| 746 | struct GetParentNodeForComparison { | |||
| 747 | using NodeType = nsINode; | |||
| 748 | static NodeType* Get(const NodeType* aNode) { | |||
| 749 | if constexpr (aKind == TreeKind::DOM) { | |||
| 750 | return aNode->GetParentNode(); | |||
| 751 | } | |||
| 752 | // We want to list up ShadowRoot as the parent of a child of ShadowRoot and | |||
| 753 | // its host as the parent of the ShadowRoot. GetFlattenedTreeParentNode() | |||
| 754 | // won't return ShadowRoot so that we cannot use | |||
| 755 | // nsINode::GetParentNode<aKind>() here. | |||
| 756 | if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) { | |||
| 757 | if (aNode->IsContent()) { | |||
| 758 | if (HTMLSlotElement* const slot = | |||
| 759 | aNode->AsContent()->GetAssignedSlot<aKind>()) { | |||
| 760 | return slot; | |||
| 761 | } | |||
| 762 | // FIXME: If aNode->GetParentNode()->GetShadowRoot<aKind>() returns | |||
| 763 | // non-nullptr, we should always return nullptr here. However, if aKind | |||
| 764 | // is TreeKind::FlatForSelection, we cannot do that because | |||
| 765 | // GetFlattenedTreeParentNode<nsINode::eForSelection>() returns the | |||
| 766 | // shadow host element as-is. Therefore, we do the strict behavior only | |||
| 767 | // here causes assertion failures with the extant tests. This should | |||
| 768 | // be fixed in bug 2014622. | |||
| 769 | if constexpr (aKind != TreeKind::FlatForSelection) { | |||
| 770 | // If we're handling a flattened tree, we should return nullptr if the | |||
| 771 | // node is not part of a flattened tree. | |||
| 772 | if (nsINode* const parentNode = aNode->GetParentNode()) { | |||
| 773 | if (parentNode->GetShadowRoot<aKind>()) { | |||
| 774 | return nullptr; | |||
| 775 | } | |||
| 776 | } | |||
| 777 | } | |||
| 778 | } | |||
| 779 | } | |||
| 780 | return aNode->GetParentOrShadowHostNode(); | |||
| 781 | } | |||
| 782 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 783 | const nsIContent* aPossibleChild) { | |||
| 784 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 785 | return aParent->ComputeIndexOf(aPossibleChild); | |||
| 786 | } else { | |||
| 787 | return aParent->ComputeIndexOf<aKind>(aPossibleChild); | |||
| 788 | } | |||
| 789 | } | |||
| 790 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 791 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 792 | return aParent->GetChildCount(); | |||
| 793 | } else { | |||
| 794 | return aParent->GetChildCount<aKind>(); | |||
| 795 | } | |||
| 796 | } | |||
| 797 | constexpr static bool CanComputeIndex() { | |||
| 798 | // The helpers of nsContentUtils::ComparePoints() and relatives require | |||
| 799 | // ComputeChildIndex() and GetChildCount(). Therefore, we implement them and | |||
| 800 | // return true. | |||
| 801 | return true; | |||
| 802 | } | |||
| 803 | }; | |||
| 804 | ||||
| 805 | /** | |||
| 806 | * GetParentNode is used for implementing | |||
| 807 | * nsContentUtils::GetClosestCommonInclusiveAncestor(). | |||
| 808 | */ | |||
| 809 | using GetParentNode = GetParentNodeForComparison<TreeKind::DOM>; | |||
| 810 | ||||
| 811 | /** | |||
| 812 | * GetParentOrShadowHostNode is used for implementing | |||
| 813 | * nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(). | |||
| 814 | */ | |||
| 815 | struct GetParentOrShadowHostNode { | |||
| 816 | using NodeType = nsINode; | |||
| 817 | static NodeType* Get(const NodeType* aNode) { | |||
| 818 | return aNode->GetParentOrShadowHostNode(); | |||
| 819 | } | |||
| 820 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 821 | const nsIContent* aPossibleChild) { | |||
| 822 | return aParent->ComputeIndexOf(aPossibleChild); | |||
| 823 | } | |||
| 824 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 825 | return aParent->GetChildCount(); | |||
| 826 | } | |||
| 827 | constexpr static bool CanComputeIndex() { | |||
| 828 | // Neither ComputeChildIndex() nor GetChildCount() is required by | |||
| 829 | // nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(), but | |||
| 830 | // let's implement them to make CommonAncestors asserts the odd situations | |||
| 831 | // so that return true. | |||
| 832 | return true; | |||
| 833 | } | |||
| 834 | }; | |||
| 835 | ||||
| 836 | /** | |||
| 837 | * GetFlattenedTreeParent is used for implementing | |||
| 838 | * nsContentUtils::GetCommonFlattenedTreeAncestor(). | |||
| 839 | */ | |||
| 840 | struct GetFlattenedTreeParent { | |||
| 841 | using NodeType = nsIContent; | |||
| 842 | static NodeType* Get(const NodeType* aContent) { | |||
| 843 | return aContent->GetFlattenedTreeParent(); | |||
| 844 | } | |||
| 845 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 846 | const nsIContent* aPossibleChild) { | |||
| 847 | return aParent->ComputeFlatTreeIndexOf(aPossibleChild); | |||
| 848 | } | |||
| 849 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 850 | return aParent->GetFlatTreeChildCount(); | |||
| 851 | } | |||
| 852 | constexpr static bool CanComputeIndex() { | |||
| 853 | // Neither ComputeChildIndex() nor GetChildCount() is required by | |||
| 854 | // nsContentUtils::GetCommonFlattenedTreeAncestor(), but let's implement | |||
| 855 | // them to make CommonAncestors asserts the odd situations so that return | |||
| 856 | // true. | |||
| 857 | return true; | |||
| 858 | } | |||
| 859 | }; | |||
| 860 | ||||
| 861 | /** | |||
| 862 | * GetFlattenedTreeParentNodeForSelection is used for implementing | |||
| 863 | * nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(). | |||
| 864 | */ | |||
| 865 | struct GetFlattenedTreeParentNodeForSelection { | |||
| 866 | using NodeType = nsINode; | |||
| 867 | static NodeType* Get(const NodeType* aNode) { | |||
| 868 | return aNode->GetFlattenedTreeParentNodeForSelection(); | |||
| 869 | } | |||
| 870 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 871 | const nsIContent* aPossibleChild) { | |||
| 872 | return aParent->ComputeFlatTreeForSelectionIndexOf(aPossibleChild); | |||
| 873 | } | |||
| 874 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 875 | return aParent->GetFlatTreeForSelectionChildCount(); | |||
| 876 | } | |||
| 877 | constexpr static bool CanComputeIndex() { | |||
| 878 | // Neither ComputeChildIndex() nor GetChildCount() is required by | |||
| 879 | // nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(), but let's | |||
| 880 | // implement them to make CommonAncestors asserts the odd situations so that | |||
| 881 | // return true. | |||
| 882 | return true; | |||
| 883 | } | |||
| 884 | }; | |||
| 885 | ||||
| 886 | /** | |||
| 887 | * GetFlattenedTreeParentElementForStyle is used for implementing | |||
| 888 | * nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(). | |||
| 889 | */ | |||
| 890 | struct GetFlattenedTreeParentElementForStyle { | |||
| 891 | using NodeType = Element; | |||
| 892 | static NodeType* Get(const NodeType* aElement) { | |||
| 893 | return aElement->GetFlattenedTreeParentElementForStyle(); | |||
| 894 | } | |||
| 895 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 896 | const nsIContent* aPossibleChild) { | |||
| 897 | return Nothing(); | |||
| 898 | } | |||
| 899 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 900 | return 0; // This should be called only when CanComputeIndex() returns true | |||
| 901 | } | |||
| 902 | constexpr static bool CanComputeIndex() { | |||
| 903 | // Neither ComputeChildIndex() nor GetChildCount() is required by | |||
| 904 | // nsContentUtils::GetCommonFlattenedTreeAncestorForStyle() and there is no | |||
| 905 | // API to get child count nor compute index of a child in the flattened tree | |||
| 906 | // for style. Therefore, we don't implement them so that return false. | |||
| 907 | return false; | |||
| 908 | } | |||
| 909 | }; | |||
| 910 | ||||
| 911 | /** | |||
| 912 | * GetParentBrowserParent is used for implementing | |||
| 913 | * nsContentUtils::GetCommonBrowserParentAncestor(). | |||
| 914 | */ | |||
| 915 | struct GetParentBrowserParent { | |||
| 916 | using NodeType = BrowserParent; | |||
| 917 | static NodeType* Get(const NodeType* aBrowserParent) { | |||
| 918 | return aBrowserParent->GetBrowserBridgeParent() | |||
| 919 | ? aBrowserParent->GetBrowserBridgeParent()->Manager() | |||
| 920 | : nullptr; | |||
| 921 | } | |||
| 922 | static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent, | |||
| 923 | const nsIContent* aPossibleChild) { | |||
| 924 | return Nothing(); | |||
| 925 | } | |||
| 926 | static uint32_t GetChildCount(const NodeType* aParent) { | |||
| 927 | return 0; // This should be called only when CanComputeIndex() returns true | |||
| 928 | } | |||
| 929 | constexpr static bool CanComputeIndex() { | |||
| 930 | // Neither ComputeChildIndex() nor GetChildCount() is required by | |||
| 931 | // nsContentUtils::GetCommonBrowserParentAncestor() and there is no API to | |||
| 932 | // get child count of a BrowserParent nor compute index of a child of | |||
| 933 | // BrowserParent. Therefore, we don't implement them so that return false. | |||
| 934 | return false; | |||
| 935 | } | |||
| 936 | }; | |||
| 937 | ||||
| 938 | template <TreeKind aKind> | |||
| 939 | static bool ChildNodeIsInShadowDOMHostedByParent(const nsINode* aParent, | |||
| 940 | const nsINode* aChild) { | |||
| 941 | ShadowRoot* const shadowRoot = aParent->GetShadowRoot<aKind>(); | |||
| 942 | if (!shadowRoot) { | |||
| 943 | return false; | |||
| 944 | } | |||
| 945 | // We already checked whether aChild is in a shadow in the tree kind. | |||
| 946 | // Therefore, we don't need to use GetContainingShadowForSelection() here. | |||
| 947 | return shadowRoot == aChild->GetContainingShadow(); | |||
| 948 | } | |||
| 949 | ||||
| 950 | // If we're comparing 2 DOM points in TreeKind::ShadowIncludingDOM mode, we want | |||
| 951 | // to compare the direct children of the parent node even if the parent is a | |||
| 952 | // shadow host. So, we want to compare them as TreeKind::DOM. | |||
| 953 | template <TreeKind aKind> | |||
| 954 | constexpr TreeKind TreeKindToCompareChildren() { | |||
| 955 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 956 | return TreeKind::DOM; | |||
| 957 | } else { | |||
| 958 | return aKind; | |||
| 959 | } | |||
| 960 | } | |||
| 961 | ||||
| 962 | template <class GetParentStruct> | |||
| 963 | class MOZ_STACK_CLASS CommonAncestors final { | |||
| 964 | public: | |||
| 965 | using NodeType = GetParentStruct::NodeType; | |||
| 966 | ||||
| 967 | /** | |||
| 968 | * @param aNode1 A DOM node or something which may have ancestors. | |||
| 969 | * @param aNode2 Another DOM node or something. | |||
| 970 | * @param aGetParentStruct A struct containing static GetParent(), | |||
| 971 | * ComputeChildIndex(), GetChildCount() and CanComputeIndex(). If | |||
| 972 | * CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount() is | |||
| 973 | * never used. | |||
| 974 | */ | |||
| 975 | CommonAncestors(const NodeType& aNode1, const NodeType& aNode2) { | |||
| 976 | #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1 | |||
| 977 | mAssertNoGC.emplace(); | |||
| 978 | #endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED | |||
| 979 | ||||
| 980 | AppendInclusiveAncestors(const_cast<NodeType*>(&aNode1), | |||
| 981 | mInclusiveAncestors1); | |||
| 982 | AppendInclusiveAncestors(const_cast<NodeType*>(&aNode2), | |||
| 983 | mInclusiveAncestors2); | |||
| 984 | ||||
| 985 | // Find where the parent chain differs | |||
| 986 | size_t depth1 = mInclusiveAncestors1.Length(); | |||
| 987 | size_t depth2 = mInclusiveAncestors2.Length(); | |||
| 988 | const size_t shorterLength = std::min(depth1, depth2); | |||
| 989 | NodeType** const inclusiveAncestors1 = mInclusiveAncestors1.Elements(); | |||
| 990 | NodeType** const inclusiveAncestors2 = mInclusiveAncestors2.Elements(); | |||
| 991 | for ([[maybe_unused]] const size_t unused : IntegerRange(shorterLength)) { | |||
| 992 | NodeType* const inclusiveAncestor1 = inclusiveAncestors1[--depth1]; | |||
| 993 | NodeType* const inclusiveAncestor2 = inclusiveAncestors2[--depth2]; | |||
| 994 | if (inclusiveAncestor1 != inclusiveAncestor2) { | |||
| 995 | MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(inclusiveAncestor1 == GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inclusiveAncestor1 == GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("inclusiveAncestor1 == GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 996); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 996 | inclusiveAncestor1 == GetClosestCommonAncestorChild1())do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(inclusiveAncestor1 == GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inclusiveAncestor1 == GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("inclusiveAncestor1 == GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 996); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 997 | MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(inclusiveAncestor2 == GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inclusiveAncestor2 == GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("inclusiveAncestor2 == GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 998); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 998 | inclusiveAncestor2 == GetClosestCommonAncestorChild2())do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(inclusiveAncestor2 == GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inclusiveAncestor2 == GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("inclusiveAncestor2 == GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 998); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 999 | return; | |||
| 1000 | } | |||
| 1001 | mNumberOfCommonAncestors++; | |||
| 1002 | mClosestCommonAncestor = inclusiveAncestor1; | |||
| 1003 | } | |||
| 1004 | MOZ_ASSERT(mClosestCommonAncestor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mClosestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mClosestCommonAncestor))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mClosestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1004); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mClosestCommonAncestor" ")"); do { MOZ_CrashSequence (__null, 1004); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1005 | MOZ_ASSERT(mNumberOfCommonAncestors)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mNumberOfCommonAncestors)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mNumberOfCommonAncestors))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mNumberOfCommonAncestors" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1005); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence (__null, 1005); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1006 | MOZ_ASSERT(!depth1 || !depth2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!depth1 || !depth2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!depth1 || !depth2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!depth1 || !depth2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1006); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!depth1 || !depth2" ")"); do { MOZ_CrashSequence (__null, 1006); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1007 | MOZ_ASSERT_IF(!depth1, !GetClosestCommonAncestorChild1())do { if (!depth1) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!GetClosestCommonAncestorChild1()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("!GetClosestCommonAncestorChild1()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1007); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 1007); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); | |||
| 1008 | MOZ_ASSERT_IF(depth1, GetClosestCommonAncestorChild1())do { if (depth1) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 1008); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 1009 | MOZ_ASSERT_IF(!depth2, !GetClosestCommonAncestorChild2())do { if (!depth2) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!GetClosestCommonAncestorChild2()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("!GetClosestCommonAncestorChild2()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1009); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 1009); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); | |||
| 1010 | MOZ_ASSERT_IF(depth2, GetClosestCommonAncestorChild2())do { if (depth2) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 1010); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 1011 | } | |||
| 1012 | ||||
| 1013 | #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1 | |||
| 1014 | ~CommonAncestors() { MOZ_DIAGNOSTIC_ASSERT(!mMutationGuard.Mutated(0))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mMutationGuard.Mutated(0))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mMutationGuard.Mutated(0))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mMutationGuard.Mutated(0)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1014); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "!mMutationGuard.Mutated(0)" ")" ); do { MOZ_CrashSequence(__null, 1014); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } | |||
| 1015 | #endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED | |||
| 1016 | ||||
| 1017 | [[nodiscard]] NodeType* GetClosestCommonAncestor() const { | |||
| 1018 | return mClosestCommonAncestor; | |||
| 1019 | } | |||
| 1020 | [[nodiscard]] NodeType* GetClosestCommonAncestorChild1() const { | |||
| 1021 | return GetClosestCommonAncestorChild(mInclusiveAncestors1); | |||
| 1022 | } | |||
| 1023 | [[nodiscard]] NodeType* GetClosestCommonAncestorChild2() const { | |||
| 1024 | return GetClosestCommonAncestorChild(mInclusiveAncestors2); | |||
| 1025 | } | |||
| 1026 | ||||
| 1027 | template <TreeKind aKind> | |||
| 1028 | void WarnIfClosestCommonAncestorChildrenAreNotInChildList() const { | |||
| 1029 | WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>( | |||
| 1030 | mInclusiveAncestors1); | |||
| 1031 | WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>( | |||
| 1032 | mInclusiveAncestors2); | |||
| 1033 | } | |||
| 1034 | ||||
| 1035 | private: | |||
| 1036 | static void AppendInclusiveAncestors(NodeType* aNode, | |||
| 1037 | nsTArray<NodeType*>& aArrayOfParents) { | |||
| 1038 | NodeType* node = aNode; | |||
| 1039 | while (node) { | |||
| 1040 | aArrayOfParents.AppendElement(node); | |||
| 1041 | node = GetParentStruct::Get(node); | |||
| 1042 | } | |||
| 1043 | } | |||
| 1044 | ||||
| 1045 | Maybe<size_t> GetClosestCommonAncestorChildIndex( | |||
| 1046 | const nsTArray<NodeType*>& aInclusiveAncestors) const { | |||
| 1047 | if (!mClosestCommonAncestor || | |||
| 1048 | aInclusiveAncestors.Length() <= mNumberOfCommonAncestors) { | |||
| 1049 | return Nothing(); | |||
| 1050 | } | |||
| 1051 | return Some((aInclusiveAncestors.Length() - 1) // last index | |||
| 1052 | - mNumberOfCommonAncestors); // before closest common ancestor | |||
| 1053 | } | |||
| 1054 | ||||
| 1055 | [[nodiscard]] NodeType* GetClosestCommonAncestorChild( | |||
| 1056 | const nsTArray<NodeType*>& aInclusiveAncestors) const { | |||
| 1057 | const Maybe<size_t> index = | |||
| 1058 | GetClosestCommonAncestorChildIndex(aInclusiveAncestors); | |||
| 1059 | if (index.isNothing()) { | |||
| 1060 | MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(aInclusiveAncestors .Length() == mNumberOfCommonAncestors)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aInclusiveAncestors.Length() == mNumberOfCommonAncestors))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aInclusiveAncestors.Length() == mNumberOfCommonAncestors" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1061); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence(__null, 1061); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 1061 | aInclusiveAncestors.Length() == mNumberOfCommonAncestors)do { if (mClosestCommonAncestor) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(aInclusiveAncestors .Length() == mNumberOfCommonAncestors)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aInclusiveAncestors.Length() == mNumberOfCommonAncestors))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aInclusiveAncestors.Length() == mNumberOfCommonAncestors" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1061); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence(__null, 1061); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 1062 | return nullptr; | |||
| 1063 | } | |||
| 1064 | NodeType* const child = aInclusiveAncestors[*index]; | |||
| 1065 | MOZ_ASSERT(child)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(child))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("child", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child" ")") ; do { MOZ_CrashSequence(__null, 1065); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 1066 | MOZ_ASSERT(GetParentStruct::Get(child) == mClosestCommonAncestor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentStruct::Get(child) == mClosestCommonAncestor )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentStruct::Get(child) == mClosestCommonAncestor ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "GetParentStruct::Get(child) == mClosestCommonAncestor", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetParentStruct::Get(child) == mClosestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 1067 | return child; | |||
| 1068 | } | |||
| 1069 | ||||
| 1070 | template <TreeKind aKind> | |||
| 1071 | void WarnIfClosestCommonAncestorChildIsNotInChildList( | |||
| 1072 | const nsTArray<NodeType*>& aInclusiveAncestors) const { | |||
| 1073 | #ifdef DEBUG1 | |||
| 1074 | if constexpr (std::is_base_of_v<nsINode, NodeType>) { | |||
| 1075 | if (!GetParentStruct::CanComputeIndex()) { | |||
| 1076 | return; | |||
| 1077 | } | |||
| 1078 | const nsIContent* const child = nsIContent::FromNodeOrNull( | |||
| 1079 | GetClosestCommonAncestorChild(aInclusiveAncestors)); | |||
| 1080 | if (!child) { | |||
| 1081 | return; | |||
| 1082 | } | |||
| 1083 | ||||
| 1084 | if (child->IsShadowRoot() || | |||
| 1085 | (ShouldHandleAssignedNodesOnSlot<aKind>() && | |||
| 1086 | child->GetAssignedSlot<aKind>() && | |||
| 1087 | mClosestCommonAncestor != child->GetAssignedSlot<aKind>())) { | |||
| 1088 | return; | |||
| 1089 | } | |||
| 1090 | ||||
| 1091 | if (MOZ_LIKELY((__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor , child) .isSome()), 1)) | |||
| 1092 | GetParentStruct::ComputeChildIndex(mClosestCommonAncestor, child)(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor , child) .isSome()), 1)) | |||
| 1093 | .isSome())(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor , child) .isSome()), 1))) { | |||
| 1094 | return; | |||
| 1095 | } | |||
| 1096 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 1097 | NS_WARNING(ToString(ConstRawRangeBoundary::FromChild(*child)).c_str())NS_DebugBreak(NS_DEBUG_WARNING, ToString(ConstRawRangeBoundary ::FromChild(*child)).c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1097); | |||
| 1098 | const nsINode* const parentOrShadowHostNode = | |||
| 1099 | child->GetParentOrShadowHostNode(); | |||
| 1100 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1101 | fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1102 | "\nparent={}\nlength={}\nshadow={}",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1103 | ToString(RefPtr{parentOrShadowHostNode}).c_str(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1104 | parentOrShadowHostNode->GetChildCount(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1105 | ToString(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1106 | RefPtr{parentOrShadowHostNodeNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1107 | ? parentOrShadowHostNode->GetShadowRoot<aKind>()NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1108 | : nullptr})NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1109 | .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110) | |||
| 1110 | .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}" , ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode ->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode ? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr }) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1110); | |||
| 1111 | } else if constexpr (aKind == TreeKind::FlatForSelection) { | |||
| 1112 | if (child->GetParentNode() == mClosestCommonAncestor) { | |||
| 1113 | // It's okay to compare the non-assigned children of a shadow host | |||
| 1114 | // with the shadow root or another non-assigned child if we're | |||
| 1115 | // handling the flattened tree for selection. | |||
| 1116 | if (mClosestCommonAncestor->GetShadowRootForSelection()) { | |||
| 1117 | return; | |||
| 1118 | } | |||
| 1119 | // It's okay to compare the fallback content of a <slot> which has | |||
| 1120 | // some assigned nodes and a parent of the flattened tree if we're | |||
| 1121 | // handling the flattened tree for selection. | |||
| 1122 | if (mClosestCommonAncestor | |||
| 1123 | ->GetAsHTMLSlotElementIfFilledForSelection()) { | |||
| 1124 | return; | |||
| 1125 | } | |||
| 1126 | } | |||
| 1127 | } | |||
| 1128 | const Maybe<size_t> index = | |||
| 1129 | GetClosestCommonAncestorChildIndex(aInclusiveAncestors); | |||
| 1130 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1131 | fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1132 | "The caller cannot compare the position of the child "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1133 | "of the common ancestor due to not in the child list "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1134 | "of the common ancestor (aKind={}):\n"NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1135 | " {}\n" // common ancestorNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1136 | " + {}\n" // common ancestor childNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1137 | "{}", // child of common ancestor child if there isNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1138 | aKind, ToString(*mClosestCommonAncestor), ToString(*child),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1139 | *index ? fmt::format(" + {}",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1140 | ToString(*aInclusiveAncestors[*index - 1]))NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1141 | : "")NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142) | |||
| 1142 | .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child " "of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n" " {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor ), ToString(*child), *index ? fmt::format(" + {}", ToString (*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1142); | |||
| 1143 | } | |||
| 1144 | #endif | |||
| 1145 | } | |||
| 1146 | ||||
| 1147 | AutoTArray<NodeType*, 30> mInclusiveAncestors1; | |||
| 1148 | AutoTArray<NodeType*, 30> mInclusiveAncestors2; | |||
| 1149 | NodeType* mClosestCommonAncestor = nullptr; | |||
| 1150 | uint32_t mNumberOfCommonAncestors = 0; | |||
| 1151 | ||||
| 1152 | #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1 | |||
| 1153 | nsMutationGuard mMutationGuard; | |||
| 1154 | Maybe<JS::AutoAssertNoGC> mAssertNoGC; | |||
| 1155 | #endif | |||
| 1156 | }; | |||
| 1157 | ||||
| 1158 | /** | |||
| 1159 | * This class is used to determine whether or not the user is currently | |||
| 1160 | * interacting with the browser. It listens to observer events to toggle the | |||
| 1161 | * value of the sUserActive static. | |||
| 1162 | * | |||
| 1163 | * This class is an internal implementation detail. | |||
| 1164 | * nsContentUtils::GetUserIsInteracting() should be used to access current | |||
| 1165 | * user interaction status. | |||
| 1166 | */ | |||
| 1167 | class nsContentUtils::UserInteractionObserver final | |||
| 1168 | : public nsIObserver, | |||
| 1169 | public BackgroundHangAnnotator { | |||
| 1170 | public: | |||
| 1171 | NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread ; public: | |||
| 1172 | NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic , const char16_t * aData) override; | |||
| 1173 | ||||
| 1174 | void Init(); | |||
| 1175 | void Shutdown(); | |||
| 1176 | void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override; | |||
| 1177 | ||||
| 1178 | static Atomic<bool> sUserActive; | |||
| 1179 | ||||
| 1180 | private: | |||
| 1181 | ~UserInteractionObserver() = default; | |||
| 1182 | }; | |||
| 1183 | ||||
| 1184 | static constexpr nsLiteralCString kRfpPrefs[] = { | |||
| 1185 | "privacy.resistFingerprinting"_ns, | |||
| 1186 | "privacy.resistFingerprinting.pbmode"_ns, | |||
| 1187 | "privacy.fingerprintingProtection"_ns, | |||
| 1188 | "privacy.fingerprintingProtection.pbmode"_ns, | |||
| 1189 | "privacy.fingerprintingProtection.overrides"_ns, | |||
| 1190 | "privacy.baselineFingerprintingProtection"_ns, | |||
| 1191 | "privacy.baselineFingerprintingProtection.overrides"_ns, | |||
| 1192 | }; | |||
| 1193 | ||||
| 1194 | static void RecomputeResistFingerprintingAllDocs(const char*, void*) { | |||
| 1195 | AutoTArray<RefPtr<Document>, 64> allDocuments; | |||
| 1196 | Document::GetAllInProcessDocuments(allDocuments); | |||
| 1197 | for (auto& doc : allDocuments) { | |||
| 1198 | doc->RecomputeResistFingerprinting( | |||
| 1199 | /* aForceRefreshRTPCallerType= */ true); | |||
| 1200 | if (auto* pc = doc->GetPresContext()) { | |||
| 1201 | pc->MediaFeatureValuesChanged( | |||
| 1202 | {MediaFeatureChangeReason::PreferenceChange}, | |||
| 1203 | MediaFeatureChangePropagation::JustThisDocument); | |||
| 1204 | } | |||
| 1205 | } | |||
| 1206 | } | |||
| 1207 | ||||
| 1208 | // static | |||
| 1209 | nsresult nsContentUtils::Init() { | |||
| 1210 | if (sInitialized) { | |||
| 1211 | NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1211); | |||
| 1212 | ||||
| 1213 | return NS_OK; | |||
| 1214 | } | |||
| 1215 | ||||
| 1216 | nsHTMLTags::AddRefTable(); | |||
| 1217 | ||||
| 1218 | sXPConnect = nsXPConnect::XPConnect(); | |||
| 1219 | // We hold a strong ref to sXPConnect to ensure that it does not go away until | |||
| 1220 | // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be | |||
| 1221 | // triggered by xpcModuleDtor late in shutdown and cause crashes due to | |||
| 1222 | // various stuff already being torn down by then. Note that this means that | |||
| 1223 | // we are effectively making sure that if we leak nsLayoutStatics then we also | |||
| 1224 | // leak nsXPConnect. | |||
| 1225 | NS_ADDREF(sXPConnect)(sXPConnect)->AddRef(); | |||
| 1226 | ||||
| 1227 | sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager(); | |||
| 1228 | if (!sSecurityManager) return NS_ERROR_FAILURE; | |||
| 1229 | NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef(); | |||
| 1230 | ||||
| 1231 | sSecurityManager->GetSystemPrincipal(&sSystemPrincipal); | |||
| 1232 | MOZ_ASSERT(sSystemPrincipal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sSystemPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sSystemPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sSystemPrincipal" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1232); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "sSystemPrincipal" ")"); do { MOZ_CrashSequence (__null, 1232); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1233 | ||||
| 1234 | RefPtr<NullPrincipal> nullPrincipal = | |||
| 1235 | NullPrincipal::CreateWithoutOriginAttributes(); | |||
| 1236 | if (!nullPrincipal) { | |||
| 1237 | return NS_ERROR_FAILURE; | |||
| 1238 | } | |||
| 1239 | ||||
| 1240 | nullPrincipal.forget(&sNullSubjectPrincipal); | |||
| 1241 | ||||
| 1242 | RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal = | |||
| 1243 | BasePrincipal::CreateContentPrincipal( | |||
| 1244 | "about:fingerprintingprotection"_ns); | |||
| 1245 | if (!fingerprintingProtectionPrincipal) { | |||
| 1246 | return NS_ERROR_FAILURE; | |||
| 1247 | } | |||
| 1248 | ||||
| 1249 | fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal); | |||
| 1250 | ||||
| 1251 | if (!InitializeEventTable()) return NS_ERROR_FAILURE; | |||
| 1252 | ||||
| 1253 | sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>; | |||
| 1254 | ||||
| 1255 | #ifndef RELEASE_OR_BETA | |||
| 1256 | sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK"); | |||
| 1257 | #endif | |||
| 1258 | ||||
| 1259 | Element::InitCCCallbacks(); | |||
| 1260 | ||||
| 1261 | RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate(); | |||
| 1262 | MOZ_ASSERT(rfpService)do { static_assert( mozilla::detail::AssertionConditionType< decltype(rfpService)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(rfpService))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("rfpService", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService" ")"); do { MOZ_CrashSequence(__null, 1262); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 1263 | ||||
| 1264 | if (XRE_IsParentProcess()) { | |||
| 1265 | AsyncPrecreateStringBundles(); | |||
| 1266 | ||||
| 1267 | #if defined(MOZ_WIDGET_ANDROID) | |||
| 1268 | // On Android, at-shutdown ping submission isn't reliable | |||
| 1269 | // (( because, on Android, we usually get killed, not shut down )). | |||
| 1270 | // To have a chance at submitting the ping, aim for idle after startup. | |||
| 1271 | nsresult rv = NS_DispatchToCurrentThreadQueue( | |||
| 1272 | NS_NewRunnableFunction( | |||
| 1273 | "AndroidUseCounterPingSubmitter", | |||
| 1274 | []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }), | |||
| 1275 | EventQueuePriority::Idle); | |||
| 1276 | // This is mostly best-effort, so if it goes awry, just log. | |||
| 1277 | (void)NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1277); | |||
| 1278 | #endif // defined(MOZ_WIDGET_ANDROID) | |||
| 1279 | ||||
| 1280 | RunOnShutdown( | |||
| 1281 | [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); }, | |||
| 1282 | ShutdownPhase::AppShutdownConfirmed); | |||
| 1283 | ||||
| 1284 | // On child process, this is initialized in ContentChild. | |||
| 1285 | LookAndFeel::EnsureInit(); | |||
| 1286 | } | |||
| 1287 | ||||
| 1288 | RefPtr<UserInteractionObserver> uio = new UserInteractionObserver(); | |||
| 1289 | uio->Init(); | |||
| 1290 | uio.forget(&sUserInteractionObserver); | |||
| 1291 | ||||
| 1292 | for (const auto& pref : kRfpPrefs) { | |||
| 1293 | Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref); | |||
| 1294 | } | |||
| 1295 | ||||
| 1296 | mozilla::dom::ReportDeliver::Initialize(); | |||
| 1297 | ||||
| 1298 | sInitialized = true; | |||
| 1299 | ||||
| 1300 | return NS_OK; | |||
| 1301 | } | |||
| 1302 | ||||
| 1303 | bool nsContentUtils::InitJSBytecodeMimeType() { | |||
| 1304 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1304); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 1304); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1305 | MOZ_ASSERT(!sJSScriptBytecodeMimeType)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sJSScriptBytecodeMimeType)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sJSScriptBytecodeMimeType)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sJSScriptBytecodeMimeType" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1305); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType" ")"); do { MOZ_CrashSequence (__null, 1305); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1306 | MOZ_ASSERT(!sJSModuleBytecodeMimeType)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sJSModuleBytecodeMimeType)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sJSModuleBytecodeMimeType)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sJSModuleBytecodeMimeType" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1306); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType" ")"); do { MOZ_CrashSequence (__null, 1306); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 1307 | ||||
| 1308 | JS::BuildIdCharVector jsBuildId; | |||
| 1309 | if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) { | |||
| 1310 | return false; | |||
| 1311 | } | |||
| 1312 | ||||
| 1313 | nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length()); | |||
| 1314 | sJSScriptBytecodeMimeType = | |||
| 1315 | new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr); | |||
| 1316 | sJSModuleBytecodeMimeType = | |||
| 1317 | new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr); | |||
| 1318 | return true; | |||
| 1319 | } | |||
| 1320 | ||||
| 1321 | void nsContentUtils::GetShiftText(nsAString& text) { | |||
| 1322 | if (!sShiftText) InitializeModifierStrings(); | |||
| 1323 | text.Assign(*sShiftText); | |||
| 1324 | } | |||
| 1325 | ||||
| 1326 | void nsContentUtils::GetControlText(nsAString& text) { | |||
| 1327 | if (!sControlText) InitializeModifierStrings(); | |||
| 1328 | text.Assign(*sControlText); | |||
| 1329 | } | |||
| 1330 | ||||
| 1331 | void nsContentUtils::GetCommandOrWinText(nsAString& text) { | |||
| 1332 | if (!sCommandOrWinText) { | |||
| 1333 | InitializeModifierStrings(); | |||
| 1334 | } | |||
| 1335 | text.Assign(*sCommandOrWinText); | |||
| 1336 | } | |||
| 1337 | ||||
| 1338 | void nsContentUtils::GetAltText(nsAString& text) { | |||
| 1339 | if (!sAltText) InitializeModifierStrings(); | |||
| 1340 | text.Assign(*sAltText); | |||
| 1341 | } | |||
| 1342 | ||||
| 1343 | void nsContentUtils::GetModifierSeparatorText(nsAString& text) { | |||
| 1344 | if (!sModifierSeparator) InitializeModifierStrings(); | |||
| 1345 | text.Assign(*sModifierSeparator); | |||
| 1346 | } | |||
| 1347 | ||||
| 1348 | void nsContentUtils::InitializeModifierStrings() { | |||
| 1349 | // load the display strings for the keyboard accelerators | |||
| 1350 | nsCOMPtr<nsIStringBundleService> bundleService = | |||
| 1351 | mozilla::components::StringBundle::Service(); | |||
| 1352 | nsCOMPtr<nsIStringBundle> bundle; | |||
| 1353 | DebugOnly<nsresult> rv = NS_OK; | |||
| 1354 | if (bundleService) { | |||
| 1355 | rv = bundleService->CreateBundle( | |||
| 1356 | "chrome://global-platform/locale/platformKeys.properties", | |||
| 1357 | getter_AddRefs(bundle)); | |||
| 1358 | } | |||
| 1359 | ||||
| 1360 | NS_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded" , "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1362); MOZ_PretendNoReturn(); } } while (0) | |||
| 1361 | NS_SUCCEEDED(rv) && bundle,do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded" , "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1362); MOZ_PretendNoReturn(); } } while (0) | |||
| 1362 | "chrome://global/locale/platformKeys.properties could not be loaded")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded" , "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1362); MOZ_PretendNoReturn(); } } while (0); | |||
| 1363 | nsAutoString shiftModifier; | |||
| 1364 | nsAutoString commandOrWinModifier; | |||
| 1365 | nsAutoString altModifier; | |||
| 1366 | nsAutoString controlModifier; | |||
| 1367 | nsAutoString modifierSeparator; | |||
| 1368 | if (bundle) { | |||
| 1369 | // macs use symbols for each modifier key, so fetch each from the bundle, | |||
| 1370 | // which also covers i18n | |||
| 1371 | bundle->GetStringFromName("VK_SHIFT", shiftModifier); | |||
| 1372 | bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier); | |||
| 1373 | bundle->GetStringFromName("VK_ALT", altModifier); | |||
| 1374 | bundle->GetStringFromName("VK_CONTROL", controlModifier); | |||
| 1375 | bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator); | |||
| 1376 | } | |||
| 1377 | // if any of these don't exist, we get an empty string | |||
| 1378 | sShiftText = new nsString(std::move(shiftModifier)); | |||
| 1379 | sCommandOrWinText = new nsString(std::move(commandOrWinModifier)); | |||
| 1380 | sAltText = new nsString(std::move(altModifier)); | |||
| 1381 | sControlText = new nsString(std::move(controlModifier)); | |||
| 1382 | sModifierSeparator = new nsString(std::move(modifierSeparator)); | |||
| 1383 | } | |||
| 1384 | ||||
| 1385 | mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage( | |||
| 1386 | EventMessage aEventMessage) { | |||
| 1387 | switch (aEventMessage) { | |||
| 1388 | #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ | |||
| 1389 | case message_: \ | |||
| 1390 | return struct_; | |||
| 1391 | #include "mozilla/EventNameList.inc" | |||
| 1392 | #undef MESSAGE_TO_EVENT | |||
| 1393 | default: | |||
| 1394 | MOZ_ASSERT_UNREACHABLE("Invalid event message?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do { MOZ_CrashSequence(__null, 1394); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 1395 | return eBasicEventClass; | |||
| 1396 | } | |||
| 1397 | } | |||
| 1398 | ||||
| 1399 | bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) { | |||
| 1400 | bool doesNotReturnData = false; | |||
| 1401 | nsresult rv = NS_URIChainHasFlags( | |||
| 1402 | aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData); | |||
| 1403 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData; | |||
| 1404 | } | |||
| 1405 | ||||
| 1406 | /* static */ | |||
| 1407 | nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) { | |||
| 1408 | switch (aEventMessage) { | |||
| 1409 | #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ | |||
| 1410 | case message_: \ | |||
| 1411 | return nsGkAtoms::on##name_; | |||
| 1412 | #include "mozilla/EventNameList.inc" | |||
| 1413 | #undef MESSAGE_TO_EVENT | |||
| 1414 | default: | |||
| 1415 | return nullptr; | |||
| 1416 | } | |||
| 1417 | } | |||
| 1418 | ||||
| 1419 | /* static */ | |||
| 1420 | already_AddRefed<nsAtom> nsContentUtils::GetEventType( | |||
| 1421 | const WidgetEvent* aEvent) { | |||
| 1422 | RefPtr<nsAtom> typeAtom = | |||
| 1423 | aEvent->mMessage == eUnidentifiedEvent | |||
| 1424 | ? aEvent->mSpecifiedEventType.get() | |||
| 1425 | : nsContentUtils::GetEventTypeFromMessage(aEvent->mMessage); | |||
| 1426 | return typeAtom.forget(); | |||
| 1427 | } | |||
| 1428 | ||||
| 1429 | bool nsContentUtils::InitializeEventTable() { | |||
| 1430 | NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!")do { if (!(!sAtomEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "EventTable already initialized!", "!sAtomEventTable", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1430); MOZ_PretendNoReturn(); } } while (0); | |||
| 1431 | NS_ASSERTION(!sStringEventTable, "EventTable already initialized!")do { if (!(!sStringEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "EventTable already initialized!", "!sStringEventTable", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 1431); MOZ_PretendNoReturn(); } } while (0); | |||
| 1432 | ||||
| 1433 | static const EventNameMapping eventArray[] = { | |||
| 1434 | #define EVENT(name_, _message, _type, _class) \ | |||
| 1435 | {nsGkAtoms::on##name_, _type, _message, _class}, | |||
| 1436 | #define WINDOW_ONLY_EVENT EVENT | |||
| 1437 | #define DOCUMENT_ONLY_EVENTEVENT EVENT | |||
| 1438 | #define NON_IDL_EVENT EVENT | |||
| 1439 | #include "mozilla/EventNameList.inc" | |||
| 1440 | #undef WINDOW_ONLY_EVENT | |||
| 1441 | #undef NON_IDL_EVENT | |||
| 1442 | #undef EVENT | |||
| 1443 | {nullptr}}; | |||
| 1444 | ||||
| 1445 | sAtomEventTable = | |||
| 1446 | new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray)); | |||
| 1447 | sStringEventTable = | |||
| 1448 | new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray)); | |||
| 1449 | sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64); | |||
| 1450 | ||||
| 1451 | // Subtract one from the length because of the trailing null | |||
| 1452 | for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) { | |||
| 1453 | MOZ_ASSERT(!sAtomEventTable->Contains(eventArray[i].mAtom),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sAtomEventTable->Contains(eventArray[i].mAtom))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!sAtomEventTable->Contains(eventArray[i].mAtom))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sAtomEventTable->Contains(eventArray[i].mAtom)" " (" "Double-defining event name; fix your EventNameList.inc" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1454 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)" ") (" "Double-defining event name; fix your EventNameList.inc" ")"); do { MOZ_CrashSequence(__null, 1454); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 1454 | "Double-defining event name; fix your EventNameList.inc")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sAtomEventTable->Contains(eventArray[i].mAtom))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!sAtomEventTable->Contains(eventArray[i].mAtom))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sAtomEventTable->Contains(eventArray[i].mAtom)" " (" "Double-defining event name; fix your EventNameList.inc" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1454 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)" ") (" "Double-defining event name; fix your EventNameList.inc" ")"); do { MOZ_CrashSequence(__null, 1454); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 1455 | sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]); | |||
| 1456 | sStringEventTable->InsertOrUpdate( | |||
| 1457 | Substring(nsDependentAtomString(eventArray[i].mAtom), 2), | |||
| 1458 | eventArray[i]); | |||
| 1459 | } | |||
| 1460 | ||||
| 1461 | return true; | |||
| 1462 | } | |||
| 1463 | ||||
| 1464 | void nsContentUtils::InitializeTouchEventTable() { | |||
| 1465 | static bool sEventTableInitialized = false; | |||
| 1466 | if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) { | |||
| 1467 | sEventTableInitialized = true; | |||
| 1468 | static const EventNameMapping touchEventArray[] = { | |||
| 1469 | #define EVENT(name_, _message, _type, _class) | |||
| 1470 | #define TOUCH_EVENT(name_, _message, _type, _class) \ | |||
| 1471 | {nsGkAtoms::on##name_, _type, _message, _class}, | |||
| 1472 | #include "mozilla/EventNameList.inc" | |||
| 1473 | #undef TOUCH_EVENT | |||
| 1474 | #undef EVENT | |||
| 1475 | {nullptr}}; | |||
| 1476 | // Subtract one from the length because of the trailing null | |||
| 1477 | for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) { | |||
| 1478 | sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom, | |||
| 1479 | touchEventArray[i]); | |||
| 1480 | sStringEventTable->InsertOrUpdate( | |||
| 1481 | Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2), | |||
| 1482 | touchEventArray[i]); | |||
| 1483 | } | |||
| 1484 | } | |||
| 1485 | } | |||
| 1486 | ||||
| 1487 | static bool Is8bit(const nsAString& aString) { | |||
| 1488 | static const char16_t EIGHT_BIT = char16_t(~0x00FF); | |||
| 1489 | ||||
| 1490 | for (nsAString::const_char_iterator start = aString.BeginReading(), | |||
| 1491 | end = aString.EndReading(); | |||
| 1492 | start != end; ++start) { | |||
| 1493 | if (*start & EIGHT_BIT) { | |||
| 1494 | return false; | |||
| 1495 | } | |||
| 1496 | } | |||
| 1497 | ||||
| 1498 | return true; | |||
| 1499 | } | |||
| 1500 | ||||
| 1501 | nsresult nsContentUtils::Btoa(const nsAString& aBinaryData, | |||
| 1502 | nsAString& aAsciiBase64String) { | |||
| 1503 | if (!Is8bit(aBinaryData)) { | |||
| 1504 | aAsciiBase64String.Truncate(); | |||
| 1505 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 1506 | } | |||
| 1507 | ||||
| 1508 | return Base64Encode(aBinaryData, aAsciiBase64String); | |||
| 1509 | } | |||
| 1510 | ||||
| 1511 | nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String, | |||
| 1512 | nsAString& aBinaryData) { | |||
| 1513 | if (!Is8bit(aAsciiBase64String)) { | |||
| 1514 | aBinaryData.Truncate(); | |||
| 1515 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 1516 | } | |||
| 1517 | ||||
| 1518 | const char16_t* start = aAsciiBase64String.BeginReading(); | |||
| 1519 | const char16_t* cur = start; | |||
| 1520 | const char16_t* end = aAsciiBase64String.EndReading(); | |||
| 1521 | bool hasWhitespace = false; | |||
| 1522 | ||||
| 1523 | while (cur < end) { | |||
| 1524 | if (nsContentUtils::IsHTMLWhitespace(*cur)) { | |||
| 1525 | hasWhitespace = true; | |||
| 1526 | break; | |||
| 1527 | } | |||
| 1528 | cur++; | |||
| 1529 | } | |||
| 1530 | ||||
| 1531 | nsresult rv; | |||
| 1532 | ||||
| 1533 | if (hasWhitespace) { | |||
| 1534 | nsString trimmedString; | |||
| 1535 | ||||
| 1536 | if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) { | |||
| 1537 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 1538 | } | |||
| 1539 | ||||
| 1540 | trimmedString.Append(start, cur - start); | |||
| 1541 | ||||
| 1542 | while (cur < end) { | |||
| 1543 | if (!nsContentUtils::IsHTMLWhitespace(*cur)) { | |||
| 1544 | trimmedString.Append(*cur); | |||
| 1545 | } | |||
| 1546 | cur++; | |||
| 1547 | } | |||
| 1548 | rv = Base64Decode(trimmedString, aBinaryData); | |||
| 1549 | } else { | |||
| 1550 | rv = Base64Decode(aAsciiBase64String, aBinaryData); | |||
| 1551 | } | |||
| 1552 | ||||
| 1553 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) { | |||
| 1554 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 1555 | } | |||
| 1556 | return rv; | |||
| 1557 | } | |||
| 1558 | ||||
| 1559 | bool nsContentUtils::IsAutocompleteEnabled(mozilla::dom::Element* aElement) { | |||
| 1560 | MOZ_ASSERT(aElement, "aElement should not be null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement" " (" "aElement should not be null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1560 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ") (" "aElement should not be null!" ")"); do { MOZ_CrashSequence(__null, 1560); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 1561 | ||||
| 1562 | nsAutoString autocomplete; | |||
| 1563 | ||||
| 1564 | if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) { | |||
| 1565 | input->GetAutocomplete(autocomplete); | |||
| 1566 | } else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) { | |||
| 1567 | textarea->GetAutocomplete(autocomplete); | |||
| 1568 | } | |||
| 1569 | ||||
| 1570 | if (autocomplete.IsEmpty()) { | |||
| 1571 | auto* control = nsGenericHTMLFormControlElement::FromNode(aElement); | |||
| 1572 | auto* form = control->GetFormInternal(); | |||
| 1573 | if (!form) { | |||
| 1574 | return true; | |||
| 1575 | } | |||
| 1576 | ||||
| 1577 | form->GetAutocomplete(autocomplete); | |||
| 1578 | } | |||
| 1579 | ||||
| 1580 | return !autocomplete.EqualsLiteral("off"); | |||
| 1581 | } | |||
| 1582 | ||||
| 1583 | nsContentUtils::AutocompleteAttrState | |||
| 1584 | nsContentUtils::SerializeAutocompleteAttribute( | |||
| 1585 | const nsAttrValue* aAttr, nsAString& aResult, | |||
| 1586 | AutocompleteAttrState aCachedState) { | |||
| 1587 | if (!aAttr || | |||
| 1588 | aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { | |||
| 1589 | return aCachedState; | |||
| 1590 | } | |||
| 1591 | ||||
| 1592 | if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) { | |||
| 1593 | uint32_t atomCount = aAttr->GetAtomCount(); | |||
| 1594 | for (uint32_t i = 0; i < atomCount; i++) { | |||
| 1595 | if (i != 0) { | |||
| 1596 | aResult.Append(' '); | |||
| 1597 | } | |||
| 1598 | aResult.Append(nsDependentAtomString(aAttr->AtomAt(i))); | |||
| 1599 | } | |||
| 1600 | nsContentUtils::ASCIIToLower(aResult); | |||
| 1601 | return aCachedState; | |||
| 1602 | } | |||
| 1603 | ||||
| 1604 | aResult.Truncate(); | |||
| 1605 | ||||
| 1606 | mozilla::dom::AutocompleteInfo info; | |||
| 1607 | AutocompleteAttrState state = | |||
| 1608 | InternalSerializeAutocompleteAttribute(aAttr, info); | |||
| 1609 | if (state == eAutocompleteAttrState_Valid) { | |||
| 1610 | // Concatenate the info fields. | |||
| 1611 | aResult = info.mSection; | |||
| 1612 | ||||
| 1613 | if (!info.mAddressType.IsEmpty()) { | |||
| 1614 | if (!aResult.IsEmpty()) { | |||
| 1615 | aResult += ' '; | |||
| 1616 | } | |||
| 1617 | aResult += info.mAddressType; | |||
| 1618 | } | |||
| 1619 | ||||
| 1620 | if (!info.mContactType.IsEmpty()) { | |||
| 1621 | if (!aResult.IsEmpty()) { | |||
| 1622 | aResult += ' '; | |||
| 1623 | } | |||
| 1624 | aResult += info.mContactType; | |||
| 1625 | } | |||
| 1626 | ||||
| 1627 | if (!info.mFieldName.IsEmpty()) { | |||
| 1628 | if (!aResult.IsEmpty()) { | |||
| 1629 | aResult += ' '; | |||
| 1630 | } | |||
| 1631 | aResult += info.mFieldName; | |||
| 1632 | } | |||
| 1633 | ||||
| 1634 | // The autocomplete attribute value "webauthn" is interpreted as both a | |||
| 1635 | // field name and a credential type. The corresponding IDL-exposed autofill | |||
| 1636 | // value is "webauthn", not "webauthn webauthn". | |||
| 1637 | if (!info.mCredentialType.IsEmpty() && | |||
| 1638 | !(info.mCredentialType.Equals(u"webauthn"_ns) && | |||
| 1639 | info.mCredentialType.Equals(aResult))) { | |||
| 1640 | if (!aResult.IsEmpty()) { | |||
| 1641 | aResult += ' '; | |||
| 1642 | } | |||
| 1643 | aResult += info.mCredentialType; | |||
| 1644 | } | |||
| 1645 | } | |||
| 1646 | ||||
| 1647 | return state; | |||
| 1648 | } | |||
| 1649 | ||||
| 1650 | nsContentUtils::AutocompleteAttrState | |||
| 1651 | nsContentUtils::SerializeAutocompleteAttribute( | |||
| 1652 | const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo, | |||
| 1653 | AutocompleteAttrState aCachedState, bool aGrantAllValidValue) { | |||
| 1654 | if (!aAttr || | |||
| 1655 | aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { | |||
| 1656 | return aCachedState; | |||
| 1657 | } | |||
| 1658 | ||||
| 1659 | return InternalSerializeAutocompleteAttribute(aAttr, aInfo, | |||
| 1660 | aGrantAllValidValue); | |||
| 1661 | } | |||
| 1662 | ||||
| 1663 | /** | |||
| 1664 | * Helper to validate the @autocomplete tokens. | |||
| 1665 | * | |||
| 1666 | * @return {AutocompleteAttrState} The state of the attribute (invalid/valid). | |||
| 1667 | */ | |||
| 1668 | nsContentUtils::AutocompleteAttrState | |||
| 1669 | nsContentUtils::InternalSerializeAutocompleteAttribute( | |||
| 1670 | const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo, | |||
| 1671 | bool aGrantAllValidValue) { | |||
| 1672 | // No autocomplete attribute so we are done | |||
| 1673 | if (!aAttrVal) { | |||
| 1674 | return eAutocompleteAttrState_Invalid; | |||
| 1675 | } | |||
| 1676 | ||||
| 1677 | uint32_t numTokens = aAttrVal->GetAtomCount(); | |||
| 1678 | if (!numTokens || numTokens > INT32_MAX(2147483647)) { | |||
| 1679 | return eAutocompleteAttrState_Invalid; | |||
| 1680 | } | |||
| 1681 | ||||
| 1682 | uint32_t index = numTokens - 1; | |||
| 1683 | nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
| 1684 | AutocompleteCategory category; | |||
| 1685 | nsAttrValue enumValue; | |||
| 1686 | nsAutoString credentialTypeStr; | |||
| 1687 | ||||
| 1688 | bool result = enumValue.ParseEnumValue( | |||
| 1689 | tokenString, kAutocompleteCredentialTypeTable, false); | |||
| 1690 | if (result) { | |||
| 1691 | if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) { | |||
| 1692 | return eAutocompleteAttrState_Invalid; | |||
| 1693 | } | |||
| 1694 | enumValue.ToString(credentialTypeStr); | |||
| 1695 | ASCIIToLower(credentialTypeStr); | |||
| 1696 | // category is Credential and the indexth token is "webauthn" | |||
| 1697 | if (index == 0) { | |||
| 1698 | aInfo.mFieldName.Assign(credentialTypeStr); | |||
| 1699 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
| 1700 | return eAutocompleteAttrState_Valid; | |||
| 1701 | } | |||
| 1702 | ||||
| 1703 | --index; | |||
| 1704 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
| 1705 | ||||
| 1706 | // Only the Normal and Contact categories are allowed with webauthn | |||
| 1707 | // - disallow Credential | |||
| 1708 | if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable, | |||
| 1709 | false)) { | |||
| 1710 | return eAutocompleteAttrState_Invalid; | |||
| 1711 | } | |||
| 1712 | // - disallow Off and Automatic | |||
| 1713 | if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, | |||
| 1714 | false)) { | |||
| 1715 | if (enumValue.Equals(u"off"_ns, eIgnoreCase) || | |||
| 1716 | enumValue.Equals(u"on"_ns, eIgnoreCase)) { | |||
| 1717 | return eAutocompleteAttrState_Invalid; | |||
| 1718 | } | |||
| 1719 | } | |||
| 1720 | ||||
| 1721 | // Proceed to process the remaining tokens as if "webauthn" was not present. | |||
| 1722 | // We need to decrement numTokens to enforce the correct per-category limits | |||
| 1723 | // on the maximum number of tokens. | |||
| 1724 | --numTokens; | |||
| 1725 | } | |||
| 1726 | ||||
| 1727 | bool unsupported = false; | |||
| 1728 | if (!aGrantAllValidValue) { | |||
| 1729 | unsupported = enumValue.ParseEnumValue( | |||
| 1730 | tokenString, kAutocompleteUnsupportedFieldNameTable, false); | |||
| 1731 | if (unsupported) { | |||
| 1732 | return eAutocompleteAttrState_Invalid; | |||
| 1733 | } | |||
| 1734 | } | |||
| 1735 | ||||
| 1736 | nsAutoString fieldNameStr; | |||
| 1737 | result = | |||
| 1738 | enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false); | |||
| 1739 | ||||
| 1740 | if (result) { | |||
| 1741 | // Off/Automatic/Normal categories. | |||
| 1742 | if (enumValue.Equals(u"off"_ns, eIgnoreCase) || | |||
| 1743 | enumValue.Equals(u"on"_ns, eIgnoreCase)) { | |||
| 1744 | if (numTokens > 1) { | |||
| 1745 | return eAutocompleteAttrState_Invalid; | |||
| 1746 | } | |||
| 1747 | enumValue.ToString(fieldNameStr); | |||
| 1748 | ASCIIToLower(fieldNameStr); | |||
| 1749 | aInfo.mFieldName.Assign(fieldNameStr); | |||
| 1750 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
| 1751 | aInfo.mCanAutomaticallyPersist = | |||
| 1752 | !enumValue.Equals(u"off"_ns, eIgnoreCase); | |||
| 1753 | return eAutocompleteAttrState_Valid; | |||
| 1754 | } | |||
| 1755 | ||||
| 1756 | // Only allow on/off if form autofill @autocomplete values aren't enabled | |||
| 1757 | // and it doesn't grant all valid values. | |||
| 1758 | if (!StaticPrefs::dom_forms_autocomplete_formautofill() && | |||
| 1759 | !aGrantAllValidValue) { | |||
| 1760 | return eAutocompleteAttrState_Invalid; | |||
| 1761 | } | |||
| 1762 | ||||
| 1763 | // Normal category | |||
| 1764 | if (numTokens > 3) { | |||
| 1765 | return eAutocompleteAttrState_Invalid; | |||
| 1766 | } | |||
| 1767 | category = eAutocompleteCategory_NORMAL; | |||
| 1768 | } else { // Check if the last token is of the contact category instead. | |||
| 1769 | // Only allow on/off if form autofill @autocomplete values aren't enabled | |||
| 1770 | // and it doesn't grant all valid values. | |||
| 1771 | if (!StaticPrefs::dom_forms_autocomplete_formautofill() && | |||
| 1772 | !aGrantAllValidValue) { | |||
| 1773 | return eAutocompleteAttrState_Invalid; | |||
| 1774 | } | |||
| 1775 | ||||
| 1776 | result = enumValue.ParseEnumValue( | |||
| 1777 | tokenString, kAutocompleteContactFieldNameTable, false); | |||
| 1778 | if (!result || numTokens > 4) { | |||
| 1779 | return eAutocompleteAttrState_Invalid; | |||
| 1780 | } | |||
| 1781 | ||||
| 1782 | category = eAutocompleteCategory_CONTACT; | |||
| 1783 | } | |||
| 1784 | ||||
| 1785 | enumValue.ToString(fieldNameStr); | |||
| 1786 | ASCIIToLower(fieldNameStr); | |||
| 1787 | ||||
| 1788 | aInfo.mFieldName.Assign(fieldNameStr); | |||
| 1789 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
| 1790 | aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue( | |||
| 1791 | tokenString, kAutocompleteNoPersistFieldNameTable, false); | |||
| 1792 | ||||
| 1793 | // We are done if this was the only token. | |||
| 1794 | if (numTokens == 1) { | |||
| 1795 | return eAutocompleteAttrState_Valid; | |||
| 1796 | } | |||
| 1797 | ||||
| 1798 | --index; | |||
| 1799 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
| 1800 | ||||
| 1801 | if (category == eAutocompleteCategory_CONTACT) { | |||
| 1802 | if (!aGrantAllValidValue) { | |||
| 1803 | unsupported = enumValue.ParseEnumValue( | |||
| 1804 | tokenString, kAutocompleteUnsupportedContactFieldHintTable, false); | |||
| 1805 | if (unsupported) { | |||
| 1806 | return eAutocompleteAttrState_Invalid; | |||
| 1807 | } | |||
| 1808 | } | |||
| 1809 | ||||
| 1810 | nsAttrValue contactFieldHint; | |||
| 1811 | result = contactFieldHint.ParseEnumValue( | |||
| 1812 | tokenString, kAutocompleteContactFieldHintTable, false); | |||
| 1813 | if (result) { | |||
| 1814 | nsAutoString contactFieldHintString; | |||
| 1815 | contactFieldHint.ToString(contactFieldHintString); | |||
| 1816 | ASCIIToLower(contactFieldHintString); | |||
| 1817 | aInfo.mContactType.Assign(contactFieldHintString); | |||
| 1818 | if (index == 0) { | |||
| 1819 | return eAutocompleteAttrState_Valid; | |||
| 1820 | } | |||
| 1821 | --index; | |||
| 1822 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
| 1823 | } | |||
| 1824 | } | |||
| 1825 | ||||
| 1826 | // Check for billing/shipping tokens | |||
| 1827 | nsAttrValue fieldHint; | |||
| 1828 | if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, | |||
| 1829 | false)) { | |||
| 1830 | nsString fieldHintString; | |||
| 1831 | fieldHint.ToString(fieldHintString); | |||
| 1832 | ASCIIToLower(fieldHintString); | |||
| 1833 | aInfo.mAddressType.Assign(fieldHintString); | |||
| 1834 | if (index == 0) { | |||
| 1835 | return eAutocompleteAttrState_Valid; | |||
| 1836 | } | |||
| 1837 | --index; | |||
| 1838 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
| 1839 | } | |||
| 1840 | ||||
| 1841 | // Check for section-* token | |||
| 1842 | const nsDependentSubstring& section = Substring(tokenString, 0, 8); | |||
| 1843 | if (section.LowerCaseEqualsASCII("section-")) { | |||
| 1844 | ASCIIToLower(tokenString); | |||
| 1845 | aInfo.mSection.Assign(tokenString); | |||
| 1846 | if (index == 0) { | |||
| 1847 | return eAutocompleteAttrState_Valid; | |||
| 1848 | } | |||
| 1849 | } | |||
| 1850 | ||||
| 1851 | // Clear the fields as the autocomplete attribute is invalid. | |||
| 1852 | aInfo.mSection.Truncate(); | |||
| 1853 | aInfo.mAddressType.Truncate(); | |||
| 1854 | aInfo.mContactType.Truncate(); | |||
| 1855 | aInfo.mFieldName.Truncate(); | |||
| 1856 | aInfo.mCredentialType.Truncate(); | |||
| 1857 | ||||
| 1858 | return eAutocompleteAttrState_Invalid; | |||
| 1859 | } | |||
| 1860 | ||||
| 1861 | // Parse an integer according to HTML spec | |||
| 1862 | template <class CharT> | |||
| 1863 | int32_t nsContentUtils::ParseHTMLIntegerImpl( | |||
| 1864 | const CharT* aStart, const CharT* aEnd, | |||
| 1865 | ParseHTMLIntegerResultFlags* aResult) { | |||
| 1866 | int result = eParseHTMLInteger_NoFlags; | |||
| 1867 | ||||
| 1868 | const CharT* iter = aStart; | |||
| 1869 | ||||
| 1870 | while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) { | |||
| 1871 | result |= eParseHTMLInteger_NonStandard; | |||
| 1872 | ++iter; | |||
| 1873 | } | |||
| 1874 | ||||
| 1875 | if (iter == aEnd) { | |||
| 1876 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; | |||
| 1877 | *aResult = (ParseHTMLIntegerResultFlags)result; | |||
| 1878 | return 0; | |||
| 1879 | } | |||
| 1880 | ||||
| 1881 | int sign = 1; | |||
| 1882 | if (*iter == CharT('-')) { | |||
| 1883 | sign = -1; | |||
| 1884 | result |= eParseHTMLInteger_Negative; | |||
| 1885 | ++iter; | |||
| 1886 | } else if (*iter == CharT('+')) { | |||
| 1887 | result |= eParseHTMLInteger_NonStandard; | |||
| 1888 | ++iter; | |||
| 1889 | } | |||
| 1890 | ||||
| 1891 | bool foundValue = false; | |||
| 1892 | CheckedInt32 value = 0; | |||
| 1893 | ||||
| 1894 | // Check for leading zeros first. | |||
| 1895 | uint64_t leadingZeros = 0; | |||
| 1896 | while (iter != aEnd) { | |||
| 1897 | if (*iter != CharT('0')) { | |||
| 1898 | break; | |||
| 1899 | } | |||
| 1900 | ||||
| 1901 | ++leadingZeros; | |||
| 1902 | foundValue = true; | |||
| 1903 | ++iter; | |||
| 1904 | } | |||
| 1905 | ||||
| 1906 | while (iter != aEnd) { | |||
| 1907 | if (*iter >= CharT('0') && *iter <= CharT('9')) { | |||
| 1908 | value = (value * 10) + (*iter - CharT('0')) * sign; | |||
| 1909 | ++iter; | |||
| 1910 | if (!value.isValid()) { | |||
| 1911 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow; | |||
| 1912 | break; | |||
| 1913 | } | |||
| 1914 | foundValue = true; | |||
| 1915 | } else { | |||
| 1916 | break; | |||
| 1917 | } | |||
| 1918 | } | |||
| 1919 | ||||
| 1920 | if (!foundValue) { | |||
| 1921 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; | |||
| 1922 | } | |||
| 1923 | ||||
| 1924 | if (value.isValid() && | |||
| 1925 | ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) || | |||
| 1926 | (sign == -1 && value == 0))) { | |||
| 1927 | result |= eParseHTMLInteger_NonStandard; | |||
| 1928 | } | |||
| 1929 | ||||
| 1930 | if (iter != aEnd) { | |||
| 1931 | result |= eParseHTMLInteger_DidNotConsumeAllInput; | |||
| 1932 | } | |||
| 1933 | ||||
| 1934 | *aResult = (ParseHTMLIntegerResultFlags)result; | |||
| 1935 | return value.isValid() ? value.value() : 0; | |||
| 1936 | } | |||
| 1937 | ||||
| 1938 | // Parse an integer according to HTML spec | |||
| 1939 | int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart, | |||
| 1940 | const char16_t* aEnd, | |||
| 1941 | ParseHTMLIntegerResultFlags* aResult) { | |||
| 1942 | return ParseHTMLIntegerImpl(aStart, aEnd, aResult); | |||
| 1943 | } | |||
| 1944 | ||||
| 1945 | int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd, | |||
| 1946 | ParseHTMLIntegerResultFlags* aResult) { | |||
| 1947 | return ParseHTMLIntegerImpl(aStart, aEnd, aResult); | |||
| 1948 | } | |||
| 1949 | ||||
| 1950 | Maybe<double> nsContentUtils::ParseHTMLFloatingPointNumber( | |||
| 1951 | const nsAString& aString) { | |||
| 1952 | // Check if it is a valid floating-point number first since the result of | |||
| 1953 | // nsString.ToDouble() is more lenient than the spec, | |||
| 1954 | // https://html.spec.whatwg.org/#valid-floating-point-number | |||
| 1955 | nsAString::const_iterator iter, end; | |||
| 1956 | aString.BeginReading(iter); | |||
| 1957 | aString.EndReading(end); | |||
| 1958 | ||||
| 1959 | if (iter == end) { | |||
| 1960 | return {}; | |||
| 1961 | } | |||
| 1962 | ||||
| 1963 | if (*iter == char16_t('-') && ++iter == end) { | |||
| 1964 | return {}; | |||
| 1965 | } | |||
| 1966 | ||||
| 1967 | if (IsAsciiDigit(*iter)) { | |||
| 1968 | for (; iter != end && IsAsciiDigit(*iter); ++iter); | |||
| 1969 | } else if (*iter == char16_t('.')) { | |||
| 1970 | // Do nothing, jumps to fraction part | |||
| 1971 | } else { | |||
| 1972 | return {}; | |||
| 1973 | } | |||
| 1974 | ||||
| 1975 | // Fraction | |||
| 1976 | if (*iter == char16_t('.')) { | |||
| 1977 | ++iter; | |||
| 1978 | if (iter == end || !IsAsciiDigit(*iter)) { | |||
| 1979 | // U+002E FULL STOP character (.) must be followed by one or more ASCII | |||
| 1980 | // digits | |||
| 1981 | return {}; | |||
| 1982 | } | |||
| 1983 | ||||
| 1984 | for (; iter != end && IsAsciiDigit(*iter); ++iter); | |||
| 1985 | } | |||
| 1986 | ||||
| 1987 | if (iter != end && (*iter == char16_t('e') || *iter == char16_t('E'))) { | |||
| 1988 | ++iter; | |||
| 1989 | if (*iter == char16_t('-') || *iter == char16_t('+')) { | |||
| 1990 | ++iter; | |||
| 1991 | } | |||
| 1992 | ||||
| 1993 | if (iter == end || !IsAsciiDigit(*iter)) { | |||
| 1994 | // Should have one or more ASCII digits | |||
| 1995 | return {}; | |||
| 1996 | } | |||
| 1997 | ||||
| 1998 | for (; iter != end && IsAsciiDigit(*iter); ++iter); | |||
| 1999 | } | |||
| 2000 | ||||
| 2001 | if (iter != end) { | |||
| 2002 | return {}; | |||
| 2003 | } | |||
| 2004 | ||||
| 2005 | nsresult rv; | |||
| 2006 | double result = PromiseFlatStringTPromiseFlatString<char16_t>(aString).ToDouble(&rv); | |||
| 2007 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 2008 | return {}; | |||
| 2009 | } | |||
| 2010 | return Some(result); | |||
| 2011 | } | |||
| 2012 | ||||
| 2013 | #define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*( iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res ); } \ | |||
| 2014 | while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \ | |||
| 2015 | ++(iter); \ | |||
| 2016 | } \ | |||
| 2017 | if ((iter) == (end_iter)) { \ | |||
| 2018 | return (end_res); \ | |||
| 2019 | } | |||
| 2020 | ||||
| 2021 | #define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(* (iter)) && *(iter) != '=') { ++(iter); } \ | |||
| 2022 | while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \ | |||
| 2023 | *(iter) != '=') { \ | |||
| 2024 | ++(iter); \ | |||
| 2025 | } | |||
| 2026 | ||||
| 2027 | bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, | |||
| 2028 | nsAtom* aName, nsAString& aValue) { | |||
| 2029 | aValue.Truncate(); | |||
| 2030 | ||||
| 2031 | const char16_t* start = aSource.get(); | |||
| 2032 | const char16_t* end = start + aSource.Length(); | |||
| 2033 | const char16_t* iter; | |||
| 2034 | ||||
| 2035 | while (start != end) { | |||
| 2036 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
| 2037 | iter = start; | |||
| 2038 | SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter )) && *(iter) != '=') { ++(iter); } | |||
| 2039 | ||||
| 2040 | if (start == iter) { | |||
| 2041 | return false; | |||
| 2042 | } | |||
| 2043 | ||||
| 2044 | // Remember the attr name. | |||
| 2045 | const nsDependentSubstring& attrName = Substring(start, iter); | |||
| 2046 | ||||
| 2047 | // Now check whether this is a valid name="value" pair. | |||
| 2048 | start = iter; | |||
| 2049 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
| 2050 | if (*start != '=') { | |||
| 2051 | // No '=', so this is not a name="value" pair. We don't know | |||
| 2052 | // what it is, and we have no way to handle it. | |||
| 2053 | return false; | |||
| 2054 | } | |||
| 2055 | ||||
| 2056 | // Have to skip the value. | |||
| 2057 | ++start; | |||
| 2058 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
| 2059 | char16_t q = *start; | |||
| 2060 | if (q != kQuote && q != kApostrophe) { | |||
| 2061 | // Not a valid quoted value, so bail. | |||
| 2062 | return false; | |||
| 2063 | } | |||
| 2064 | ||||
| 2065 | ++start; // Point to the first char of the value. | |||
| 2066 | iter = start; | |||
| 2067 | ||||
| 2068 | while (iter != end && *iter != q) { | |||
| 2069 | ++iter; | |||
| 2070 | } | |||
| 2071 | ||||
| 2072 | if (iter == end) { | |||
| 2073 | // Oops, unterminated quoted string. | |||
| 2074 | return false; | |||
| 2075 | } | |||
| 2076 | ||||
| 2077 | // At this point attrName holds the name of the "attribute" and | |||
| 2078 | // the value is between start and iter. | |||
| 2079 | ||||
| 2080 | if (aName->Equals(attrName)) { | |||
| 2081 | // We'll accumulate as many characters as possible (until we hit either | |||
| 2082 | // the end of the string or the beginning of an entity). Chunks will be | |||
| 2083 | // delimited by start and chunkEnd. | |||
| 2084 | const char16_t* chunkEnd = start; | |||
| 2085 | while (chunkEnd != iter) { | |||
| 2086 | if (*chunkEnd == kLessThan) { | |||
| 2087 | aValue.Truncate(); | |||
| 2088 | ||||
| 2089 | return false; | |||
| 2090 | } | |||
| 2091 | ||||
| 2092 | if (*chunkEnd == kAmpersand) { | |||
| 2093 | aValue.Append(start, chunkEnd - start); | |||
| 2094 | ||||
| 2095 | const char16_t* afterEntity = nullptr; | |||
| 2096 | char16_t result[2]; | |||
| 2097 | uint32_t count = MOZ_XMLTranslateEntity( | |||
| 2098 | reinterpret_cast<const char*>(chunkEnd), | |||
| 2099 | reinterpret_cast<const char*>(iter), | |||
| 2100 | reinterpret_cast<const char**>(&afterEntity), result); | |||
| 2101 | if (count == 0) { | |||
| 2102 | aValue.Truncate(); | |||
| 2103 | ||||
| 2104 | return false; | |||
| 2105 | } | |||
| 2106 | ||||
| 2107 | aValue.Append(result, count); | |||
| 2108 | ||||
| 2109 | // Advance to after the entity and begin a new chunk. | |||
| 2110 | start = chunkEnd = afterEntity; | |||
| 2111 | } else { | |||
| 2112 | ++chunkEnd; | |||
| 2113 | } | |||
| 2114 | } | |||
| 2115 | ||||
| 2116 | // Append remainder. | |||
| 2117 | aValue.Append(start, iter - start); | |||
| 2118 | ||||
| 2119 | return true; | |||
| 2120 | } | |||
| 2121 | ||||
| 2122 | // Resume scanning after the end of the attribute value (past the quote | |||
| 2123 | // char). | |||
| 2124 | start = iter + 1; | |||
| 2125 | } | |||
| 2126 | ||||
| 2127 | return false; | |||
| 2128 | } | |||
| 2129 | ||||
| 2130 | bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) { | |||
| 2131 | // Create MIME type as "text/" + given input | |||
| 2132 | nsAutoString mimeType(u"text/"); | |||
| 2133 | mimeType.Append(aName); | |||
| 2134 | ||||
| 2135 | return IsJavascriptMIMEType(mimeType); | |||
| 2136 | } | |||
| 2137 | ||||
| 2138 | void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType, | |||
| 2139 | nsString& aParams) { | |||
| 2140 | aType.Truncate(); | |||
| 2141 | aParams.Truncate(); | |||
| 2142 | int32_t semiIndex = aValue.FindChar(char16_t(';')); | |||
| 2143 | if (-1 != semiIndex) { | |||
| 2144 | aType = Substring(aValue, 0, semiIndex); | |||
| 2145 | aParams = | |||
| 2146 | Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1)); | |||
| 2147 | aParams.StripWhitespace(); | |||
| 2148 | } else { | |||
| 2149 | aType = aValue; | |||
| 2150 | } | |||
| 2151 | aType.StripWhitespace(); | |||
| 2152 | } | |||
| 2153 | ||||
| 2154 | /** | |||
| 2155 | * A helper function that parses a sandbox attribute (of an <iframe> or a CSP | |||
| 2156 | * directive) and converts it to the set of flags used internally. | |||
| 2157 | * | |||
| 2158 | * @param aSandboxAttr the sandbox attribute | |||
| 2159 | * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is | |||
| 2160 | * null) | |||
| 2161 | */ | |||
| 2162 | uint32_t nsContentUtils::ParseSandboxAttributeToFlags( | |||
| 2163 | const nsAttrValue* aSandboxAttr) { | |||
| 2164 | if (!aSandboxAttr) { | |||
| 2165 | return SANDBOXED_NONE; | |||
| 2166 | } | |||
| 2167 | ||||
| 2168 | uint32_t out = SANDBOX_ALL_FLAGS; | |||
| 2169 | ||||
| 2170 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
| 2171 | if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \ | |||
| 2172 | out &= ~(flags); \ | |||
| 2173 | } | |||
| 2174 | #include "IframeSandboxKeywordList.inc" | |||
| 2175 | #undef SANDBOX_KEYWORD | |||
| 2176 | ||||
| 2177 | return out; | |||
| 2178 | } | |||
| 2179 | ||||
| 2180 | /** | |||
| 2181 | * A helper function that checks if a string matches a valid sandbox flag. | |||
| 2182 | * | |||
| 2183 | * @param aFlag the potential sandbox flag. | |||
| 2184 | * @return true if the flag is a sandbox flag. | |||
| 2185 | */ | |||
| 2186 | bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) { | |||
| 2187 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
| 2188 | if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \ | |||
| 2189 | return true; \ | |||
| 2190 | } | |||
| 2191 | #include "IframeSandboxKeywordList.inc" | |||
| 2192 | #undef SANDBOX_KEYWORD | |||
| 2193 | return false; | |||
| 2194 | } | |||
| 2195 | ||||
| 2196 | /** | |||
| 2197 | * A helper function that returns a string attribute corresponding to the | |||
| 2198 | * sandbox flags. | |||
| 2199 | * | |||
| 2200 | * @param aFlags the sandbox flags | |||
| 2201 | * @param aString the attribute corresponding to the flags (null if aFlags | |||
| 2202 | * is zero) | |||
| 2203 | */ | |||
| 2204 | void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) { | |||
| 2205 | if (!aFlags) { | |||
| 2206 | SetDOMStringToNull(aString); | |||
| 2207 | return; | |||
| 2208 | } | |||
| 2209 | ||||
| 2210 | aString.Truncate(); | |||
| 2211 | ||||
| 2212 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
| 2213 | if (!(aFlags & (flags))) { \ | |||
| 2214 | if (!aString.IsEmpty()) { \ | |||
| 2215 | aString.AppendLiteral(u" "); \ | |||
| 2216 | } \ | |||
| 2217 | aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \ | |||
| 2218 | } | |||
| 2219 | #include "IframeSandboxKeywordList.inc" | |||
| 2220 | #undef SANDBOX_KEYWORD | |||
| 2221 | } | |||
| 2222 | ||||
| 2223 | nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() { | |||
| 2224 | if (!sBidiKeyboard) { | |||
| 2225 | sBidiKeyboard = nsIWidget::CreateBidiKeyboard(); | |||
| 2226 | } | |||
| 2227 | return sBidiKeyboard; | |||
| 2228 | } | |||
| 2229 | ||||
| 2230 | // static | |||
| 2231 | bool nsContentUtils::IsAlphanumeric(uint32_t aChar) { | |||
| 2232 | nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar); | |||
| 2233 | ||||
| 2234 | return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber); | |||
| 2235 | } | |||
| 2236 | ||||
| 2237 | // static | |||
| 2238 | bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) { | |||
| 2239 | nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar); | |||
| 2240 | ||||
| 2241 | return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber || | |||
| 2242 | cat == nsUGenCategory::kSymbol; | |||
| 2243 | } | |||
| 2244 | ||||
| 2245 | // static | |||
| 2246 | bool nsContentUtils::IsHyphen(uint32_t aChar) { | |||
| 2247 | // Characters treated as hyphens for the purpose of "emergency" breaking | |||
| 2248 | // when the content would otherwise overflow. | |||
| 2249 | return aChar == uint32_t('-') || // HYPHEN-MINUS | |||
| 2250 | aChar == 0x2010 || // HYPHEN | |||
| 2251 | aChar == 0x2012 || // FIGURE DASH | |||
| 2252 | aChar == 0x2013 || // EN DASH | |||
| 2253 | aChar == 0x058A; // ARMENIAN HYPHEN | |||
| 2254 | } | |||
| 2255 | ||||
| 2256 | /* static */ | |||
| 2257 | bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) { | |||
| 2258 | return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) || | |||
| 2259 | aChar == char16_t(0x000C) || aChar == char16_t(0x000D) || | |||
| 2260 | aChar == char16_t(0x0020); | |||
| 2261 | } | |||
| 2262 | ||||
| 2263 | /* static */ | |||
| 2264 | bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) { | |||
| 2265 | return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0); | |||
| 2266 | } | |||
| 2267 | ||||
| 2268 | /* static */ | |||
| 2269 | bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) { | |||
| 2270 | return aContent->IsAnyOfHTMLElements( | |||
| 2271 | nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside, | |||
| 2272 | nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div, | |||
| 2273 | nsGkAtoms::dl, // XXX why not dt and dd? | |||
| 2274 | nsGkAtoms::fieldset, | |||
| 2275 | nsGkAtoms::figure, // XXX shouldn't figcaption be on this list | |||
| 2276 | nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2, | |||
| 2277 | nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, | |||
| 2278 | nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li, | |||
| 2279 | nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol, | |||
| 2280 | nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table, | |||
| 2281 | nsGkAtoms::ul, nsGkAtoms::xmp); | |||
| 2282 | } | |||
| 2283 | ||||
| 2284 | // static | |||
| 2285 | int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) { | |||
| 2286 | nsAString::const_iterator iter, end; | |||
| 2287 | aValue.BeginReading(iter); | |||
| 2288 | aValue.EndReading(end); | |||
| 2289 | ||||
| 2290 | while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { | |||
| 2291 | ++iter; | |||
| 2292 | } | |||
| 2293 | ||||
| 2294 | if (iter == end) { | |||
| 2295 | return 0; | |||
| 2296 | } | |||
| 2297 | ||||
| 2298 | bool relative = false; | |||
| 2299 | bool negate = false; | |||
| 2300 | if (*iter == char16_t('-')) { | |||
| 2301 | relative = true; | |||
| 2302 | negate = true; | |||
| 2303 | ++iter; | |||
| 2304 | } else if (*iter == char16_t('+')) { | |||
| 2305 | relative = true; | |||
| 2306 | ++iter; | |||
| 2307 | } | |||
| 2308 | ||||
| 2309 | if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) { | |||
| 2310 | return 0; | |||
| 2311 | } | |||
| 2312 | ||||
| 2313 | // We don't have to worry about overflow, since we can bail out as soon as | |||
| 2314 | // we're bigger than 7. | |||
| 2315 | int32_t value = 0; | |||
| 2316 | while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) { | |||
| 2317 | value = 10 * value + (*iter - char16_t('0')); | |||
| 2318 | if (value >= 7) { | |||
| 2319 | break; | |||
| 2320 | } | |||
| 2321 | ++iter; | |||
| 2322 | } | |||
| 2323 | ||||
| 2324 | if (relative) { | |||
| 2325 | if (negate) { | |||
| 2326 | value = 3 - value; | |||
| 2327 | } else { | |||
| 2328 | value = 3 + value; | |||
| 2329 | } | |||
| 2330 | } | |||
| 2331 | ||||
| 2332 | return std::clamp(value, 1, 7); | |||
| 2333 | } | |||
| 2334 | ||||
| 2335 | /* static */ | |||
| 2336 | void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) { | |||
| 2337 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2337); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 2337); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 2338 | MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDocument)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { MOZ_CrashSequence(__null, 2338); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 2339 | *aURI = nullptr; | |||
| 2340 | ||||
| 2341 | if (aDocument->GetController().isSome()) { | |||
| 2342 | return; | |||
| 2343 | } | |||
| 2344 | ||||
| 2345 | Element* docElement = aDocument->GetRootElement(); | |||
| 2346 | if (!docElement) { | |||
| 2347 | return; | |||
| 2348 | } | |||
| 2349 | ||||
| 2350 | nsAutoString manifestSpec; | |||
| 2351 | docElement->GetAttr(nsGkAtoms::manifest, manifestSpec); | |||
| 2352 | ||||
| 2353 | // Manifest URIs can't have fragment identifiers. | |||
| 2354 | if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) { | |||
| 2355 | return; | |||
| 2356 | } | |||
| 2357 | ||||
| 2358 | nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument, | |||
| 2359 | aDocument->GetDocBaseURI()); | |||
| 2360 | } | |||
| 2361 | ||||
| 2362 | /* static */ | |||
| 2363 | bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; } | |||
| 2364 | ||||
| 2365 | /* static */ | |||
| 2366 | bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) { | |||
| 2367 | return false; | |||
| 2368 | } | |||
| 2369 | // Static | |||
| 2370 | bool nsContentUtils::IsErrorPage(nsIURI* aURI) { | |||
| 2371 | if (!aURI) { | |||
| 2372 | return false; | |||
| 2373 | } | |||
| 2374 | ||||
| 2375 | if (!aURI->SchemeIs("about")) { | |||
| 2376 | return false; | |||
| 2377 | } | |||
| 2378 | ||||
| 2379 | nsAutoCString name; | |||
| 2380 | nsresult rv = NS_GetAboutModuleName(aURI, name); | |||
| 2381 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2381); return false; } } while (false); | |||
| 2382 | ||||
| 2383 | return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") || | |||
| 2384 | name.EqualsLiteral("blocked"); | |||
| 2385 | } | |||
| 2386 | ||||
| 2387 | // static | |||
| 2388 | void nsContentUtils::Shutdown() { | |||
| 2389 | sInitialized = false; | |||
| 2390 | ||||
| 2391 | nsHTMLTags::ReleaseTable(); | |||
| 2392 | ||||
| 2393 | NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)-> Release(); (sContentPolicyService) = 0; } } while (0); | |||
| 2394 | sTriedToGetContentPolicy = false; | |||
| 2395 | for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) { | |||
| 2396 | bundle = nullptr; | |||
| 2397 | } | |||
| 2398 | ||||
| 2399 | NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release (); (sStringBundleService) = 0; } } while (0); | |||
| 2400 | NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); ( sConsoleService) = 0; } } while (0); | |||
| 2401 | NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect ) = 0; } } while (0); | |||
| 2402 | NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release() ; (sSecurityManager) = 0; } } while (0); | |||
| 2403 | NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release() ; (sSystemPrincipal) = 0; } } while (0); | |||
| 2404 | NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)-> Release(); (sNullSubjectPrincipal) = 0; } } while (0); | |||
| 2405 | NS_IF_RELEASE(sFingerprintingProtectionPrincipal)do { if (sFingerprintingProtectionPrincipal) { (sFingerprintingProtectionPrincipal )->Release(); (sFingerprintingProtectionPrincipal) = 0; } } while (0); | |||
| 2406 | ||||
| 2407 | sBidiKeyboard = nullptr; | |||
| 2408 | ||||
| 2409 | delete sAtomEventTable; | |||
| 2410 | sAtomEventTable = nullptr; | |||
| 2411 | delete sStringEventTable; | |||
| 2412 | sStringEventTable = nullptr; | |||
| 2413 | delete sUserDefinedEvents; | |||
| 2414 | sUserDefinedEvents = nullptr; | |||
| 2415 | ||||
| 2416 | // Managers left in the list remove themselves from it when they're deleted, | |||
| 2417 | // which can happen after this point. | |||
| 2418 | NS_ASSERTION(sNodeEventListenerManagers.isEmpty(),do { if (!(sNodeEventListenerManagers.isEmpty())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!" , "sNodeEventListenerManagers.isEmpty()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2419); MOZ_PretendNoReturn(); } } while (0) | |||
| 2419 | "Node event listener manager list not empty at shutdown!")do { if (!(sNodeEventListenerManagers.isEmpty())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!" , "sNodeEventListenerManagers.isEmpty()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2419); MOZ_PretendNoReturn(); } } while (0); | |||
| 2420 | ||||
| 2421 | MOZ_ASSERT_IF(sDOMArenaHashtable, sDOMArenaHashtable->Count() == 0)do { if (sDOMArenaHashtable) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(sDOMArenaHashtable->Count () == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(sDOMArenaHashtable->Count() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sDOMArenaHashtable->Count() == 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2421); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0" ")"); do { MOZ_CrashSequence(__null, 2421); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 2422 | delete sDOMArenaHashtable; | |||
| 2423 | sDOMArenaHashtable = nullptr; | |||
| 2424 | ||||
| 2425 | NS_ASSERTION(!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0,do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners-> Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?" , "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2426); MOZ_PretendNoReturn (); } } while (0) | |||
| 2426 | "How'd this happen?")do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners-> Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?" , "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2426); MOZ_PretendNoReturn (); } } while (0); | |||
| 2427 | delete sBlockedScriptRunners; | |||
| 2428 | sBlockedScriptRunners = nullptr; | |||
| 2429 | ||||
| 2430 | delete sShiftText; | |||
| 2431 | sShiftText = nullptr; | |||
| 2432 | delete sControlText; | |||
| 2433 | sControlText = nullptr; | |||
| 2434 | delete sCommandOrWinText; | |||
| 2435 | sCommandOrWinText = nullptr; | |||
| 2436 | delete sAltText; | |||
| 2437 | sAltText = nullptr; | |||
| 2438 | delete sModifierSeparator; | |||
| 2439 | sModifierSeparator = nullptr; | |||
| 2440 | ||||
| 2441 | delete sJSScriptBytecodeMimeType; | |||
| 2442 | sJSScriptBytecodeMimeType = nullptr; | |||
| 2443 | ||||
| 2444 | delete sJSModuleBytecodeMimeType; | |||
| 2445 | sJSModuleBytecodeMimeType = nullptr; | |||
| 2446 | ||||
| 2447 | NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release (); (sSameOriginChecker) = 0; } } while (0); | |||
| 2448 | ||||
| 2449 | if (sUserInteractionObserver) { | |||
| 2450 | sUserInteractionObserver->Shutdown(); | |||
| 2451 | NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver ) = 0; } while (0); | |||
| 2452 | } | |||
| 2453 | ||||
| 2454 | for (const auto& pref : kRfpPrefs) { | |||
| 2455 | Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref); | |||
| 2456 | } | |||
| 2457 | ||||
| 2458 | TextControlState::Shutdown(); | |||
| 2459 | } | |||
| 2460 | ||||
| 2461 | /** | |||
| 2462 | * Checks whether two nodes come from the same origin. aTrustedNode is | |||
| 2463 | * considered 'safe' in that a user can operate on it. | |||
| 2464 | */ | |||
| 2465 | // static | |||
| 2466 | nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode, | |||
| 2467 | const nsINode* unTrustedNode) { | |||
| 2468 | MOZ_ASSERT(aTrustedNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTrustedNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTrustedNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTrustedNode", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode" ")"); do { MOZ_CrashSequence(__null, 2468); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 2469 | MOZ_ASSERT(unTrustedNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(unTrustedNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(unTrustedNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("unTrustedNode", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2469); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "unTrustedNode" ")"); do { MOZ_CrashSequence (__null, 2469); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 2470 | ||||
| 2471 | /* | |||
| 2472 | * Get hold of each node's principal | |||
| 2473 | */ | |||
| 2474 | ||||
| 2475 | nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal(); | |||
| 2476 | nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal(); | |||
| 2477 | ||||
| 2478 | if (trustedPrincipal == unTrustedPrincipal) { | |||
| 2479 | return NS_OK; | |||
| 2480 | } | |||
| 2481 | ||||
| 2482 | bool equal; | |||
| 2483 | // XXXbz should we actually have a Subsumes() check here instead? Or perhaps | |||
| 2484 | // a separate method for that, with callers using one or the other? | |||
| 2485 | if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal-> Equals(unTrustedPrincipal, &equal))), 0))) || | |||
| 2486 | !equal) { | |||
| 2487 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; | |||
| 2488 | } | |||
| 2489 | ||||
| 2490 | return NS_OK; | |||
| 2491 | } | |||
| 2492 | ||||
| 2493 | // static | |||
| 2494 | bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal, | |||
| 2495 | nsIPrincipal* aPrincipal) { | |||
| 2496 | bool subsumes; | |||
| 2497 | nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes); | |||
| 2498 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2498); return false; } } while (false); | |||
| 2499 | ||||
| 2500 | if (subsumes) { | |||
| 2501 | return true; | |||
| 2502 | } | |||
| 2503 | ||||
| 2504 | // The subject doesn't subsume aPrincipal. Allow access only if the subject | |||
| 2505 | // is chrome. | |||
| 2506 | return IsCallerChrome(); | |||
| 2507 | } | |||
| 2508 | ||||
| 2509 | // static | |||
| 2510 | bool nsContentUtils::CanCallerAccess(const nsINode* aNode) { | |||
| 2511 | nsIPrincipal* subject = SubjectPrincipal(); | |||
| 2512 | if (subject->IsSystemPrincipal()) { | |||
| 2513 | return true; | |||
| 2514 | } | |||
| 2515 | ||||
| 2516 | if (aNode->ChromeOnlyAccess()) { | |||
| 2517 | return false; | |||
| 2518 | } | |||
| 2519 | ||||
| 2520 | return CanCallerAccess(subject, aNode->NodePrincipal()); | |||
| 2521 | } | |||
| 2522 | ||||
| 2523 | // static | |||
| 2524 | bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) { | |||
| 2525 | nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow); | |||
| 2526 | NS_ENSURE_TRUE(scriptObject, false)do { if ((__builtin_expect(!!(!(scriptObject)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptObject" ") failed" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2526); return false; } } while (false); | |||
| 2527 | ||||
| 2528 | return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal()); | |||
| 2529 | } | |||
| 2530 | ||||
| 2531 | // static | |||
| 2532 | bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal, | |||
| 2533 | const nsAtom* aPerm) { | |||
| 2534 | // Chrome gets access by default. | |||
| 2535 | if (aPrincipal.IsSystemPrincipal()) { | |||
| 2536 | return true; | |||
| 2537 | } | |||
| 2538 | ||||
| 2539 | // Otherwise, only allow if caller is an addon with the permission. | |||
| 2540 | return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm); | |||
| 2541 | } | |||
| 2542 | ||||
| 2543 | // static | |||
| 2544 | bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) { | |||
| 2545 | return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm); | |||
| 2546 | } | |||
| 2547 | ||||
| 2548 | // static | |||
| 2549 | nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal( | |||
| 2550 | nsIContent* aContent, const nsAString& aAttrValue, | |||
| 2551 | nsIPrincipal* aSubjectPrincipal) { | |||
| 2552 | nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr; | |||
| 2553 | ||||
| 2554 | // If the subject principal is the same as the content principal, or no | |||
| 2555 | // explicit subject principal was provided, we don't need to do any further | |||
| 2556 | // checks. Just return the content principal. | |||
| 2557 | if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) { | |||
| 2558 | return contentPrin; | |||
| 2559 | } | |||
| 2560 | ||||
| 2561 | // Only use the subject principal if the URL string we are going to end up | |||
| 2562 | // fetching is under the control of that principal, which is never the case | |||
| 2563 | // for relative URLs. | |||
| 2564 | if (aAttrValue.IsEmpty() || | |||
| 2565 | !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) { | |||
| 2566 | return contentPrin; | |||
| 2567 | } | |||
| 2568 | ||||
| 2569 | // Only use the subject principal as the attr triggering principal if it | |||
| 2570 | // should override the CSP of the node's principal. | |||
| 2571 | if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) { | |||
| 2572 | return aSubjectPrincipal; | |||
| 2573 | } | |||
| 2574 | ||||
| 2575 | return contentPrin; | |||
| 2576 | } | |||
| 2577 | ||||
| 2578 | // static | |||
| 2579 | bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource, | |||
| 2580 | mozilla::dom::BrowsingContext* aTarget, | |||
| 2581 | nsIPrincipal* aDocumentPrincipal, | |||
| 2582 | bool aConsiderOpener) { | |||
| 2583 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSource->Group() == aTarget->Group())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aSource->Group() == aTarget->Group()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()" " (" "Source and target BrowsingContexts must be in the same group" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2585 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()" ") (" "Source and target BrowsingContexts must be in the same group" ")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 2584 | aSource->Group() == aTarget->Group(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSource->Group() == aTarget->Group())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aSource->Group() == aTarget->Group()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()" " (" "Source and target BrowsingContexts must be in the same group" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2585 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()" ") (" "Source and target BrowsingContexts must be in the same group" ")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 2585 | "Source and target BrowsingContexts must be in the same group")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSource->Group() == aTarget->Group())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aSource->Group() == aTarget->Group()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()" " (" "Source and target BrowsingContexts must be in the same group" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2585 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()" ") (" "Source and target BrowsingContexts must be in the same group" ")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 2586 | if (aSource->Group() != aTarget->Group()) { | |||
| 2587 | return false; | |||
| 2588 | } | |||
| 2589 | ||||
| 2590 | auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool { | |||
| 2591 | // NOTE: This code previously checked for a file scheme using | |||
| 2592 | // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer | |||
| 2593 | // use GetURI, as it has been deprecated, and it makes more sense to take | |||
| 2594 | // advantage of the pre-computed origin, which will already use the | |||
| 2595 | // innermost URI (bug 1810619) | |||
| 2596 | nsAutoCString origin, scheme; | |||
| 2597 | return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetOriginNoSuffix (origin))), 1))) && | |||
| 2598 | NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(net_ExtractURLScheme (origin, scheme))), 1))) && | |||
| 2599 | scheme == "file"_ns; | |||
| 2600 | }; | |||
| 2601 | ||||
| 2602 | // A frame can navigate itself and its own root. | |||
| 2603 | if (aTarget == aSource || aTarget == aSource->Top()) { | |||
| 2604 | return true; | |||
| 2605 | } | |||
| 2606 | ||||
| 2607 | // If the target frame doesn't yet have a WindowContext, start checking | |||
| 2608 | // principals from its direct ancestor instead. It would inherit its principal | |||
| 2609 | // from this document upon creation. | |||
| 2610 | dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext(); | |||
| 2611 | if (!initialWc) { | |||
| 2612 | initialWc = aTarget->GetParentWindowContext(); | |||
| 2613 | } | |||
| 2614 | ||||
| 2615 | // A frame can navigate any frame with a same-origin ancestor. | |||
| 2616 | bool isFileDocument = isFileScheme(aDocumentPrincipal); | |||
| 2617 | for (dom::WindowContext* wc = initialWc; wc; | |||
| 2618 | wc = wc->GetParentWindowContext()) { | |||
| 2619 | nsIPrincipal* documentPrincipal = nullptr; | |||
| 2620 | if (XRE_IsParentProcess()) { | |||
| 2621 | dom::WindowGlobalParent* wgp = wc->Canonical(); | |||
| 2622 | if (!wgp) { | |||
| 2623 | continue; | |||
| 2624 | } | |||
| 2625 | documentPrincipal = wgp->DocumentPrincipal(); | |||
| 2626 | } else { | |||
| 2627 | dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild(); | |||
| 2628 | if (!wgc) { | |||
| 2629 | continue; // not same-origin. | |||
| 2630 | } | |||
| 2631 | documentPrincipal = wgc->DocumentPrincipal(); | |||
| 2632 | } | |||
| 2633 | ||||
| 2634 | if (aDocumentPrincipal->Equals(documentPrincipal)) { | |||
| 2635 | return true; | |||
| 2636 | } | |||
| 2637 | ||||
| 2638 | // Not strictly equal, special case if both are file: URIs. | |||
| 2639 | // | |||
| 2640 | // file: URIs are considered the same domain for the purpose of frame | |||
| 2641 | // navigation, regardless of script accessibility (bug 420425). | |||
| 2642 | if (isFileDocument && isFileScheme(documentPrincipal)) { | |||
| 2643 | return true; | |||
| 2644 | } | |||
| 2645 | } | |||
| 2646 | ||||
| 2647 | // If the target is a top-level document, a frame can navigate it | |||
| 2648 | // when the source is allowed to navigate the opener | |||
| 2649 | if (aConsiderOpener && !aTarget->GetParent()) { | |||
| 2650 | if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) { | |||
| 2651 | return CanNavigate(aSource, opener, aDocumentPrincipal, false); | |||
| 2652 | } | |||
| 2653 | } | |||
| 2654 | ||||
| 2655 | return false; | |||
| 2656 | } | |||
| 2657 | ||||
| 2658 | // static | |||
| 2659 | bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) { | |||
| 2660 | nsAutoCString scheme; | |||
| 2661 | if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme (aURL, scheme))), 0)))) { | |||
| 2662 | // If we can't extract a scheme, it's not an absolute URL. | |||
| 2663 | return false; | |||
| 2664 | } | |||
| 2665 | ||||
| 2666 | // If it parses as an absolute StandardURL, it's definitely an absolute URL, | |||
| 2667 | // so no need to check with the IO service. | |||
| 2668 | if (net_IsAbsoluteURL(aURL)) { | |||
| 2669 | return true; | |||
| 2670 | } | |||
| 2671 | ||||
| 2672 | nsresult rv = NS_OK; | |||
| 2673 | nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv); | |||
| 2674 | MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2674); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { MOZ_CrashSequence(__null, 2674); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 2675 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 2676 | return false; | |||
| 2677 | } | |||
| 2678 | ||||
| 2679 | uint32_t flags; | |||
| 2680 | if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags (scheme.get(), &flags))), 1)))) { | |||
| 2681 | return flags & nsIProtocolHandler::URI_NORELATIVE; | |||
| 2682 | } | |||
| 2683 | ||||
| 2684 | return false; | |||
| 2685 | } | |||
| 2686 | ||||
| 2687 | // static | |||
| 2688 | bool nsContentUtils::InProlog(nsINode* aNode) { | |||
| 2689 | MOZ_ASSERT(aNode, "missing node to nsContentUtils::InProlog")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aNode))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("aNode" " (" "missing node to nsContentUtils::InProlog" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2689 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "missing node to nsContentUtils::InProlog" ")"); do { MOZ_CrashSequence(__null, 2689); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 2690 | ||||
| 2691 | nsINode* parent = aNode->GetParentNode(); | |||
| 2692 | if (!parent || !parent->IsDocument()) { | |||
| 2693 | return false; | |||
| 2694 | } | |||
| 2695 | ||||
| 2696 | const Document* doc = parent->AsDocument(); | |||
| 2697 | const nsIContent* root = doc->GetRootElement(); | |||
| 2698 | if (!root) { | |||
| 2699 | return true; | |||
| 2700 | } | |||
| 2701 | const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode); | |||
| 2702 | const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root); | |||
| 2703 | if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot .isSome()), 1))) { | |||
| 2704 | return *indexOfNode < *indexOfRoot; | |||
| 2705 | } | |||
| 2706 | // XXX Keep the odd traditional behavior for now. | |||
| 2707 | return indexOfNode.isNothing() && indexOfRoot.isSome(); | |||
| 2708 | } | |||
| 2709 | ||||
| 2710 | bool nsContentUtils::IsCallerChrome() { | |||
| 2711 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2711); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 2711); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 2712 | return SubjectPrincipal() == sSystemPrincipal; | |||
| 2713 | } | |||
| 2714 | ||||
| 2715 | #ifdef FUZZING | |||
| 2716 | bool nsContentUtils::IsFuzzingEnabled() { | |||
| 2717 | return StaticPrefs::fuzzing_enabled(); | |||
| 2718 | } | |||
| 2719 | #endif | |||
| 2720 | ||||
| 2721 | /* static */ | |||
| 2722 | bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled( | |||
| 2723 | JSContext* aCx, JSObject*) { | |||
| 2724 | return ThreadsafeIsSystemCaller(aCx) || | |||
| 2725 | StaticPrefs::dom_element_transform_getters_enabled(); | |||
| 2726 | } | |||
| 2727 | ||||
| 2728 | // Older Should RFP Functions ---------------------------------- | |||
| 2729 | ||||
| 2730 | /* static */ | |||
| 2731 | bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode, | |||
| 2732 | RFPTarget aTarget) { | |||
| 2733 | return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing()); | |||
| 2734 | } | |||
| 2735 | ||||
| 2736 | /* static */ | |||
| 2737 | bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject, | |||
| 2738 | RFPTarget aTarget) { | |||
| 2739 | if (!aGlobalObject) { | |||
| 2740 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
| 2741 | } | |||
| 2742 | return aGlobalObject->ShouldResistFingerprinting(aTarget); | |||
| 2743 | } | |||
| 2744 | ||||
| 2745 | // Newer Should RFP Functions ---------------------------------- | |||
| 2746 | // Utilities --------------------------------------------------- | |||
| 2747 | ||||
| 2748 | inline void LogDomainAndList(const char* urlType, nsAutoCString& list, | |||
| 2749 | nsAutoCString& url, bool isExemptDomain) { | |||
| 2750 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString <char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString <char>(list).get()); } } while (0) | |||
| 2751 | ("%s \"%s\" is %s the exempt list \"%s\"", urlType,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString <char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString <char>(list).get()); } } while (0) | |||
| 2752 | PromiseFlatCString(url).get(), isExemptDomain ? "in" : "NOT in",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString <char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString <char>(list).get()); } } while (0) | |||
| 2753 | PromiseFlatCString(list).get()))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString <char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString <char>(list).get()); } } while (0); | |||
| 2754 | } | |||
| 2755 | ||||
| 2756 | inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings( | |||
| 2757 | nsILoadInfo* aLoadInfo) { | |||
| 2758 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings; | |||
| 2759 | nsresult rv = | |||
| 2760 | aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); | |||
| 2761 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { | |||
| 2762 | // The TRRLoadInfo in particular does not implement this method | |||
| 2763 | // In that instance. We will return false and let other code decide if | |||
| 2764 | // we shouldRFP for this connection | |||
| 2765 | return nullptr; | |||
| 2766 | } | |||
| 2767 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 2767)) { | |||
| 2768 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the " "loadinfo's CookieJarSettings couldn't be retrieved"); } } while (0) | |||
| 2769 | ("Called CookieJarSettingsSaysShouldResistFingerprinting but the "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the " "loadinfo's CookieJarSettings couldn't be retrieved"); } } while (0) | |||
| 2770 | "loadinfo's CookieJarSettings couldn't be retrieved"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the " "loadinfo's CookieJarSettings couldn't be retrieved"); } } while (0); | |||
| 2771 | return nullptr; | |||
| 2772 | } | |||
| 2773 | ||||
| 2774 | MOZ_ASSERT(cookieJarSettings)do { static_assert( mozilla::detail::AssertionConditionType< decltype(cookieJarSettings)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(cookieJarSettings))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cookieJarSettings" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2774); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "cookieJarSettings" ")"); do { MOZ_CrashSequence (__null, 2774); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 2775 | return cookieJarSettings.forget(); | |||
| 2776 | } | |||
| 2777 | ||||
| 2778 | bool nsContentUtils::ETPSaysShouldNotResistFingerprinting( | |||
| 2779 | nsICookieJarSettings* aCookieJarSettings, bool aIsPBM) { | |||
| 2780 | // A positive return from this function should always be obeyed. | |||
| 2781 | // A negative return means we should keep checking things. | |||
| 2782 | ||||
| 2783 | // We do not want this check to apply to RFP, only to FPP. | |||
| 2784 | if (nsRFPService::IsRFPPrefEnabled(aIsPBM)) { | |||
| 2785 | // In RFP, never use the ETP toggle to exempt. | |||
| 2786 | // We can safely return false here even if we are not in PBM mode | |||
| 2787 | // and RFP_pbmode is enabled because we will later see that and | |||
| 2788 | // return false from the ShouldRFP function entirely. | |||
| 2789 | return false; | |||
| 2790 | } | |||
| 2791 | ||||
| 2792 | return ContentBlockingAllowList::Check(aCookieJarSettings); | |||
| 2793 | } | |||
| 2794 | ||||
| 2795 | bool nsContentUtils::ETPSaysShouldNotResistFingerprinting( | |||
| 2796 | nsIChannel* aChannel, nsILoadInfo* aLoadInfo) { | |||
| 2797 | bool isPBM = NS_UsePrivateBrowsing(aChannel); | |||
| 2798 | ||||
| 2799 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
| 2800 | GetCookieJarSettings(aLoadInfo); | |||
| 2801 | if (!cookieJarSettings) { | |||
| 2802 | return false; | |||
| 2803 | } | |||
| 2804 | ||||
| 2805 | return ETPSaysShouldNotResistFingerprinting(cookieJarSettings, isPBM); | |||
| 2806 | } | |||
| 2807 | ||||
| 2808 | inline bool CookieJarSettingsSaysShouldResistFingerprinting( | |||
| 2809 | nsILoadInfo* aLoadInfo) { | |||
| 2810 | // A positive return from this function should always be obeyed. | |||
| 2811 | // A negative return means we should keep checking things. | |||
| 2812 | ||||
| 2813 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
| 2814 | GetCookieJarSettings(aLoadInfo); | |||
| 2815 | if (!cookieJarSettings) { | |||
| 2816 | return false; | |||
| 2817 | } | |||
| 2818 | return cookieJarSettings->GetShouldResistFingerprinting(); | |||
| 2819 | } | |||
| 2820 | ||||
| 2821 | inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) { | |||
| 2822 | return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") || | |||
| 2823 | aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") || | |||
| 2824 | (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI)); | |||
| 2825 | } | |||
| 2826 | ||||
| 2827 | inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) { | |||
| 2828 | if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") || | |||
| 2829 | aPrincipal->SchemeIs("view-source") || | |||
| 2830 | aPrincipal->SchemeIs("moz-extension")) { | |||
| 2831 | return true; | |||
| 2832 | } | |||
| 2833 | ||||
| 2834 | if (!aPrincipal->SchemeIs("about")) { | |||
| 2835 | return false; | |||
| 2836 | } | |||
| 2837 | ||||
| 2838 | bool isContentAccessibleAboutURI; | |||
| 2839 | (void)aPrincipal->IsContentAccessibleAboutURI(&isContentAccessibleAboutURI); | |||
| 2840 | return !isContentAccessibleAboutURI; | |||
| 2841 | } | |||
| 2842 | ||||
| 2843 | // mFirstPartyDomain and mPartitionKey are serialized either as a bare host | |||
| 2844 | // ("example.com") or in site format ("(https,example.com[,port][,f])"), | |||
| 2845 | // depending on privacy.firstparty.isolate.use_site and | |||
| 2846 | // privacy.dynamic_firstparty.use_site respectively. Those two prefs are | |||
| 2847 | // independent, and ParsePartitionKey() only consults the latter, so detect the | |||
| 2848 | // format here instead of letting it decide for a first-party domain. | |||
| 2849 | inline void TopLevelInfoToBaseDomain(const nsAString& aInfo, | |||
| 2850 | nsAString& aBaseDomain) { | |||
| 2851 | if (aInfo.IsEmpty() || aInfo.First() != '(') { | |||
| 2852 | aBaseDomain = aInfo; | |||
| 2853 | return; | |||
| 2854 | } | |||
| 2855 | ||||
| 2856 | nsAutoString scheme; | |||
| 2857 | int32_t port; | |||
| 2858 | bool foreignByAncestorContext; | |||
| 2859 | if (!OriginAttributes::ParsePartitionKey(aInfo, scheme, aBaseDomain, port, | |||
| 2860 | foreignByAncestorContext)) { | |||
| 2861 | aBaseDomain.Truncate(); | |||
| 2862 | } | |||
| 2863 | } | |||
| 2864 | ||||
| 2865 | inline bool PartionKeyIsAlsoExempted( | |||
| 2866 | const mozilla::OriginAttributes& aOriginAttributes) { | |||
| 2867 | // If we've gotten here we have (probably) passed the CookieJarSettings | |||
| 2868 | // check that would tell us that if we _are_ a subdocument, then we are on | |||
| 2869 | // an exempted top-level domain and we should see if we ourselves are | |||
| 2870 | // exempted. But we may have gotten here because we directly called the | |||
| 2871 | // _dangerous function and we haven't done that check, but we _were_ | |||
| 2872 | // instatiated from a state where we could have been partitioned. | |||
| 2873 | // So perform this last-ditch check for that scenario. | |||
| 2874 | // We arbitrarily use https as the scheme, but it doesn't matter. | |||
| 2875 | nsAutoString baseDomain; | |||
| 2876 | if (StaticPrefs::privacy_firstparty_isolate() && | |||
| 2877 | !aOriginAttributes.mFirstPartyDomain.IsEmpty()) { | |||
| 2878 | TopLevelInfoToBaseDomain(aOriginAttributes.mFirstPartyDomain, baseDomain); | |||
| 2879 | } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) { | |||
| 2880 | TopLevelInfoToBaseDomain(aOriginAttributes.mPartitionKey, baseDomain); | |||
| 2881 | } | |||
| 2882 | ||||
| 2883 | nsresult rv = NS_ERROR_NOT_INITIALIZED; | |||
| 2884 | nsCOMPtr<nsIURI> uri; | |||
| 2885 | if (!baseDomain.IsEmpty()) { | |||
| 2886 | rv = NS_NewURI(getter_AddRefs(uri), u"https://"_ns + baseDomain); | |||
| 2887 | } | |||
| 2888 | ||||
| 2889 | if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 2890 | nsAutoCString list; | |||
| 2891 | nsRFPService::GetExemptedDomainsLowercase(list); | |||
| 2892 | bool isExemptPartitionKey = nsContentUtils::IsURIInList(uri, list); | |||
| 2893 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
| 2894 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
| 2895 | nsAutoCString url; | |||
| 2896 | uri->GetHost(url); | |||
| 2897 | LogDomainAndList("Partition Key", list, url, isExemptPartitionKey); | |||
| 2898 | } | |||
| 2899 | return isExemptPartitionKey; | |||
| 2900 | } | |||
| 2901 | return true; | |||
| 2902 | } | |||
| 2903 | ||||
| 2904 | // Functions --------------------------------------------------- | |||
| 2905 | ||||
| 2906 | /* static */ | |||
| 2907 | bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification, | |||
| 2908 | RFPTarget aTarget) { | |||
| 2909 | // See comment in header file for information about usage | |||
| 2910 | // We hardcode PBM to true to be the more restrictive option. | |||
| 2911 | return nsContentUtils::ShouldResistFingerprinting(true, aTarget); | |||
| 2912 | } | |||
| 2913 | ||||
| 2914 | namespace { | |||
| 2915 | ||||
| 2916 | // This function is only called within this file for Positive Return Checks | |||
| 2917 | bool ShouldResistFingerprinting_(const char* aJustification, | |||
| 2918 | bool aIsPrivateMode, RFPTarget aTarget) { | |||
| 2919 | // See comment in header file for information about usage | |||
| 2920 | return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget); | |||
| 2921 | } | |||
| 2922 | ||||
| 2923 | } // namespace | |||
| 2924 | ||||
| 2925 | /* static */ | |||
| 2926 | bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType, | |||
| 2927 | nsIGlobalObject* aGlobalObject, | |||
| 2928 | RFPTarget aTarget) { | |||
| 2929 | if (aCallerType == CallerType::System) { | |||
| 2930 | return false; | |||
| 2931 | } | |||
| 2932 | return ShouldResistFingerprinting(aGlobalObject, aTarget); | |||
| 2933 | } | |||
| 2934 | ||||
| 2935 | /* static */ | |||
| 2936 | bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell, | |||
| 2937 | RFPTarget aTarget) { | |||
| 2938 | if (!aDocShell) { | |||
| 2939 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) " "with NULL docshell"); } } while (0) | |||
| 2940 | ("Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) " "with NULL docshell"); } } while (0) | |||
| 2941 | "with NULL docshell"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) " "with NULL docshell"); } } while (0); | |||
| 2942 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
| 2943 | } | |||
| 2944 | return ShouldResistFingerprinting(aDocShell->GetDocument(), aTarget); | |||
| 2945 | } | |||
| 2946 | ||||
| 2947 | /* static */ | |||
| 2948 | bool nsContentUtils::ShouldResistFingerprinting(const Document* aDocument, | |||
| 2949 | RFPTarget aTarget) { | |||
| 2950 | if (!aDocument) { | |||
| 2951 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) " "with NULL document"); } } while (0) | |||
| 2952 | nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) " "with NULL document"); } } while (0) | |||
| 2953 | ("Called nsContentUtils::ShouldResistFingerprinting(const Document*) "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) " "with NULL document"); } } while (0) | |||
| 2954 | "with NULL document"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) " "with NULL document"); } } while (0); | |||
| 2955 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
| 2956 | } | |||
| 2957 | return aDocument->ShouldResistFingerprinting(aTarget); | |||
| 2958 | } | |||
| 2959 | ||||
| 2960 | /* static */ | |||
| 2961 | bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel, | |||
| 2962 | RFPTarget aTarget) { | |||
| 2963 | if (!aChannel) { | |||
| 2964 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) with NULL channel"); } } while (0) | |||
| 2965 | ("Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) with NULL channel"); } } while (0) | |||
| 2966 | "aChannel) with NULL channel"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) with NULL channel"); } } while (0); | |||
| 2967 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
| 2968 | } | |||
| 2969 | ||||
| 2970 | bool isPBM = NS_UsePrivateBrowsing(aChannel); | |||
| 2971 | ||||
| 2972 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
| 2973 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
| 2974 | nsCOMPtr<nsIURI> channelURI; | |||
| 2975 | (void)NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
| 2976 | nsAutoCString channelSpec; | |||
| 2977 | channelURI->GetSpec(channelSpec); | |||
| 2978 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)" , channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 2979 | ("Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)" , channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 2980 | channelSpec.get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)" , channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0); | |||
| 2981 | } | |||
| 2982 | ||||
| 2983 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
| 2984 | if (!loadInfo) { | |||
| 2985 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) but the channel's loadinfo was NULL"); } } while ( 0) | |||
| 2986 | ("Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) but the channel's loadinfo was NULL"); } } while ( 0) | |||
| 2987 | "aChannel) but the channel's loadinfo was NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* " "aChannel) but the channel's loadinfo was NULL"); } } while ( 0); | |||
| 2988 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
| 2989 | } | |||
| 2990 | ||||
| 2991 | // With this check, we can ensure that the prefs and target say yes, so only | |||
| 2992 | // an exemption would cause us to return false. | |||
| 2993 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
| 2994 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 2995 | ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 2996 | " Positive return check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 2997 | isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0); | |||
| 2998 | return false; | |||
| 2999 | } | |||
| 3000 | ||||
| 3001 | auto contentType = loadInfo->GetExternalContentPolicyType(); | |||
| 3002 | ||||
| 3003 | if (sSecurityManager && (contentType == ExtContentPolicy::TYPE_DOCUMENT || | |||
| 3004 | contentType == ExtContentPolicy::TYPE_SUBDOCUMENT)) { | |||
| 3005 | nsCOMPtr<nsIPrincipal> resultPrincipal; | |||
| 3006 | nsresult rv = sSecurityManager->GetChannelResultPrincipal( | |||
| 3007 | aChannel, getter_AddRefs(resultPrincipal)); | |||
| 3008 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && IsPDFJS(resultPrincipal)) { | |||
| 3009 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted" ); } } while (0) | |||
| 3010 | ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted" ); } } while (0) | |||
| 3011 | " PDF.js document exempted"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted" ); } } while (0); | |||
| 3012 | return false; | |||
| 3013 | } | |||
| 3014 | } | |||
| 3015 | ||||
| 3016 | if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) { | |||
| 3017 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3018 | ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3019 | " ETPSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false" ); } } while (0); | |||
| 3020 | return false; | |||
| 3021 | } | |||
| 3022 | ||||
| 3023 | if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) { | |||
| 3024 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true" ); } } while (0) | |||
| 3025 | ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true" ); } } while (0) | |||
| 3026 | " CookieJarSettingsSaysShouldResistFingerprinting said true"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true" ); } } while (0); | |||
| 3027 | return true; | |||
| 3028 | } | |||
| 3029 | ||||
| 3030 | // Document types have no loading principal. Subdocument types do have a | |||
| 3031 | // loading principal, but it is the loading principal of the parent | |||
| 3032 | // document; not the subdocument. | |||
| 3033 | // Case 1: Document or Subdocument load | |||
| 3034 | if (contentType == ExtContentPolicy::TYPE_DOCUMENT || | |||
| 3035 | contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) { | |||
| 3036 | nsCOMPtr<nsIURI> channelURI; | |||
| 3037 | nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
| 3038 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3041 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 3039 | NS_SUCCEEDED(rv),do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3041 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 3040 | "Failed to get URI in "do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3041 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 3041 | "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3041 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3042 | // this check is to ensure that we do not crash in non-debug builds. | |||
| 3043 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 3044 | return true; | |||
| 3045 | } | |||
| 3046 | ||||
| 3047 | nsAutoCString loadingPrincipalSpec; | |||
| 3048 | nsAutoCString channelSpec; | |||
| 3049 | channelURI->GetSpec(channelSpec); | |||
| 3050 | ||||
| 3051 | if (contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) { | |||
| 3052 | MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3053 | nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3054 | ("Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3055 | channelSpec.get(),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3056 | loadInfo->GetLoadingPrincipal()do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3057 | ? loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3058 | loadingPrincipalSpec.get() : "is NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0); | |||
| 3059 | } else { | |||
| 3060 | MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3061 | nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3062 | ("Document Type. FinalChannelURI is %s, Loading Principal %s\n",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3063 | channelSpec.get(),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3064 | loadInfo->GetLoadingPrincipal()do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3065 | ? loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0) | |||
| 3066 | loadingPrincipalSpec.get() : "is NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n" , channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo ->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec ), loadingPrincipalSpec.get() : "is NULL"); } } while (0); | |||
| 3067 | } | |||
| 3068 | ||||
| 3069 | return ShouldResistFingerprinting_dangerous( | |||
| 3070 | channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget); | |||
| 3071 | } | |||
| 3072 | ||||
| 3073 | // Case 2: Subresource Load | |||
| 3074 | // Because this code is only used for subresource loads, this | |||
| 3075 | // will check the parent's principal | |||
| 3076 | nsIPrincipal* principal = loadInfo->GetLoadingPrincipal(); | |||
| 3077 | ||||
| 3078 | MOZ_ASSERT_IF(principal && !principal->IsSystemPrincipal() &&do { if (principal && !principal->IsSystemPrincipal () && !principal->GetIsAddonOrExpandedAddonPrincipal ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(BasePrincipal::Cast(principal)->OriginAttributesRef () == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal )->OriginAttributesRef() == loadInfo->GetOriginAttributes ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3081); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3079 | !principal->GetIsAddonOrExpandedAddonPrincipal(),do { if (principal && !principal->IsSystemPrincipal () && !principal->GetIsAddonOrExpandedAddonPrincipal ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(BasePrincipal::Cast(principal)->OriginAttributesRef () == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal )->OriginAttributesRef() == loadInfo->GetOriginAttributes ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3081); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3080 | BasePrincipal::Cast(principal)->OriginAttributesRef() ==do { if (principal && !principal->IsSystemPrincipal () && !principal->GetIsAddonOrExpandedAddonPrincipal ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(BasePrincipal::Cast(principal)->OriginAttributesRef () == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal )->OriginAttributesRef() == loadInfo->GetOriginAttributes ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3081); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3081 | loadInfo->GetOriginAttributes())do { if (principal && !principal->IsSystemPrincipal () && !principal->GetIsAddonOrExpandedAddonPrincipal ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(BasePrincipal::Cast(principal)->OriginAttributesRef () == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal )->OriginAttributesRef() == loadInfo->GetOriginAttributes ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3081); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3082 | return ShouldResistFingerprinting_dangerous(principal, "Internal Call", | |||
| 3083 | aTarget); | |||
| 3084 | } | |||
| 3085 | ||||
| 3086 | /* static */ | |||
| 3087 | bool nsContentUtils::ShouldResistFingerprinting_dangerous( | |||
| 3088 | nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes, | |||
| 3089 | const char* aJustification, RFPTarget aTarget) { | |||
| 3090 | // With this check, we can ensure that the prefs and target say yes, so only | |||
| 3091 | // an exemption would cause us to return false. | |||
| 3092 | bool isPBM = aOriginAttributes.IsPrivateBrowsing(); | |||
| 3093 | ||||
| 3094 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)" , aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3095 | ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)" , aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3096 | " OriginAttributes) and the URI is %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)" , aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3097 | aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)" , aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); } } while (0); | |||
| 3098 | ||||
| 3099 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
| 3100 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 3101 | ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 3102 | " OriginAttributes) Positive return check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0) | |||
| 3103 | isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)" , isPBM ? "Yes" : "No"); } } while (0); | |||
| 3104 | return false; | |||
| 3105 | } | |||
| 3106 | ||||
| 3107 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s" , aURI->GetSpecOrDefault().get()); } } while (0) | |||
| 3108 | ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s" , aURI->GetSpecOrDefault().get()); } } while (0) | |||
| 3109 | " OriginAttributes) and the URI is %s",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s" , aURI->GetSpecOrDefault().get()); } } while (0) | |||
| 3110 | aURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s" , aURI->GetSpecOrDefault().get()); } } while (0); | |||
| 3111 | ||||
| 3112 | // Exclude internal schemes and web extensions | |||
| 3113 | if (SchemeSaysShouldNotResistFingerprinting(aURI)) { | |||
| 3114 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3115 | ("Inside ShouldResistFingerprinting(nsIURI*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3116 | " SchemeSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0); | |||
| 3117 | return false; | |||
| 3118 | } | |||
| 3119 | ||||
| 3120 | bool isExemptDomain = false; | |||
| 3121 | nsAutoCString list; | |||
| 3122 | nsRFPService::GetExemptedDomainsLowercase(list); | |||
| 3123 | isExemptDomain = IsURIInList(aURI, list); | |||
| 3124 | ||||
| 3125 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
| 3126 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
| 3127 | nsAutoCString url; | |||
| 3128 | aURI->GetHost(url); | |||
| 3129 | LogDomainAndList("URI", list, url, isExemptDomain); | |||
| 3130 | } | |||
| 3131 | ||||
| 3132 | if (isExemptDomain) { | |||
| 3133 | isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes); | |||
| 3134 | } | |||
| 3135 | ||||
| 3136 | return !isExemptDomain; | |||
| 3137 | } | |||
| 3138 | ||||
| 3139 | /* static */ | |||
| 3140 | bool nsContentUtils::ShouldResistFingerprinting_dangerous( | |||
| 3141 | nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) { | |||
| 3142 | if (!aPrincipal) { | |||
| 3143 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* " "aChannel) but the loadinfo's loadingprincipal was NULL"); } } while (0) | |||
| 3144 | ("Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* " "aChannel) but the loadinfo's loadingprincipal was NULL"); } } while (0) | |||
| 3145 | "aChannel) but the loadinfo's loadingprincipal was NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla ::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* " "aChannel) but the loadinfo's loadingprincipal was NULL"); } } while (0); | |||
| 3146 | return ShouldResistFingerprinting("Null object", aTarget); | |||
| 3147 | } | |||
| 3148 | ||||
| 3149 | const auto& originAttributes = | |||
| 3150 | BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(); | |||
| 3151 | // With this check, we can ensure that the prefs and target say yes, so only | |||
| 3152 | // an exemption would cause us to return false. | |||
| 3153 | bool isPBM = originAttributes.IsPrivateBrowsing(); | |||
| 3154 | ||||
| 3155 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
| 3156 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
| 3157 | nsAutoCString origin; | |||
| 3158 | aPrincipal->GetOrigin(origin); | |||
| 3159 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)" , origin.get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3160 | nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)" , origin.get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3161 | ("Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)" , origin.get(), isPBM ? "Yes" : "No"); } } while (0) | |||
| 3162 | origin.get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)" , origin.get(), isPBM ? "Yes" : "No"); } } while (0); | |||
| 3163 | } | |||
| 3164 | ||||
| 3165 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
| 3166 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return " "check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while (0) | |||
| 3167 | ("Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return " "check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while (0) | |||
| 3168 | "check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return " "check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while (0) | |||
| 3169 | isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return " "check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while (0); | |||
| 3170 | return false; | |||
| 3171 | } | |||
| 3172 | ||||
| 3173 | if (aPrincipal->IsSystemPrincipal()) { | |||
| 3174 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false" ); } } while (0) | |||
| 3175 | ("Inside ShouldResistFingerprinting(nsIPrincipal*) System "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false" ); } } while (0) | |||
| 3176 | "Principal said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false" ); } } while (0); | |||
| 3177 | return false; | |||
| 3178 | } | |||
| 3179 | ||||
| 3180 | // Exclude internal schemes and web extensions | |||
| 3181 | if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) { | |||
| 3182 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3183 | ("Inside ShouldResistFingerprinting(nsIPrincipal*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0) | |||
| 3184 | " SchemeSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false" ); } } while (0); | |||
| 3185 | return false; | |||
| 3186 | } | |||
| 3187 | ||||
| 3188 | // Web extension principals are also excluded | |||
| 3189 | if (BasePrincipal::Cast(aPrincipal)->AddonPolicyCore()) { | |||
| 3190 | MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false" ); } } while (0) | |||
| 3191 | ("Inside ShouldResistFingerprinting(nsIPrincipal*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false" ); } } while (0) | |||
| 3192 | " and AddonPolicy said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla ::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module, LogLevel::Debug, "Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false" ); } } while (0); | |||
| 3193 | return false; | |||
| 3194 | } | |||
| 3195 | ||||
| 3196 | bool isExemptDomain = false; | |||
| 3197 | nsAutoCString list; | |||
| 3198 | nsRFPService::GetExemptedDomainsLowercase(list); | |||
| 3199 | aPrincipal->IsURIInList(list, &isExemptDomain); | |||
| 3200 | ||||
| 3201 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
| 3202 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
| 3203 | nsAutoCString origin; | |||
| 3204 | aPrincipal->GetOrigin(origin); | |||
| 3205 | LogDomainAndList("URI", list, origin, isExemptDomain); | |||
| 3206 | } | |||
| 3207 | ||||
| 3208 | if (isExemptDomain) { | |||
| 3209 | isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes); | |||
| 3210 | } | |||
| 3211 | ||||
| 3212 | return !isExemptDomain; | |||
| 3213 | } | |||
| 3214 | ||||
| 3215 | // -------------------------------------------------------------------- | |||
| 3216 | ||||
| 3217 | /* static */ | |||
| 3218 | void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting( | |||
| 3219 | int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth, | |||
| 3220 | int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight, | |||
| 3221 | bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth, | |||
| 3222 | int32_t* aOutputHeight) { | |||
| 3223 | MOZ_ASSERT(aOutputWidth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOutputWidth)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOutputWidth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aOutputWidth", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth" ")"); do { MOZ_CrashSequence(__null, 3223); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3224 | MOZ_ASSERT(aOutputHeight)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOutputHeight)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOutputHeight))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aOutputHeight", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3224); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aOutputHeight" ")"); do { MOZ_CrashSequence (__null, 3224); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3225 | ||||
| 3226 | int32_t availContentWidth = 0; | |||
| 3227 | int32_t availContentHeight = 0; | |||
| 3228 | ||||
| 3229 | availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(), | |||
| 3230 | aScreenWidth - aChromeWidth); | |||
| 3231 | #ifdef MOZ_WIDGET_GTK1 | |||
| 3232 | // In the GTK window, it will not report outside system decorations | |||
| 3233 | // when we get available window size, see Bug 581863. So, we leave a | |||
| 3234 | // 40 pixels space for them when calculating the available content | |||
| 3235 | // height. It is not necessary for the width since the content width | |||
| 3236 | // is usually pretty much the same as the chrome width. | |||
| 3237 | availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(), | |||
| 3238 | (-40 + aScreenHeight) - aChromeHeight); | |||
| 3239 | #else | |||
| 3240 | availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(), | |||
| 3241 | aScreenHeight - aChromeHeight); | |||
| 3242 | #endif | |||
| 3243 | ||||
| 3244 | // Ideally, we'd like to round window size to 1000x1000, but the | |||
| 3245 | // screen space could be too small to accommodate this size in some | |||
| 3246 | // cases. If it happens, we would round the window size to the nearest | |||
| 3247 | // 200x100. | |||
| 3248 | availContentWidth = availContentWidth - (availContentWidth % 200); | |||
| 3249 | availContentHeight = availContentHeight - (availContentHeight % 100); | |||
| 3250 | ||||
| 3251 | // If aIsOuter is true, we are setting the outer window. So we | |||
| 3252 | // have to consider the chrome UI. | |||
| 3253 | int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0; | |||
| 3254 | int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0; | |||
| 3255 | int32_t resultWidth = 0, resultHeight = 0; | |||
| 3256 | ||||
| 3257 | // if the original size is greater than the maximum available size, we set | |||
| 3258 | // it to the maximum size. And if the original value is less than the | |||
| 3259 | // minimum rounded size, we set it to the minimum 200x100. | |||
| 3260 | if (aInputWidth > (availContentWidth + chromeOffsetWidth)) { | |||
| 3261 | resultWidth = availContentWidth + chromeOffsetWidth; | |||
| 3262 | } else if (aInputWidth < (200 + chromeOffsetWidth)) { | |||
| 3263 | resultWidth = 200 + chromeOffsetWidth; | |||
| 3264 | } else { | |||
| 3265 | // Otherwise, we round the window to the nearest upper rounded 200x100. | |||
| 3266 | resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 + | |||
| 3267 | chromeOffsetWidth; | |||
| 3268 | } | |||
| 3269 | ||||
| 3270 | if (aInputHeight > (availContentHeight + chromeOffsetHeight)) { | |||
| 3271 | resultHeight = availContentHeight + chromeOffsetHeight; | |||
| 3272 | } else if (aInputHeight < (100 + chromeOffsetHeight)) { | |||
| 3273 | resultHeight = 100 + chromeOffsetHeight; | |||
| 3274 | } else { | |||
| 3275 | resultHeight = | |||
| 3276 | NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 + | |||
| 3277 | chromeOffsetHeight; | |||
| 3278 | } | |||
| 3279 | ||||
| 3280 | *aOutputWidth = resultWidth; | |||
| 3281 | *aOutputHeight = resultHeight; | |||
| 3282 | } | |||
| 3283 | ||||
| 3284 | bool nsContentUtils::ThreadsafeIsCallerChrome() { | |||
| 3285 | return NS_IsMainThread() ? IsCallerChrome() | |||
| 3286 | : IsCurrentThreadRunningChromeWorker(); | |||
| 3287 | } | |||
| 3288 | ||||
| 3289 | bool nsContentUtils::IsCallerUAWidget() { | |||
| 3290 | JSContext* cx = GetCurrentJSContext(); | |||
| 3291 | if (!cx) { | |||
| 3292 | return false; | |||
| 3293 | } | |||
| 3294 | ||||
| 3295 | JS::Realm* realm = JS::GetCurrentRealmOrNull(cx); | |||
| 3296 | if (!realm) { | |||
| 3297 | return false; | |||
| 3298 | } | |||
| 3299 | ||||
| 3300 | return xpc::IsUAWidgetScope(realm); | |||
| 3301 | } | |||
| 3302 | ||||
| 3303 | bool nsContentUtils::IsSystemCaller(JSContext* aCx) { | |||
| 3304 | // Note that SubjectPrincipal() assumes we are in a compartment here. | |||
| 3305 | return SubjectPrincipal(aCx) == sSystemPrincipal; | |||
| 3306 | } | |||
| 3307 | ||||
| 3308 | bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) { | |||
| 3309 | CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get(); | |||
| 3310 | MOZ_ASSERT(ccjscx->Context() == aCx)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ccjscx->Context() == aCx)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ccjscx->Context() == aCx) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ccjscx->Context() == aCx" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3310); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ccjscx->Context() == aCx" ")"); do { MOZ_CrashSequence (__null, 3310); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3311 | ||||
| 3312 | return ccjscx->IsSystemCaller(); | |||
| 3313 | } | |||
| 3314 | ||||
| 3315 | // static | |||
| 3316 | bool nsContentUtils::LookupBindingMember( | |||
| 3317 | JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId, | |||
| 3318 | JS::MutableHandle<JS::PropertyDescriptor> aDesc) { | |||
| 3319 | return true; | |||
| 3320 | } | |||
| 3321 | ||||
| 3322 | nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode( | |||
| 3323 | nsINode* aChild) { | |||
| 3324 | if (aChild->IsDocument()) { | |||
| 3325 | for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc; | |||
| 3326 | bc = bc->GetParent()) { | |||
| 3327 | if (bc->GetEmbedderElement()) { | |||
| 3328 | return bc->GetEmbedderElement(); | |||
| 3329 | } | |||
| 3330 | } | |||
| 3331 | return nullptr; | |||
| 3332 | } | |||
| 3333 | ||||
| 3334 | nsINode* parent = aChild->GetParentNode(); | |||
| 3335 | if (parent && parent->IsContent() && aChild->IsContent()) { | |||
| 3336 | parent = aChild->AsContent()->GetFlattenedTreeParent(); | |||
| 3337 | } | |||
| 3338 | ||||
| 3339 | return parent; | |||
| 3340 | } | |||
| 3341 | ||||
| 3342 | bool nsContentUtils::ContentIsHostIncludingDescendantOf( | |||
| 3343 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
| 3344 | MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleDescendant)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant" " (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence (__null, 3344); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3345 | MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor" " (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence (__null, 3345); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3346 | ||||
| 3347 | while (true) { | |||
| 3348 | if (aPossibleDescendant == aPossibleAncestor) { | |||
| 3349 | return true; | |||
| 3350 | } | |||
| 3351 | if (nsINode* parent = aPossibleDescendant->GetParentNode()) { | |||
| 3352 | aPossibleDescendant = parent; | |||
| 3353 | continue; | |||
| 3354 | } | |||
| 3355 | if (auto* df = DocumentFragment::FromNode(aPossibleDescendant)) { | |||
| 3356 | if (nsINode* host = df->GetHost()) { | |||
| 3357 | aPossibleDescendant = host; | |||
| 3358 | continue; | |||
| 3359 | } | |||
| 3360 | } | |||
| 3361 | break; | |||
| 3362 | } | |||
| 3363 | return false; | |||
| 3364 | } | |||
| 3365 | ||||
| 3366 | // static | |||
| 3367 | bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant, | |||
| 3368 | nsINode* aPossibleAncestor) { | |||
| 3369 | MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleDescendant)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant" " (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence (__null, 3369); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3370 | MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor" " (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence (__null, 3370); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3371 | ||||
| 3372 | do { | |||
| 3373 | if (aPossibleDescendant == aPossibleAncestor) { | |||
| 3374 | return true; | |||
| 3375 | } | |||
| 3376 | ||||
| 3377 | aPossibleDescendant = | |||
| 3378 | GetNearestInProcessCrossDocParentNode(aPossibleDescendant); | |||
| 3379 | } while (aPossibleDescendant); | |||
| 3380 | ||||
| 3381 | return false; | |||
| 3382 | } | |||
| 3383 | ||||
| 3384 | // static | |||
| 3385 | bool nsContentUtils::ContentIsFlattenedTreeDescendantOf( | |||
| 3386 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
| 3387 | MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleDescendant)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant" " (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence (__null, 3387); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3388 | MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor" " (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence (__null, 3388); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3389 | ||||
| 3390 | do { | |||
| 3391 | if (aPossibleDescendant == aPossibleAncestor) { | |||
| 3392 | return true; | |||
| 3393 | } | |||
| 3394 | aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode(); | |||
| 3395 | } while (aPossibleDescendant); | |||
| 3396 | ||||
| 3397 | return false; | |||
| 3398 | } | |||
| 3399 | ||||
| 3400 | // static | |||
| 3401 | bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle( | |||
| 3402 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
| 3403 | MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleDescendant)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant" " (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3403); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence (__null, 3403); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3404 | MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPossibleAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor" " (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence (__null, 3404); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3405 | ||||
| 3406 | do { | |||
| 3407 | if (aPossibleDescendant == aPossibleAncestor) { | |||
| 3408 | return true; | |||
| 3409 | } | |||
| 3410 | aPossibleDescendant = | |||
| 3411 | aPossibleDescendant->GetFlattenedTreeParentNodeForStyle(); | |||
| 3412 | } while (aPossibleDescendant); | |||
| 3413 | ||||
| 3414 | return false; | |||
| 3415 | } | |||
| 3416 | ||||
| 3417 | // static | |||
| 3418 | nsINode* nsContentUtils::Retarget(nsINode* aTargetA, const nsINode* aTargetB) { | |||
| 3419 | while (true && aTargetA) { | |||
| 3420 | // If A's root is not a shadow root... | |||
| 3421 | nsINode* root = aTargetA->SubtreeRoot(); | |||
| 3422 | if (!root->IsShadowRoot()) { | |||
| 3423 | // ...then return A. | |||
| 3424 | return aTargetA; | |||
| 3425 | } | |||
| 3426 | ||||
| 3427 | // or A's root is a shadow-including inclusive ancestor of B... | |||
| 3428 | if (aTargetB && aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) { | |||
| 3429 | // ...then return A. | |||
| 3430 | return aTargetA; | |||
| 3431 | } | |||
| 3432 | ||||
| 3433 | aTargetA = ShadowRoot::FromNode(root)->GetHost(); | |||
| 3434 | } | |||
| 3435 | ||||
| 3436 | return nullptr; | |||
| 3437 | } | |||
| 3438 | ||||
| 3439 | // static | |||
| 3440 | Element* nsContentUtils::GetAnElementForTiming(Element* aTarget, | |||
| 3441 | const Document* aDocument, | |||
| 3442 | nsIGlobalObject* aGlobal) { | |||
| 3443 | if (!aTarget->IsInComposedDoc()) { | |||
| 3444 | return nullptr; | |||
| 3445 | } | |||
| 3446 | ||||
| 3447 | if (!aDocument) { | |||
| 3448 | nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal); | |||
| 3449 | if (!inner) { | |||
| 3450 | return nullptr; | |||
| 3451 | } | |||
| 3452 | aDocument = inner->GetExtantDoc(); | |||
| 3453 | } | |||
| 3454 | ||||
| 3455 | MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDocument)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { MOZ_CrashSequence(__null, 3455); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3456 | ||||
| 3457 | if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument || | |||
| 3458 | !aDocument->IsCurrentActiveDocument()) { | |||
| 3459 | return nullptr; | |||
| 3460 | } | |||
| 3461 | ||||
| 3462 | return aTarget; | |||
| 3463 | } | |||
| 3464 | ||||
| 3465 | // static | |||
| 3466 | nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode, | |||
| 3467 | nsTArray<nsINode*>& aArray) { | |||
| 3468 | while (aNode) { | |||
| 3469 | aArray.AppendElement(aNode); | |||
| 3470 | aNode = aNode->GetParentNode(); | |||
| 3471 | } | |||
| 3472 | return NS_OK; | |||
| 3473 | } | |||
| 3474 | ||||
| 3475 | // static | |||
| 3476 | template <typename GetParentFunc, typename ComputeChildIndexFunc> | |||
| 3477 | nsresult static GetInclusiveAncestorsAndOffsetsHelper( | |||
| 3478 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
| 3479 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc, | |||
| 3480 | ComputeChildIndexFunc aComputeChildIndexFunc) { | |||
| 3481 | NS_ENSURE_ARG_POINTER(aNode)do { if ((__builtin_expect(!!(!(aNode)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNode" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3481); return NS_ERROR_INVALID_POINTER; } } while (false); | |||
| 3482 | ||||
| 3483 | if (!aNode->IsContent()) { | |||
| 3484 | return NS_ERROR_FAILURE; | |||
| 3485 | } | |||
| 3486 | nsIContent* content = aNode->AsContent(); | |||
| 3487 | ||||
| 3488 | if (!aAncestorNodes.IsEmpty()) { | |||
| 3489 | NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3489); | |||
| 3490 | aAncestorNodes.Clear(); | |||
| 3491 | } | |||
| 3492 | ||||
| 3493 | if (!aAncestorOffsets.IsEmpty()) { | |||
| 3494 | NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3494); | |||
| 3495 | aAncestorOffsets.Clear(); | |||
| 3496 | } | |||
| 3497 | ||||
| 3498 | // insert the node itself | |||
| 3499 | aAncestorNodes.AppendElement(content); | |||
| 3500 | aAncestorOffsets.AppendElement(Some(aOffset)); | |||
| 3501 | ||||
| 3502 | // insert all the ancestors | |||
| 3503 | nsIContent* child = content; | |||
| 3504 | nsIContent* parent = aGetParentFunc(child); | |||
| 3505 | while (parent) { | |||
| 3506 | aAncestorNodes.AppendElement(parent->AsContent()); | |||
| 3507 | aAncestorOffsets.AppendElement(aComputeChildIndexFunc(parent, child)); | |||
| 3508 | child = parent; | |||
| 3509 | parent = aGetParentFunc(child); | |||
| 3510 | } | |||
| 3511 | ||||
| 3512 | return NS_OK; | |||
| 3513 | } | |||
| 3514 | ||||
| 3515 | nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets( | |||
| 3516 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
| 3517 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets) { | |||
| 3518 | return GetInclusiveAncestorsAndOffsetsHelper( | |||
| 3519 | aNode, aOffset, aAncestorNodes, aAncestorOffsets, | |||
| 3520 | [](nsIContent* aContent) { return aContent->GetParent(); }, | |||
| 3521 | [](nsIContent* aParent, nsIContent* aChild) { | |||
| 3522 | return aParent->ComputeIndexOf(aChild); | |||
| 3523 | }); | |||
| 3524 | } | |||
| 3525 | ||||
| 3526 | nsresult nsContentUtils::GetFlattenedTreeAncestorsAndOffsetsForSelection( | |||
| 3527 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
| 3528 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets) { | |||
| 3529 | return GetInclusiveAncestorsAndOffsetsHelper( | |||
| 3530 | aNode, aOffset, aAncestorNodes, aAncestorOffsets, | |||
| 3531 | [](nsIContent* aContent) -> nsIContent* { | |||
| 3532 | return nsIContent::FromNodeOrNull( | |||
| 3533 | GetParentNodeForComparison<TreeKind::FlatForSelection>::Get( | |||
| 3534 | aContent)); | |||
| 3535 | }, | |||
| 3536 | [](nsIContent* aParent, nsIContent* aChild) { | |||
| 3537 | return GetParentNodeForComparison< | |||
| 3538 | TreeKind::FlatForSelection>::ComputeChildIndex(aParent, aChild); | |||
| 3539 | }); | |||
| 3540 | } | |||
| 3541 | ||||
| 3542 | /* static */ | |||
| 3543 | nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1, | |||
| 3544 | nsINode* aNode2) { | |||
| 3545 | MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode1)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")" ); do { MOZ_CrashSequence(__null, 3545); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3546 | MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode2)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")" ); do { MOZ_CrashSequence(__null, 3546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3547 | return CommonAncestors<GetParentNode>(*aNode1, *aNode2) | |||
| 3548 | .GetClosestCommonAncestor(); | |||
| 3549 | } | |||
| 3550 | ||||
| 3551 | /* static */ | |||
| 3552 | nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor( | |||
| 3553 | nsINode* aNode1, nsINode* aNode2) { | |||
| 3554 | if (aNode1 == aNode2) { | |||
| 3555 | return aNode1; | |||
| 3556 | } | |||
| 3557 | ||||
| 3558 | MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode1)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")" ); do { MOZ_CrashSequence(__null, 3558); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3559 | MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode2)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")" ); do { MOZ_CrashSequence(__null, 3559); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3560 | return CommonAncestors<GetParentOrShadowHostNode>(*aNode1, *aNode2) | |||
| 3561 | .GetClosestCommonAncestor(); | |||
| 3562 | } | |||
| 3563 | ||||
| 3564 | /* static */ | |||
| 3565 | nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper( | |||
| 3566 | nsIContent* aContent1, nsIContent* aContent2) { | |||
| 3567 | MOZ_ASSERT(aContent1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent1" ")" ); do { MOZ_CrashSequence(__null, 3567); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3568 | MOZ_ASSERT(aContent2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent2" ")" ); do { MOZ_CrashSequence(__null, 3568); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3569 | return CommonAncestors<GetFlattenedTreeParent>(*aContent1, *aContent2) | |||
| 3570 | .GetClosestCommonAncestor(); | |||
| 3571 | } | |||
| 3572 | ||||
| 3573 | /* static */ | |||
| 3574 | nsINode* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection( | |||
| 3575 | nsINode* aNode1, nsINode* aNode2) { | |||
| 3576 | if (aNode1 == aNode2) { | |||
| 3577 | return aNode1; | |||
| 3578 | } | |||
| 3579 | MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode1)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")" ); do { MOZ_CrashSequence(__null, 3579); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3580 | MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode2)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")" ); do { MOZ_CrashSequence(__null, 3580); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3581 | return CommonAncestors<GetFlattenedTreeParentNodeForSelection>(*aNode1, | |||
| 3582 | *aNode2) | |||
| 3583 | .GetClosestCommonAncestor(); | |||
| 3584 | } | |||
| 3585 | ||||
| 3586 | /* static */ | |||
| 3587 | Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle( | |||
| 3588 | Element* aElement1, Element* aElement2) { | |||
| 3589 | MOZ_ASSERT(aElement1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement1" ")" ); do { MOZ_CrashSequence(__null, 3589); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3590 | MOZ_ASSERT(aElement2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement2" ")" ); do { MOZ_CrashSequence(__null, 3590); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3591 | return CommonAncestors<GetFlattenedTreeParentElementForStyle>(*aElement1, | |||
| 3592 | *aElement2) | |||
| 3593 | .GetClosestCommonAncestor(); | |||
| 3594 | } | |||
| 3595 | ||||
| 3596 | /* static */ | |||
| 3597 | template <TreeKind aKind, typename Dummy> | |||
| 3598 | Maybe<int32_t> nsContentUtils::CompareChildNodes( | |||
| 3599 | const nsINode& aParent, const nsIContent* aChild1, | |||
| 3600 | const nsIContent* aChild2, NodeIndexCache* aIndexCache /* = nullptr */) { | |||
| 3601 | MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild1,do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild1) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3602); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3602); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3602 | GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent)do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild1) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3602); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3602); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3603 | MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild2,do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3604); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3604); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3604 | GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent)do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3604); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3604); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3605 | // See the explanation of TreeKindToCompareChildren. aParent may be computed | |||
| 3606 | // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM. | |||
| 3607 | MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3611); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3608 | aKind == TreeKind::DOM && aChild1,do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3611); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3609 | GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent ||do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3611); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3610 | GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3611); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3611 | aChild1) == &aParent)do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3611); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3612 | MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3616); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3613 | aKind == TreeKind::DOM && aChild2,do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3616); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3614 | GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent ||do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3616); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3615 | GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3616); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3616 | aChild2) == &aParent)do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3616); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3617 | ||||
| 3618 | // FIXME: bug 1946003 and bug 1946008. | |||
| 3619 | if ((aChild1 && NS_WARN_IF(aChild1->IsDocumentFragment())NS_warn_if_impl(aChild1->IsDocumentFragment(), "aChild1->IsDocumentFragment()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3619)) || | |||
| 3620 | (aChild2 && NS_WARN_IF(aChild2->IsDocumentFragment())NS_warn_if_impl(aChild2->IsDocumentFragment(), "aChild2->IsDocumentFragment()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3620))) [[unlikely]] { | |||
| 3621 | return Nothing(); | |||
| 3622 | } | |||
| 3623 | if (MOZ_UNLIKELY(aChild1 == aChild2)(__builtin_expect(!!(aChild1 == aChild2), 0))) { | |||
| 3624 | return Some(0); | |||
| 3625 | } | |||
| 3626 | MOZ_ASSERT(aChild1 || aChild2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChild1 || aChild2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aChild1 || aChild2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild1 || aChild2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3626); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aChild1 || aChild2" ")"); do { MOZ_CrashSequence (__null, 3626); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3627 | // Native anonymous content (e.g. ::before/::after pseudo-elements) is not in | |||
| 3628 | // the regular child list, so the sibling/index fast paths below cannot order | |||
| 3629 | // it against regular children or the end-of-children boundary (a null child). | |||
| 3630 | // GetIndexInParent assigns flat-tree-consistent indices to NAC roots, so use | |||
| 3631 | // it to order the points instead. | |||
| 3632 | if (MOZ_UNLIKELY((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree ()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree ())), 0)) | |||
| 3633 | (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree()))(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree ()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree ())), 0))) { | |||
| 3634 | const nsINode& parent = | |||
| 3635 | aChild1 ? *GetParentNodeForComparison<aKind>::Get(aChild1) | |||
| 3636 | : *GetParentNodeForComparison<aKind>::Get(aChild2); | |||
| 3637 | // A null child is the boundary at the end of the parent's regular child | |||
| 3638 | // list (offset == number of regular children). Regular children occupy | |||
| 3639 | // indices [0, regularCount) in the index space assigned by | |||
| 3640 | // GetIndexInParent, while trailing NAC (other anonymous subtrees and | |||
| 3641 | // ::after) start at regularCount. The discriminator here must match the | |||
| 3642 | // one in GetIndexInParent so the boundary lands in the same index space: | |||
| 3643 | // only the flat tree indexes regular children via the flattened iterator; | |||
| 3644 | // DOM and ShadowIncludingDOM both index them via ComputeIndexOf. | |||
| 3645 | const int32_t regularCount = | |||
| 3646 | aKind == TreeKind::Flat | |||
| 3647 | ? int32_t(FlattenedChildIterator::GetLength(&parent)) | |||
| 3648 | : int32_t(parent.GetChildCount()); | |||
| 3649 | const auto indexOf = [&](const nsIContent* aChild) -> Maybe<int32_t> { | |||
| 3650 | if (!aChild) { | |||
| 3651 | return Some(regularCount); | |||
| 3652 | } | |||
| 3653 | return aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&parent, aChild) | |||
| 3654 | : GetIndexInParent<aKind>(&parent, aChild); | |||
| 3655 | }; | |||
| 3656 | const Maybe<int32_t> child1Index = indexOf(aChild1); | |||
| 3657 | const Maybe<int32_t> child2Index = indexOf(aChild2); | |||
| 3658 | if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index .isSome()), 1))) { | |||
| 3659 | if (*child1Index != *child2Index) { | |||
| 3660 | return Some(*child1Index < *child2Index ? -1 : 1); | |||
| 3661 | } | |||
| 3662 | // Equal indices only happen when one child is the end-of-children | |||
| 3663 | // boundary (null) and the other is the first trailing NAC subtree at the | |||
| 3664 | // same index. The boundary precedes trailing NAC in tree order. | |||
| 3665 | if (!aChild1) { | |||
| 3666 | return Some(-1); | |||
| 3667 | } | |||
| 3668 | if (!aChild2) { | |||
| 3669 | return Some(1); | |||
| 3670 | } | |||
| 3671 | } | |||
| 3672 | // XXX Keep the odd traditional behavior for now. | |||
| 3673 | return Some(1); | |||
| 3674 | } | |||
| 3675 | if (!aChild1) { // i.e., end of parent vs aChild2 | |||
| 3676 | return Some(1); | |||
| 3677 | } | |||
| 3678 | if (!aChild2) { // i.e., aChild1 vs. end of parent | |||
| 3679 | return Some(-1); | |||
| 3680 | } | |||
| 3681 | ||||
| 3682 | if constexpr (aKind == TreeKind::FlatForSelection) { | |||
| 3683 | // If we're handling flattened tree for selection, aChild1 and/or aChild2 | |||
| 3684 | // may be: | |||
| 3685 | // - fallback content of a <slot> which has some assigned nodes | |||
| 3686 | // - unassigned child node of a shadow host | |||
| 3687 | // Even though they are not part of the flattened tree, but they are also | |||
| 3688 | // valid for range boundaries. Therefore, we need to handle the case here. | |||
| 3689 | if (aParent.GetAsHTMLSlotElementIfFilledForSelection() || | |||
| 3690 | aParent.GetShadowRootForSelection()) { | |||
| 3691 | if (aChild1->GetParentNode() == &aParent) { | |||
| 3692 | if (aChild2->GetParentNode() == &aParent) { | |||
| 3693 | // If both aChild1 and aChild2 are the fallback content or the | |||
| 3694 | // unassigned children of a shadow host, compare them in the DOM. | |||
| 3695 | return CompareChildNodes<TreeKind::DOM>(aParent, aChild1, aChild2); | |||
| 3696 | } | |||
| 3697 | // If only aChild1 is the fallback content or the unassigned child, | |||
| 3698 | // let's treat it as after the last assigned node. | |||
| 3699 | return Some(1); | |||
| 3700 | } | |||
| 3701 | if (aChild2->GetParentNode() == &aParent) { | |||
| 3702 | // If only aChild2 is the fallback content or the unassigned child, | |||
| 3703 | // let's treat it as after the last assigned node for now. | |||
| 3704 | return Some(-1); | |||
| 3705 | } | |||
| 3706 | } | |||
| 3707 | } | |||
| 3708 | ||||
| 3709 | if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) { | |||
| 3710 | HTMLSlotElement* const slot1 = aChild1->GetAssignedSlot<aKind>(); | |||
| 3711 | HTMLSlotElement* const slot2 = aChild2->GetAssignedSlot<aKind>(); | |||
| 3712 | if (slot1 || slot2) { | |||
| 3713 | // If they are assigned into a same <slot>, compare the index. | |||
| 3714 | if (slot1 == slot2) { | |||
| 3715 | const auto* slot = HTMLSlotElement::FromNode(aParent); | |||
| 3716 | MOZ_ASSERT(slot)do { static_assert( mozilla::detail::AssertionConditionType< decltype(slot)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(slot))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("slot", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot" ")"); do { MOZ_CrashSequence(__null, 3716); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3717 | ||||
| 3718 | constexpr auto NoIndex = size_t(-1); | |||
| 3719 | auto child1Index = NoIndex; | |||
| 3720 | auto child2Index = NoIndex; | |||
| 3721 | size_t index = 0; | |||
| 3722 | for (nsINode* node : slot->AssignedNodes()) { | |||
| 3723 | if (node == aChild1) { | |||
| 3724 | child1Index = index; | |||
| 3725 | if (child2Index != NoIndex) { | |||
| 3726 | break; | |||
| 3727 | } | |||
| 3728 | } else if (node == aChild2) { | |||
| 3729 | child2Index = index; | |||
| 3730 | if (child1Index != NoIndex) { | |||
| 3731 | break; | |||
| 3732 | } | |||
| 3733 | } | |||
| 3734 | index++; | |||
| 3735 | } | |||
| 3736 | ||||
| 3737 | MOZ_ASSERT(child1Index != NoIndex)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child1Index != NoIndex)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(child1Index != NoIndex))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("child1Index != NoIndex" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3737); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "child1Index != NoIndex" ")"); do { MOZ_CrashSequence (__null, 3737); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3738 | MOZ_ASSERT(child2Index != NoIndex)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child2Index != NoIndex)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(child2Index != NoIndex))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("child2Index != NoIndex" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3738); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "child2Index != NoIndex" ")"); do { MOZ_CrashSequence (__null, 3738); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3739 | ||||
| 3740 | return Some(child1Index < child2Index ? -1 : 1); | |||
| 3741 | } | |||
| 3742 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3743 | fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3744 | "aChild1 and aChild2 are not in same "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3745 | "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3746 | ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3747 | ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748) | |||
| 3748 | .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same " "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n" , ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str() , ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str() ) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3748); | |||
| 3749 | MOZ_ASSERT(!slot1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!slot1)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!slot1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!slot1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot1" ")" ); do { MOZ_CrashSequence(__null, 3749); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3750 | MOZ_ASSERT(!slot2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!slot2)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!slot2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!slot2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot2" ")" ); do { MOZ_CrashSequence(__null, 3750); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3751 | return Nothing(); | |||
| 3752 | } | |||
| 3753 | } | |||
| 3754 | ||||
| 3755 | ChildIteratorBase<aKind> iter(&aParent); | |||
| 3756 | ||||
| 3757 | // If the parent node is not a shadow host, we can use | |||
| 3758 | // nsINode::GetNextSibling() and nsINode::GetPreviousSibling() in any trees | |||
| 3759 | // so that we can check whether aChild1 and aChild2 are adjacent siblings. | |||
| 3760 | if (MOZ_LIKELY(!iter.ShadowDOMInvolved())(__builtin_expect(!!(!iter.ShadowDOMInvolved()), 1))) { | |||
| 3761 | if (aChild1->GetNextSibling() == aChild2) { | |||
| 3762 | return Some(-1); | |||
| 3763 | } | |||
| 3764 | if (aChild2->GetNextSibling() == aChild1) { | |||
| 3765 | return Some(1); | |||
| 3766 | } | |||
| 3767 | } | |||
| 3768 | ||||
| 3769 | // Retrieving the first child and the last child is not expensive so, let's | |||
| 3770 | // check whether aChild1 or aChild2 is the first/last child. | |||
| 3771 | const nsIContent* lastChild = iter.GetLastChild(); | |||
| 3772 | MOZ_ASSERT(lastChild)do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lastChild))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lastChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastChild" ")" ); do { MOZ_CrashSequence(__null, 3772); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3773 | if (aChild1 == lastChild) { | |||
| 3774 | return Some(1); | |||
| 3775 | } | |||
| 3776 | if (aChild2 == lastChild) { | |||
| 3777 | return Some(-1); | |||
| 3778 | } | |||
| 3779 | const nsIContent* firstChild = iter.GetFirstChild(); | |||
| 3780 | MOZ_ASSERT(firstChild)do { static_assert( mozilla::detail::AssertionConditionType< decltype(firstChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(firstChild))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("firstChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3780); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild" ")"); do { MOZ_CrashSequence(__null, 3780); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3781 | MOZ_ASSERT(firstChild != lastChild)do { static_assert( mozilla::detail::AssertionConditionType< decltype(firstChild != lastChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(firstChild != lastChild))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("firstChild != lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3781); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "firstChild != lastChild" ")"); do { MOZ_CrashSequence (__null, 3781); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 3782 | if (aChild1 == firstChild) { | |||
| 3783 | return Some(-1); | |||
| 3784 | } | |||
| 3785 | if (aChild2 == firstChild) { | |||
| 3786 | return Some(1); | |||
| 3787 | } | |||
| 3788 | ||||
| 3789 | // nsINode::ComputeIndexOf() computes the index with scanning siblings from | |||
| 3790 | // the first child in the worst case. However, if the node caches the | |||
| 3791 | // computed result, the scan range may be narrowed in fortunate cases. | |||
| 3792 | // Therefore, if the node uses the cache, we should use it because the callers | |||
| 3793 | // may need to compute the index again. In such cases, the cache saves the | |||
| 3794 | // computation cost. | |||
| 3795 | if (aParent.MaybeCachesComputedIndex()) { | |||
| 3796 | Maybe<uint32_t> child1Index; | |||
| 3797 | Maybe<uint32_t> child2Index; | |||
| 3798 | if (aIndexCache) { | |||
| 3799 | Maybe<int32_t> maybeGenContentChild1Index; | |||
| 3800 | Maybe<int32_t> maybeGenContentChild2Index; | |||
| 3801 | aIndexCache->ComputeIndicesOf<aKind>(&aParent, aChild1, aChild2, | |||
| 3802 | maybeGenContentChild1Index, | |||
| 3803 | maybeGenContentChild2Index); | |||
| 3804 | // Negative offset if the child is generated content or native anonymous | |||
| 3805 | // content. However, this method does not support such nodes. Therefore, | |||
| 3806 | // we should treat them as "disconnected". | |||
| 3807 | if (maybeGenContentChild1Index && *maybeGenContentChild1Index >= 0) { | |||
| 3808 | child1Index.emplace(static_cast<uint32_t>(*maybeGenContentChild1Index)); | |||
| 3809 | } | |||
| 3810 | if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) { | |||
| 3811 | child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index)); | |||
| 3812 | } | |||
| 3813 | #ifdef DEBUG1 | |||
| 3814 | const Maybe<uint32_t> child1IndexDebug = | |||
| 3815 | aParent.ComputeIndexOf<aKind>(aChild1); | |||
| 3816 | NS_WARNING_ASSERTION(do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3817 | child1Index == child1IndexDebug,do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3818 | fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3819 | "{}\naParent={}\naChild1={}\n",do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3820 | ToString(child1IndexDebug), ToString(child1Index),do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3821 | ToString(aParent), ToString(*aChild1))do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false) | |||
| 3822 | .c_str())do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString (child1Index), ToString(aParent), ToString(*aChild1)) .c_str( ), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3822); } } while (false); | |||
| 3823 | MOZ_ASSERT(child1Index == child1IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child1Index == child1IndexDebug)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(child1Index == child1IndexDebug ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child1Index == child1IndexDebug" ")"); do { MOZ_CrashSequence(__null, 3823); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3824 | const Maybe<uint32_t> child2IndexDebug = | |||
| 3825 | aParent.ComputeIndexOf<aKind>(aChild2); | |||
| 3826 | NS_WARNING_ASSERTION(do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3827 | child2Index == child2IndexDebug,do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3828 | fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3829 | "{}\naParent={}\naChild1={}\n",do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3830 | ToString(child2IndexDebug), ToString(child2Index),do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3831 | ToString(aParent), ToString(*aChild2))do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false) | |||
| 3832 | .c_str())do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(*aChild2)) .c_str( ), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3832); } } while (false); | |||
| 3833 | MOZ_ASSERT(child2Index == child2IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child2Index == child2IndexDebug)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(child2Index == child2IndexDebug ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug" ")"); do { MOZ_CrashSequence(__null, 3833); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3834 | #endif // #ifdef DEBUG | |||
| 3835 | } else { | |||
| 3836 | child1Index = aParent.ComputeIndexOf<aKind>(aChild1); | |||
| 3837 | child2Index = aParent.ComputeIndexOf<aKind>(aChild2); | |||
| 3838 | } | |||
| 3839 | if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index .isSome()), 1))) { | |||
| 3840 | MOZ_ASSERT(*child1Index != *child2Index)do { static_assert( mozilla::detail::AssertionConditionType< decltype(*child1Index != *child2Index)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*child1Index != *child2Index ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "*child1Index != *child2Index", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*child1Index != *child2Index" ")"); do { MOZ_CrashSequence(__null, 3840); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3841 | return Some(*child1Index < *child2Index ? -1 : 1); | |||
| 3842 | } | |||
| 3843 | // XXX Keep the odd traditional behavior for now. | |||
| 3844 | return Some(child1Index.isNothing() && child2Index.isSome() ? -1 : 1); | |||
| 3845 | } | |||
| 3846 | ||||
| 3847 | // On the other hand, it does not use the cache, let's scan siblings starting | |||
| 3848 | // from aChild1. Then, if we find aChild2, the position is aChild1 < aChild2. | |||
| 3849 | // Otherwise, aChild2 < aChild1. This narrows the scanning range than using | |||
| 3850 | // ComputeIndexOf(), i.e., even in the worst case, this is faster than a call | |||
| 3851 | // of ComputeIndexOf(). | |||
| 3852 | if (NS_WARN_IF(!iter.Seek(aChild1))NS_warn_if_impl(!iter.Seek(aChild1), "!iter.Seek(aChild1)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3852)) { | |||
| 3853 | return Nothing{}; | |||
| 3854 | } | |||
| 3855 | for (const nsIContent* followingSiblingOfChild1 = iter.GetNextChild(); | |||
| 3856 | followingSiblingOfChild1; | |||
| 3857 | followingSiblingOfChild1 = iter.GetNextChild()) { | |||
| 3858 | if (followingSiblingOfChild1 == aChild2) { | |||
| 3859 | return Some(-1); | |||
| 3860 | } | |||
| 3861 | } | |||
| 3862 | MOZ_ASSERT(aParent.ComputeIndexOf<aKind>(aChild2).isSome())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent.ComputeIndexOf<aKind>(aChild2).isSome( ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aParent.ComputeIndexOf<aKind>(aChild2).isSome( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParent.ComputeIndexOf<aKind>(aChild2).isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.ComputeIndexOf<aKind>(aChild2).isSome()" ")"); do { MOZ_CrashSequence(__null, 3862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 3863 | return Some(1); | |||
| 3864 | } | |||
| 3865 | ||||
| 3866 | /* static */ | |||
| 3867 | template <TreeKind aKind, typename Dummy> | |||
| 3868 | Maybe<int32_t> nsContentUtils::CompareClosestCommonAncestorChildren( | |||
| 3869 | const nsINode& aParent, const nsIContent* aChild1, | |||
| 3870 | const nsIContent* aChild2, nsContentUtils::NodeIndexCache* aIndexCache) { | |||
| 3871 | MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild1,do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild1) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3872); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3872); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3872 | GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent)do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild1) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3872); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3872); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3873 | MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild2,do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3874); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3874); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3874 | GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent)do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3874); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3874); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3875 | // See the explanation of TreeKindToCompareChildren. aParent may be computed | |||
| 3876 | // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM. | |||
| 3877 | MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3881); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3878 | aKind == TreeKind::DOM && aChild1,do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3881); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3879 | GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent ||do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3881); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3880 | GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3881); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3881 | aChild1) == &aParent)do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild1) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3881); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3882 | MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3886); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3883 | aKind == TreeKind::DOM && aChild2,do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3886); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3884 | GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent ||do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3886); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3885 | GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3886); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3886 | aChild2) == &aParent)do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (aChild2) == &aParent || GetParentNodeForComparison<TreeKind ::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3886); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3887 | ||||
| 3888 | if (aChild1 && aChild2) { | |||
| 3889 | if (MOZ_UNLIKELY(aChild1->IsShadowRoot())(__builtin_expect(!!(aChild1->IsShadowRoot()), 0))) { | |||
| 3890 | // Shadow roots come before light DOM per | |||
| 3891 | // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order | |||
| 3892 | MOZ_ASSERT(!aChild2->IsShadowRoot(), "Two shadow roots?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aChild2->IsShadowRoot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aChild2->IsShadowRoot()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aChild2->IsShadowRoot()" " (" "Two shadow roots?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild2->IsShadowRoot()" ") (" "Two shadow roots?" ")"); do { MOZ_CrashSequence(__null , 3892); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 3893 | return Some(-1); | |||
| 3894 | } | |||
| 3895 | if (MOZ_UNLIKELY(aChild2->IsShadowRoot())(__builtin_expect(!!(aChild2->IsShadowRoot()), 0))) { | |||
| 3896 | return Some(1); | |||
| 3897 | } | |||
| 3898 | } | |||
| 3899 | // FIXME: bug 1946003 and bug 1946008. | |||
| 3900 | if (MOZ_UNLIKELY((aChild1 && aChild1->IsDocumentFragment()) ||(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment ()) || (aChild2 && aChild2->IsDocumentFragment())) , 0)) | |||
| 3901 | (aChild2 && aChild2->IsDocumentFragment()))(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment ()) || (aChild2 && aChild2->IsDocumentFragment())) , 0))) { | |||
| 3902 | // XXX Keep the odd traditional behavior for now. I think that we should | |||
| 3903 | // return Nothing in this case. | |||
| 3904 | return Some(1); | |||
| 3905 | } | |||
| 3906 | ||||
| 3907 | const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<aKind>( | |||
| 3908 | aParent, aChild1, aChild2, aIndexCache); | |||
| 3909 | if (MOZ_UNLIKELY(comp.isNothing())(__builtin_expect(!!(comp.isNothing()), 0))) { | |||
| 3910 | NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3912); MOZ_PretendNoReturn (); } } while (0) | |||
| 3911 | "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3912); MOZ_PretendNoReturn (); } } while (0) | |||
| 3912 | "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3912); MOZ_PretendNoReturn (); } } while (0); | |||
| 3913 | // XXX Keep the odd traditional behavior for now. I think that we should | |||
| 3914 | // return Nothing in this case. | |||
| 3915 | return Some(1); | |||
| 3916 | } | |||
| 3917 | #ifdef DEBUG1 | |||
| 3918 | const auto NodeIsNullOrValidChild = [](const nsINode& aParent, | |||
| 3919 | const nsIContent* aChild) { | |||
| 3920 | if (!aChild || aParent.ComputeIndexOf<aKind>(aChild).isSome()) { | |||
| 3921 | return true; | |||
| 3922 | } | |||
| 3923 | if constexpr (aKind == TreeKind::FlatForSelection) { | |||
| 3924 | const Element* const excluderShadowHostOrSlotElement = | |||
| 3925 | aChild->GetClosestFlatTreeAncestorElementForNonFlatTreeNode< | |||
| 3926 | TreeKind::FlatForSelection>(); | |||
| 3927 | if (excluderShadowHostOrSlotElement && | |||
| 3928 | (excluderShadowHostOrSlotElement == &aParent || | |||
| 3929 | excluderShadowHostOrSlotElement->GetShadowRootForSelection() == | |||
| 3930 | &aParent)) { | |||
| 3931 | return true; | |||
| 3932 | } | |||
| 3933 | } | |||
| 3934 | return false; | |||
| 3935 | }; | |||
| 3936 | const auto ChildrenHaveSameIndex = [](const nsIContent* aChild1, | |||
| 3937 | const nsIContent* aChild2) { | |||
| 3938 | if (aChild1 == aChild2) { | |||
| 3939 | return true; | |||
| 3940 | } | |||
| 3941 | const bool child1IsAtEndOfParent = | |||
| 3942 | !aChild1 || | |||
| 3943 | (aKind == TreeKind::FlatForSelection && | |||
| 3944 | aChild1->GetClosestFlatTreeAncestorElementForNonFlatTreeNode< | |||
| 3945 | TreeKind::FlatForSelection>()); | |||
| 3946 | const bool child2IsAtEndOfParent = | |||
| 3947 | !aChild2 || | |||
| 3948 | (aKind == TreeKind::FlatForSelection && | |||
| 3949 | aChild2->GetClosestFlatTreeAncestorElementForNonFlatTreeNode< | |||
| 3950 | TreeKind::FlatForSelection>()); | |||
| 3951 | return child1IsAtEndOfParent && child2IsAtEndOfParent; | |||
| 3952 | }; | |||
| 3953 | const auto ChildIndexIsLessThanTheOtherChildIndex = | |||
| 3954 | [](const nsINode& aParent, const nsIContent* aChild1, | |||
| 3955 | const nsIContent* aChild2) { | |||
| 3956 | const uint32_t child1Index = | |||
| 3957 | aChild1 ? aParent.ComputeIndexOf<aKind>(aChild1).valueOr( | |||
| 3958 | aParent.GetChildCount<aKind>()) | |||
| 3959 | : aParent.GetChildCount<aKind>(); | |||
| 3960 | const uint32_t child2Index = | |||
| 3961 | aChild2 ? aParent.ComputeIndexOf<aKind>(aChild2).valueOr( | |||
| 3962 | aParent.GetChildCount<aKind>()) | |||
| 3963 | : aParent.GetChildCount<aKind>(); | |||
| 3964 | return child1Index < child2Index; | |||
| 3965 | }; | |||
| 3966 | NS_WARNING_ASSERTION(do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3970); } } while (false) | |||
| 3967 | NodeIsNullOrValidChild(aParent, aChild1),do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3970); } } while (false) | |||
| 3968 | fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}",do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3970); } } while (false) | |||
| 3969 | aKind, ToString(*aChild1), ToString(aParent))do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3970); } } while (false) | |||
| 3970 | .c_str())do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3970); } } while (false); | |||
| 3971 | NS_WARNING_ASSERTION(do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3975); } } while (false) | |||
| 3972 | NodeIsNullOrValidChild(aParent, aChild2),do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3975); } } while (false) | |||
| 3973 | fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}",do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3975); } } while (false) | |||
| 3974 | aKind, ToString(*aChild2), ToString(aParent))do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3975); } } while (false) | |||
| 3975 | .c_str())do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}" , aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3975); } } while (false); | |||
| 3976 | MOZ_ASSERT_IF(!*comp, aChild1 == aChild2)do { if (!*comp) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(aChild1 == aChild2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aChild1 == aChild2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild1 == aChild2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3976); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aChild1 == aChild2" ")"); do { MOZ_CrashSequence (__null, 3976); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false); | |||
| 3977 | const DebugOnly<bool> eitherIsNAC = | |||
| 3978 | (aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) || | |||
| 3979 | (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree()); | |||
| 3980 | const DebugOnly<bool> eitherIsNotPartOfTree = | |||
| 3981 | ShouldHandleAssignedNodesOnSlot<aKind>() && | |||
| 3982 | ((aParent.GetShadowRoot<aKind>() && | |||
| 3983 | ((aChild1 && aChild1->GetParentNode() == &aParent) || | |||
| 3984 | (aChild2 && aChild2->GetParentNode() == &aParent))) || | |||
| 3985 | ((aParent.GetAsHTMLSlotElementIfFilled<aKind>() && | |||
| 3986 | ((aChild1 && !aChild1->GetAssignedSlot<aKind>()) || | |||
| 3987 | (aChild2 && !aChild2->GetAssignedSlot<aKind>()))))); | |||
| 3988 | MOZ_ASSERT_IF(!eitherIsNAC && !*comp,do { if (!eitherIsNAC && !*comp) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(ChildrenHaveSameIndex (aChild1, aChild2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ChildrenHaveSameIndex(aChild1 , aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildrenHaveSameIndex(aChild1, aChild2)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)" ")"); do { MOZ_CrashSequence(__null, 3989); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3989 | ChildrenHaveSameIndex(aChild1, aChild2))do { if (!eitherIsNAC && !*comp) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(ChildrenHaveSameIndex (aChild1, aChild2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ChildrenHaveSameIndex(aChild1 , aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildrenHaveSameIndex(aChild1, aChild2)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 3989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)" ")"); do { MOZ_CrashSequence(__null, 3989); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3990 | MOZ_ASSERT_IF(do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1 , aChild2))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3992); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" ")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3991 | !eitherIsNAC && !eitherIsNotPartOfTree && *comp < 0,do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1 , aChild2))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3992); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" ")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3992 | ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2))do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1 , aChild2))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3992); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)" ")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3993 | MOZ_ASSERT_IF(do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2 , aChild1))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" ")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3994 | !eitherIsNAC && !eitherIsNotPartOfTree && *comp > 0,do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2 , aChild1))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" ")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 3995 | ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1))do { if (!eitherIsNAC && !eitherIsNotPartOfTree && *comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2 , aChild1))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex (aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)" ")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 3996 | #endif // #ifdef DEBUG | |||
| 3997 | return comp; | |||
| 3998 | } | |||
| 3999 | ||||
| 4000 | /* static */ | |||
| 4001 | template <TreeKind aKind, typename Dummy> | |||
| 4002 | Maybe<int32_t> nsContentUtils::CompareChildOffsetAndChildNode( | |||
| 4003 | const nsINode& aParent, uint32_t aOffset1, const nsIContent& aChild2, | |||
| 4004 | NodeIndexCache* aIndexCache /* = nullptr */) { | |||
| 4005 | MOZ_ASSERT_IF(aKind != TreeKind::DOM,do { if (aKind != TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(&aChild2) == &aParent)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4006); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4006); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4006 | GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent)do { if (aKind != TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <aKind>::Get(&aChild2) == &aParent)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4006); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4006); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4007 | // See the explanation of TreeKindToCompareChildren. aParent may be computed | |||
| 4008 | // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM. | |||
| 4009 | MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (&aChild2) == &aParent || GetParentNodeForComparison< TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4013); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4010 | aKind == TreeKind::DOM,do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (&aChild2) == &aParent || GetParentNodeForComparison< TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4013); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4011 | GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent ||do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (&aChild2) == &aParent || GetParentNodeForComparison< TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4013); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4012 | GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (&aChild2) == &aParent || GetParentNodeForComparison< TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4013); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4013 | &aChild2) == &aParent)do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(GetParentNodeForComparison <TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison <TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get (&aChild2) == &aParent || GetParentNodeForComparison< TreeKind::ShadowIncludingDOM>::Get( &aChild2) == & aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4013); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4014 | ||||
| 4015 | if (NS_WARN_IF(aChild2.IsDocumentFragment())NS_warn_if_impl(aChild2.IsDocumentFragment(), "aChild2.IsDocumentFragment()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4015)) { | |||
| 4016 | return Nothing(); | |||
| 4017 | } | |||
| 4018 | // Native anonymous content (e.g. ::before/::after) is not in the regular | |||
| 4019 | // child list, so order it against the [parentNode, aOffset1] boundary using | |||
| 4020 | // the flat-tree index space from GetIndexInParent. aOffset1 indexes regular | |||
| 4021 | // children [0, N); the NAC child sits at child2Index in the same space, and | |||
| 4022 | // the boundary precedes it iff aOffset1 <= child2Index. | |||
| 4023 | if (MOZ_UNLIKELY(aChild2.IsRootOfNativeAnonymousSubtree())(__builtin_expect(!!(aChild2.IsRootOfNativeAnonymousSubtree() ), 0))) { | |||
| 4024 | const Maybe<int32_t> child2Index = | |||
| 4025 | aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2) | |||
| 4026 | : GetIndexInParent<aKind>(&aParent, &aChild2); | |||
| 4027 | if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4027)) { | |||
| 4028 | // XXX Keep the odd traditional behavior for now. | |||
| 4029 | return Some(1); | |||
| 4030 | } | |||
| 4031 | return Some(int32_t(aOffset1) <= *child2Index ? -1 : 1); | |||
| 4032 | } | |||
| 4033 | ||||
| 4034 | MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get(&aChild2 ) == &aParent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get(&aChild2) == &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4034); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent" ")"); do { MOZ_CrashSequence(__null, 4034); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4035 | ||||
| 4036 | const uint32_t parentNodeChildCount = aParent.GetChildCount<aKind>(); | |||
| 4037 | if (NS_WARN_IF(aOffset1 > parentNodeChildCount)NS_warn_if_impl(aOffset1 > parentNodeChildCount, "aOffset1 > parentNodeChildCount" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4037)) { | |||
| 4038 | // If the root caller's boundary points after end of aParent, let's treat | |||
| 4039 | // it's after the fallback content for now... If you find a bug and you know | |||
| 4040 | // better result in this case, feel free to change. | |||
| 4041 | return Some(1); | |||
| 4042 | } | |||
| 4043 | ||||
| 4044 | if constexpr (aKind == TreeKind::FlatForSelection) { | |||
| 4045 | // If we're handling flattened tree for selection, aChild2 may be a fallback | |||
| 4046 | // content of a <slot> which has some assigned nodes or an unassigned child | |||
| 4047 | // node of a shadow host. Then, aChild2 is not part of the flattened tree, | |||
| 4048 | // but it is also valid for range boundaries. Therefore, we need to handle | |||
| 4049 | // the case here. | |||
| 4050 | if (aChild2.GetParentNode() == &aParent && | |||
| 4051 | (aParent.GetAsHTMLSlotElementIfFilledForSelection() || | |||
| 4052 | aParent.GetShadowRootForSelection())) { | |||
| 4053 | // Treat the fallback content and the unassigned node is after the last | |||
| 4054 | // assigned node or the shadow. | |||
| 4055 | // XXX I'm not sure whether we should treat the end of aParent and a | |||
| 4056 | // fallback content node are the same position or not. For now, we treat | |||
| 4057 | // them as the same, but if you find a bug and you know better result in | |||
| 4058 | // this case, feel free to change here. | |||
| 4059 | return aOffset1 == parentNodeChildCount ? Some(0) : Some(-1); | |||
| 4060 | } | |||
| 4061 | } | |||
| 4062 | ||||
| 4063 | if (aOffset1 == parentNodeChildCount) { | |||
| 4064 | return Some(1); // Comparing with after the last child and a child. | |||
| 4065 | } | |||
| 4066 | ||||
| 4067 | MOZ_ASSERT(aParent.GetFirstChild<aKind>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent.GetFirstChild<aKind>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParent.GetFirstChild<aKind >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParent.GetFirstChild<aKind>()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetFirstChild<aKind>()" ")"); do { MOZ_CrashSequence(__null, 4067); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4068 | const nsIContent& firstChild = *aParent.GetFirstChild<aKind>(); | |||
| 4069 | if (&aChild2 == &firstChild) { | |||
| 4070 | return Some(!aOffset1 ? 0 : 1); | |||
| 4071 | } | |||
| 4072 | ||||
| 4073 | MOZ_ASSERT(aParent.GetLastChild<aKind>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent.GetLastChild<aKind>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParent.GetLastChild<aKind >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParent.GetLastChild<aKind>()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetLastChild<aKind>()" ")"); do { MOZ_CrashSequence(__null, 4073); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4074 | const nsIContent& lastChild = *aParent.GetLastChild<aKind>(); | |||
| 4075 | NS_WARNING_ASSERTION(do { if (!(&firstChild != &lastChild)) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n" , ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4079); } } while (false) | |||
| 4076 | &firstChild != &lastChild,do { if (!(&firstChild != &lastChild)) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n" , ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4079); } } while (false) | |||
| 4077 | fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n",do { if (!(&firstChild != &lastChild)) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n" , ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4079); } } while (false) | |||
| 4078 | ToString(firstChild), ToString(aChild2))do { if (!(&firstChild != &lastChild)) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n" , ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4079); } } while (false) | |||
| 4079 | .c_str())do { if (!(&firstChild != &lastChild)) { NS_DebugBreak (NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n" , ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4079); } } while (false); | |||
| 4080 | MOZ_ASSERT(&firstChild != &lastChild)do { static_assert( mozilla::detail::AssertionConditionType< decltype(&firstChild != &lastChild)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(&firstChild != &lastChild ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "&firstChild != &lastChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&firstChild != &lastChild" ")"); do { MOZ_CrashSequence(__null, 4080); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4081 | if (&aChild2 == &lastChild) { | |||
| 4082 | return Some(aOffset1 == parentNodeChildCount - 1 ? 0 : -1); | |||
| 4083 | } | |||
| 4084 | Maybe<uint32_t> child2Index; | |||
| 4085 | if (aIndexCache) { | |||
| 4086 | const Maybe<int32_t> maybeGenContentChild2Index = | |||
| 4087 | aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2); | |||
| 4088 | if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) { | |||
| 4089 | child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index)); | |||
| 4090 | } | |||
| 4091 | #ifdef DEBUG1 | |||
| 4092 | const Maybe<uint32_t> child2IndexDebug = | |||
| 4093 | aParent.ComputeIndexOf<aKind>(&aChild2); | |||
| 4094 | NS_WARNING_ASSERTION(do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4095 | child2Index == child2IndexDebug,do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4096 | fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4097 | "{}\naParent={}\naChild1={}\n",do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4098 | ToString(child2IndexDebug), ToString(child2Index),do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4099 | ToString(aParent), ToString(aChild2))do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false) | |||
| 4100 | .c_str())do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak( NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got " "{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString (child2Index), ToString(aParent), ToString(aChild2)) .c_str() , "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4100); } } while (false); | |||
| 4101 | MOZ_ASSERT(child2Index == child2IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType< decltype(child2Index == child2IndexDebug)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(child2Index == child2IndexDebug ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug" ")"); do { MOZ_CrashSequence(__null, 4101); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4102 | #endif // #ifdef DEBUG | |||
| 4103 | } else { | |||
| 4104 | child2Index = aParent.ComputeIndexOf<aKind>(&aChild2); | |||
| 4105 | } | |||
| 4106 | if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4106)) { | |||
| 4107 | return Some(1); | |||
| 4108 | } | |||
| 4109 | return Some(aOffset1 == *child2Index ? 0 | |||
| 4110 | : (aOffset1 < *child2Index ? -1 : 1)); | |||
| 4111 | } | |||
| 4112 | ||||
| 4113 | /* static */ | |||
| 4114 | template <TreeKind aKind, typename Dummy> | |||
| 4115 | Maybe<int32_t> nsContentUtils::CompareChildNodeAndChildOffset( | |||
| 4116 | const nsINode& aParent, const nsIContent& aChild1, uint32_t aOffset2, | |||
| 4117 | NodeIndexCache* aIndexCache /* = nullptr */) { | |||
| 4118 | const Maybe<int32_t> comp = CompareChildOffsetAndChildNode<aKind>( | |||
| 4119 | aParent, aOffset2, aChild1, aIndexCache); | |||
| 4120 | if (comp.isNothing()) { | |||
| 4121 | return comp; | |||
| 4122 | } | |||
| 4123 | return Some(*comp * -1); | |||
| 4124 | } | |||
| 4125 | ||||
| 4126 | /* static */ | |||
| 4127 | template <TreeKind aKind> | |||
| 4128 | Maybe<int32_t> nsContentUtils::ComparePointsWithIndices( | |||
| 4129 | const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2, | |||
| 4130 | uint32_t aOffset2, NodeIndexCache* aIndexCache) { | |||
| 4131 | MOZ_ASSERT(aParent1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParent1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParent1", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent1" ")" ); do { MOZ_CrashSequence(__null, 4131); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4132 | MOZ_ASSERT(aParent2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParent2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParent2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent2" ")" ); do { MOZ_CrashSequence(__null, 4132); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4133 | ||||
| 4134 | if (aParent1 == aParent2) { | |||
| 4135 | return Some(aOffset1 < aOffset2 ? -1 : (aOffset1 > aOffset2 ? 1 : 0)); | |||
| 4136 | } | |||
| 4137 | ||||
| 4138 | const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors( | |||
| 4139 | *aParent1, *aParent2); | |||
| 4140 | const nsINode* const closestCommonAncestor = | |||
| 4141 | commonAncestors.GetClosestCommonAncestor(); | |||
| 4142 | if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) { | |||
| 4143 | return Nothing(); | |||
| 4144 | } | |||
| 4145 | ||||
| 4146 | const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull( | |||
| 4147 | commonAncestors.GetClosestCommonAncestorChild1()); | |||
| 4148 | const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull( | |||
| 4149 | commonAncestors.GetClosestCommonAncestorChild2()); | |||
| 4150 | MOZ_ASSERT(closestCommonAncestorChild1 != closestCommonAncestorChild2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(closestCommonAncestorChild1 != closestCommonAncestorChild2 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(closestCommonAncestorChild1 != closestCommonAncestorChild2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "closestCommonAncestorChild1 != closestCommonAncestorChild2", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4150); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2" ")"); do { MOZ_CrashSequence(__null, 4150); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4151 | MOZ_ASSERT_IF(!closestCommonAncestorChild1,do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 4152); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4152 | !commonAncestors.GetClosestCommonAncestorChild1())do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 4152); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4153 | MOZ_ASSERT_IF(!closestCommonAncestorChild2,do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 4154); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4154 | !commonAncestors.GetClosestCommonAncestorChild2())do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 4154); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4155 | commonAncestors | |||
| 4156 | .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>(); | |||
| 4157 | if (closestCommonAncestorChild1 && closestCommonAncestorChild2) { | |||
| 4158 | return CompareClosestCommonAncestorChildren< | |||
| 4159 | TreeKindToCompareChildren<aKind>()>( | |||
| 4160 | *closestCommonAncestor, closestCommonAncestorChild1, | |||
| 4161 | closestCommonAncestorChild2, aIndexCache); | |||
| 4162 | } | |||
| 4163 | ||||
| 4164 | if (closestCommonAncestorChild2) { | |||
| 4165 | // aParent1 is the common ancestor. | |||
| 4166 | MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2 ) == aParent1)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind >::Get( closestCommonAncestorChild2) == aParent1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4167); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1" ")"); do { MOZ_CrashSequence(__null, 4167); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4167 | closestCommonAncestorChild2) == aParent1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2 ) == aParent1)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind >::Get( closestCommonAncestorChild2) == aParent1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4167); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1" ")"); do { MOZ_CrashSequence(__null, 4167); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4168 | if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>( | |||
| 4169 | aParent1, closestCommonAncestorChild2)) { | |||
| 4170 | // Comparing a shadow host with its shadow root. | |||
| 4171 | // We consider: | |||
| 4172 | // [aParent1, 0] < closestCommonAncestorChild2 < [aParent1, 1] | |||
| 4173 | return aOffset1 > 0 ? Some(1) : Some(-1); | |||
| 4174 | } | |||
| 4175 | ||||
| 4176 | // FIXME: bug 1946003 and bug 1946008. | |||
| 4177 | if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment ()), 0))) { | |||
| 4178 | // XXX Keep the odd traditional behavior for now. | |||
| 4179 | return Some(1); | |||
| 4180 | } | |||
| 4181 | // If the common ancestor is a shadow host, closestCommonAncestorChild2 must | |||
| 4182 | // be a child node of the host and we shouldn't handle the flattened tree. | |||
| 4183 | // Therefore, we can compare closestCommonAncestorChild2 and the child at | |||
| 4184 | // aBoundary1 can be compared within TreeKind::DOM tree. | |||
| 4185 | // NOTE: When aKind is TreeKind::FlatForSelection, | |||
| 4186 | // GetParentNodeForComparison returns the shadow host as the parent node | |||
| 4187 | // of a child node even if it's not assigned to any <slot>. Therefore, even | |||
| 4188 | // when we should return Nothing, we may return Some value for now. | |||
| 4189 | // Therefore, we need to relax this assertion for TreeKind::FlatForSelection | |||
| 4190 | // until fixing bug 2014622. And it's okay to compare the child nodes not a | |||
| 4191 | // part of flattened tree as in the DOM since anyway we return wrong value. | |||
| 4192 | MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4193 | aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4194 | closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4195 | closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4196 | const Maybe<int32_t> comp = nsContentUtils::CompareChildOffsetAndChildNode< | |||
| 4197 | TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor, aOffset1, | |||
| 4198 | *closestCommonAncestorChild2, | |||
| 4199 | aIndexCache); | |||
| 4200 | if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4200)) { | |||
| 4201 | NS_ASSERTION(do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildOffsetAndChildNode() must return Some " "here. It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4204); MOZ_PretendNoReturn (); } } while (0) | |||
| 4202 | comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildOffsetAndChildNode() must return Some " "here. It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4204); MOZ_PretendNoReturn (); } } while (0) | |||
| 4203 | "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildOffsetAndChildNode() must return Some " "here. It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4204); MOZ_PretendNoReturn (); } } while (0) | |||
| 4204 | "here. It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildOffsetAndChildNode() must return Some " "here. It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4204); MOZ_PretendNoReturn (); } } while (0); | |||
| 4205 | // XXX Keep the odd traditional behavior for now. | |||
| 4206 | return Some(1); | |||
| 4207 | } | |||
| 4208 | // If the child of the closest common ancestor is at aOffset1 of aParent1, | |||
| 4209 | // it means that aOffset2 of aParent2 refers a descendant of the child. | |||
| 4210 | // So, aOffset2 of aParent2 refers a descendant of aOffset1 of aParent1. | |||
| 4211 | if (!*comp) { | |||
| 4212 | return Some(-1); | |||
| 4213 | } | |||
| 4214 | return comp; | |||
| 4215 | } | |||
| 4216 | ||||
| 4217 | // aParent2 is the common ancestor. | |||
| 4218 | MOZ_ASSERT(closestCommonAncestorChild1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(closestCommonAncestorChild1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4218); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence (__null, 4218); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4219 | MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1 ) == aParent2)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind >::Get( closestCommonAncestorChild1) == aParent2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4220); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2" ")"); do { MOZ_CrashSequence(__null, 4220); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4220 | closestCommonAncestorChild1) == aParent2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1 ) == aParent2)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind >::Get( closestCommonAncestorChild1) == aParent2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4220); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2" ")"); do { MOZ_CrashSequence(__null, 4220); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4221 | if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>( | |||
| 4222 | aParent2, closestCommonAncestorChild1)) { | |||
| 4223 | // Comparing a shadow host with its shadow root. | |||
| 4224 | // We consider: [aParent2, 0] < closestCommonAncestorChild1 < [aParent2, 1] | |||
| 4225 | return aOffset2 > 0 ? Some(-1) : Some(1); | |||
| 4226 | } | |||
| 4227 | ||||
| 4228 | // FIXME: bug 1946003 and bug 1946008. | |||
| 4229 | if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment ()), 0))) { | |||
| 4230 | // XXX Keep the odd traditional behavior for now. | |||
| 4231 | return Some(-1); | |||
| 4232 | } | |||
| 4233 | // If the common ancestor is a shadow host, closestCommonAncestorChild1 must | |||
| 4234 | // be a child node of the host and we shouldn't handle the flattened tree. | |||
| 4235 | // Therefore, we can compare closestCommonAncestorChild1 and the child at | |||
| 4236 | // aBoundary2 can be compared within TreeKind::DOM tree. | |||
| 4237 | // NOTE: When aKind is TreeKind::FlatForSelection, | |||
| 4238 | // GetParentNodeForComparison returns the shadow host as the parent node | |||
| 4239 | // of a child node even if it's not assigned to any <slot>. Therefore, even | |||
| 4240 | // when we should return Nothing, we may return Some value for now. | |||
| 4241 | // Therefore, we need to relax this assertion for TreeKind::FlatForSelection | |||
| 4242 | // until fixing bug 2014622. And it's okay to compare the child nodes not a | |||
| 4243 | // part of flattened tree as in the DOM since anyway we return wrong value. | |||
| 4244 | MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4247); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4245 | aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4247); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4246 | closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4247); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4247 | closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4247); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4248 | const Maybe<int32_t> comp = nsContentUtils::CompareChildNodeAndChildOffset< | |||
| 4249 | TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor, | |||
| 4250 | *closestCommonAncestorChild1, | |||
| 4251 | aOffset2, aIndexCache); | |||
| 4252 | if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4252)) { | |||
| 4253 | NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodeAndChildOffset() must return " "Some here. It should've already checked before we call it." , "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4255); MOZ_PretendNoReturn(); } } while (0) | |||
| 4254 | "nsContentUtils::CompareChildNodeAndChildOffset() must return "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodeAndChildOffset() must return " "Some here. It should've already checked before we call it." , "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4255); MOZ_PretendNoReturn(); } } while (0) | |||
| 4255 | "Some here. It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodeAndChildOffset() must return " "Some here. It should've already checked before we call it." , "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4255); MOZ_PretendNoReturn(); } } while (0); | |||
| 4256 | // XXX Keep the odd traditional behavior for now. | |||
| 4257 | return Some(-1); | |||
| 4258 | } | |||
| 4259 | // If the child of the closet common ancestor is at aOffset2 of aParent2, it | |||
| 4260 | // means that aOffset1 of aParent1 refers a descendant of the child. | |||
| 4261 | // So, aOffset1 of aParent1 refers a descendant of aOffset2 of aParent2. | |||
| 4262 | if (!*comp) { | |||
| 4263 | return Some(1); | |||
| 4264 | } | |||
| 4265 | return comp; | |||
| 4266 | } | |||
| 4267 | ||||
| 4268 | /* static */ | |||
| 4269 | BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor( | |||
| 4270 | BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) { | |||
| 4271 | MOZ_ASSERT(aBrowserParent1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowserParent1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowserParent1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowserParent1" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4271); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aBrowserParent1" ")"); do { MOZ_CrashSequence (__null, 4271); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4272 | MOZ_ASSERT(aBrowserParent2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowserParent2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowserParent2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowserParent2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4272); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aBrowserParent2" ")"); do { MOZ_CrashSequence (__null, 4272); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4273 | return CommonAncestors<GetParentBrowserParent>(*aBrowserParent1, | |||
| 4274 | *aBrowserParent2) | |||
| 4275 | .GetClosestCommonAncestor(); | |||
| 4276 | } | |||
| 4277 | ||||
| 4278 | /* static */ | |||
| 4279 | Element* nsContentUtils::GetTargetElement(Document* aDocument, | |||
| 4280 | const nsAString& aAnchorName) { | |||
| 4281 | MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDocument)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { MOZ_CrashSequence(__null, 4281); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4282 | ||||
| 4283 | if (aAnchorName.IsEmpty()) { | |||
| 4284 | return nullptr; | |||
| 4285 | } | |||
| 4286 | // 1. If there is an element in the document tree that has an ID equal to | |||
| 4287 | // fragment, then return the first such element in tree order. | |||
| 4288 | if (Element* el = aDocument->GetElementById(aAnchorName)) { | |||
| 4289 | return el; | |||
| 4290 | } | |||
| 4291 | ||||
| 4292 | // 2. If there is an a element in the document tree that has a name | |||
| 4293 | // attribute whose value is equal to fragment, then return the first such | |||
| 4294 | // element in tree order. | |||
| 4295 | // | |||
| 4296 | // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs? | |||
| 4297 | if (aDocument->IsHTMLDocument()) { | |||
| 4298 | RefPtr<NodeList> list = aDocument->GetElementsByName(aAnchorName); | |||
| 4299 | // Loop through the named nodes looking for the first anchor | |||
| 4300 | uint32_t length = list->Length(); | |||
| 4301 | for (uint32_t i = 0; i < length; i++) { | |||
| 4302 | nsIContent* node = list->Item(i); | |||
| 4303 | if (node->IsHTMLElement(nsGkAtoms::a)) { | |||
| 4304 | return node->AsElement(); | |||
| 4305 | } | |||
| 4306 | } | |||
| 4307 | } else { | |||
| 4308 | constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns; | |||
| 4309 | // Get the list of anchor elements | |||
| 4310 | RefPtr<NodeList> list = | |||
| 4311 | aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns); | |||
| 4312 | // Loop through the anchors looking for the first one with the given name. | |||
| 4313 | for (uint32_t i = 0; true; i++) { | |||
| 4314 | nsIContent* node = list->Item(i); | |||
| 4315 | if (!node) { // End of list | |||
| 4316 | break; | |||
| 4317 | } | |||
| 4318 | ||||
| 4319 | // Compare the name attribute | |||
| 4320 | if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, | |||
| 4321 | aAnchorName, eCaseMatters)) { | |||
| 4322 | return node->AsElement(); | |||
| 4323 | } | |||
| 4324 | } | |||
| 4325 | } | |||
| 4326 | ||||
| 4327 | // 3. Return null. | |||
| 4328 | return nullptr; | |||
| 4329 | } | |||
| 4330 | ||||
| 4331 | /* static */ | |||
| 4332 | template <TreeKind aKind, typename PT1, typename RT1, typename PT2, | |||
| 4333 | typename RT2> | |||
| 4334 | Maybe<int32_t> nsContentUtils::ComparePoints( | |||
| 4335 | const RangeBoundaryBase<PT1, RT1>& aBoundary1, | |||
| 4336 | const RangeBoundaryBase<PT2, RT2>& aBoundary2, | |||
| 4337 | NodeIndexCache* aIndexCache /* = nullptr */) { | |||
| 4338 | if (!aBoundary1.IsSet() || !aBoundary2.IsSet()) { | |||
| 4339 | return Nothing{}; | |||
| 4340 | } | |||
| 4341 | MOZ_ASSERT(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()" ")"); do { MOZ_CrashSequence(__null, 4341); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4342 | ||||
| 4343 | const auto kValidOrInvalidOffsets1 = | |||
| 4344 | RangeBoundaryBase<PT1, RT1>::OffsetFilter::kValidOrInvalidOffsets; | |||
| 4345 | const auto kValidOrInvalidOffsets2 = | |||
| 4346 | RangeBoundaryBase<PT2, RT2>::OffsetFilter::kValidOrInvalidOffsets; | |||
| 4347 | ||||
| 4348 | // RangeBoundaryBase instances may be initialized only with a child node or an | |||
| 4349 | // offset in the container. If both instances have computed offset, we can | |||
| 4350 | // use ComparePointsWithIndices() which works with offsets. | |||
| 4351 | if (aBoundary1.HasOffset() && aBoundary2.HasOffset()) { | |||
| 4352 | return ComparePointsWithIndices<aKind>( | |||
| 4353 | aBoundary1.GetContainer(), *aBoundary1.Offset(kValidOrInvalidOffsets1), | |||
| 4354 | aBoundary2.GetContainer(), *aBoundary2.Offset(kValidOrInvalidOffsets2), | |||
| 4355 | aIndexCache); | |||
| 4356 | } | |||
| 4357 | ||||
| 4358 | // Otherwise, i.e., at least one RangeBoundaryBase stores the child node. | |||
| 4359 | // In the most cases, RangeBoundaryBase has it, so, the worst scenario here | |||
| 4360 | // is, one of the boundaries comes from a StaticRange or is initialized with | |||
| 4361 | // offset and RangeBoundarySetBy::Offset. However, for making it faster in | |||
| 4362 | // the most cases, we should compare the child nodes without offsets if | |||
| 4363 | // possible. | |||
| 4364 | ||||
| 4365 | // If we're comparing children in the same container, we don't need to compute | |||
| 4366 | // common ancestors. So, we can skip it and just compare the children. | |||
| 4367 | if (aBoundary1.GetContainer() == aBoundary2.GetContainer()) { | |||
| 4368 | const nsIContent* const child1 = aBoundary1.GetChildAtOffset(); | |||
| 4369 | MOZ_ASSERT_IF(child1, !child1->IsShadowRoot())do { if (child1) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!child1->IsShadowRoot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!child1->IsShadowRoot())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!child1->IsShadowRoot()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4369); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!child1->IsShadowRoot()" ")"); do { MOZ_CrashSequence (__null, 4369); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false); | |||
| 4370 | const nsIContent* const child2 = aBoundary2.GetChildAtOffset(); | |||
| 4371 | MOZ_ASSERT_IF(child2, !child2->IsShadowRoot())do { if (child2) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(!child2->IsShadowRoot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!child2->IsShadowRoot())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!child2->IsShadowRoot()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4371); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!child2->IsShadowRoot()" ")"); do { MOZ_CrashSequence (__null, 4371); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false); | |||
| 4372 | // But aBoundary1 and aBoundary2 may be not updated for the latest DOM. | |||
| 4373 | // In such case, we need to return Nothing. | |||
| 4374 | if (NS_WARN_IF(child1 && GetParentNodeForComparison<aKind>::Get(child1) !=NS_warn_if_impl(child1 && GetParentNodeForComparison< aKind>::Get(child1) != aBoundary1.GetContainer(), "child1 && GetParentNodeForComparison<aKind>::Get(child1) != aBoundary1.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4375) | |||
| 4375 | aBoundary1.GetContainer())NS_warn_if_impl(child1 && GetParentNodeForComparison< aKind>::Get(child1) != aBoundary1.GetContainer(), "child1 && GetParentNodeForComparison<aKind>::Get(child1) != aBoundary1.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4375) || | |||
| 4376 | NS_WARN_IF(child2 && GetParentNodeForComparison<aKind>::Get(child2) !=NS_warn_if_impl(child2 && GetParentNodeForComparison< aKind>::Get(child2) != aBoundary2.GetContainer(), "child2 && GetParentNodeForComparison<aKind>::Get(child2) != aBoundary2.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4377) | |||
| 4377 | aBoundary2.GetContainer())NS_warn_if_impl(child2 && GetParentNodeForComparison< aKind>::Get(child2) != aBoundary2.GetContainer(), "child2 && GetParentNodeForComparison<aKind>::Get(child2) != aBoundary2.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4377)) [[unlikely]] { | |||
| 4378 | return Nothing{}; | |||
| 4379 | } | |||
| 4380 | return CompareClosestCommonAncestorChildren< | |||
| 4381 | TreeKindToCompareChildren<aKind>()>(*aBoundary1.GetContainer(), child1, | |||
| 4382 | child2, aIndexCache); | |||
| 4383 | } | |||
| 4384 | ||||
| 4385 | // Otherwise, we need to compare the common ancestor children which is the | |||
| 4386 | // most distant different inclusive ancestors of the containers. So, the | |||
| 4387 | // following implementation is similar to ComparePointsWithIndices(), but we | |||
| 4388 | // don't have offset, so, we cannot use offset when we compare the boundaries | |||
| 4389 | // whose one is a descendant of the other. | |||
| 4390 | const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors( | |||
| 4391 | *aBoundary1.GetContainer(), *aBoundary2.GetContainer()); | |||
| 4392 | ||||
| 4393 | const nsINode* const closestCommonAncestor = | |||
| 4394 | commonAncestors.GetClosestCommonAncestor(); | |||
| 4395 | if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) { | |||
| 4396 | return Nothing(); | |||
| 4397 | } | |||
| 4398 | MOZ_ASSERT(commonAncestors.GetClosestCommonAncestor())do { static_assert( mozilla::detail::AssertionConditionType< decltype(commonAncestors.GetClosestCommonAncestor())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(commonAncestors.GetClosestCommonAncestor()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("commonAncestors.GetClosestCommonAncestor()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4398); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "commonAncestors.GetClosestCommonAncestor()" ")"); do { MOZ_CrashSequence(__null, 4398); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4399 | ||||
| 4400 | const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull( | |||
| 4401 | commonAncestors.GetClosestCommonAncestorChild1()); | |||
| 4402 | const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull( | |||
| 4403 | commonAncestors.GetClosestCommonAncestorChild2()); | |||
| 4404 | commonAncestors | |||
| 4405 | .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>(); | |||
| 4406 | MOZ_ASSERT(closestCommonAncestorChild1 != closestCommonAncestorChild2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(closestCommonAncestorChild1 != closestCommonAncestorChild2 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(closestCommonAncestorChild1 != closestCommonAncestorChild2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "closestCommonAncestorChild1 != closestCommonAncestorChild2", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4406); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2" ")"); do { MOZ_CrashSequence(__null, 4406); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4407 | MOZ_ASSERT_IF(!closestCommonAncestorChild1,do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 4408); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4408 | !commonAncestors.GetClosestCommonAncestorChild1())do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()" ")"); do { MOZ_CrashSequence(__null, 4408); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4409 | MOZ_ASSERT_IF(!closestCommonAncestorChild2,do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 4410); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4410 | !commonAncestors.GetClosestCommonAncestorChild2())do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(!commonAncestors .GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2 ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()" ")"); do { MOZ_CrashSequence(__null, 4410); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4411 | if (closestCommonAncestorChild1 && closestCommonAncestorChild2) { | |||
| 4412 | return CompareClosestCommonAncestorChildren< | |||
| 4413 | TreeKindToCompareChildren<aKind>()>( | |||
| 4414 | *closestCommonAncestor, closestCommonAncestorChild1, | |||
| 4415 | closestCommonAncestorChild2, aIndexCache); | |||
| 4416 | } | |||
| 4417 | ||||
| 4418 | if (closestCommonAncestorChild2) { | |||
| 4419 | MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2 ) == aBoundary1.GetContainer())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4420); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()" ")"); do { MOZ_CrashSequence(__null, 4420); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4420 | closestCommonAncestorChild2) == aBoundary1.GetContainer())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2 ) == aBoundary1.GetContainer())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4420); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()" ")"); do { MOZ_CrashSequence(__null, 4420); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4421 | // FIXME: bug 1946003 and bug 1946008. | |||
| 4422 | if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment ()), 0))) { | |||
| 4423 | // XXX Keep the odd traditional behavior for now. | |||
| 4424 | return Some(1); | |||
| 4425 | } | |||
| 4426 | // If the common ancestor is a shadow host, closestCommonAncestorChild2 must | |||
| 4427 | // be a child node of the host and we shouldn't handle the flattened tree. | |||
| 4428 | // Therefore, we can compare closestCommonAncestorChild2 and the child at | |||
| 4429 | // aBoundary1 can be compared within TreeKind::DOM tree. | |||
| 4430 | // NOTE: When aKind is TreeKind::FlatForSelection, | |||
| 4431 | // GetParentNodeForComparison returns the shadow host as the parent node | |||
| 4432 | // of a child node even if it's not assigned to any <slot>. Therefore, even | |||
| 4433 | // when we should return Nothing, we may return Some value for now. | |||
| 4434 | // Therefore, we need to relax this assertion for TreeKind::FlatForSelection | |||
| 4435 | // until fixing bug 2014622. And it's okay to compare the child nodes not a | |||
| 4436 | // part of flattened tree as in the DOM since anyway we return wrong value. | |||
| 4437 | MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4440); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4438 | aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4440); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4439 | closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4440); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4440 | closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild2 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4440); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4441 | const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes< | |||
| 4442 | TreeKindToCompareChildren<TreeKindToCompareChildren<aKind>()>()>( | |||
| 4443 | *closestCommonAncestor, aBoundary1.GetChildAtOffset(), | |||
| 4444 | closestCommonAncestorChild2, aIndexCache); | |||
| 4445 | NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4447); MOZ_PretendNoReturn (); } } while (0) | |||
| 4446 | "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4447); MOZ_PretendNoReturn (); } } while (0) | |||
| 4447 | "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4447); MOZ_PretendNoReturn (); } } while (0); | |||
| 4448 | if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4448)) { | |||
| 4449 | // XXX Keep the odd traditional behavior for now. | |||
| 4450 | return Some(1); | |||
| 4451 | } | |||
| 4452 | // If the child of the closest common ancestor is at aBoundary1, it means | |||
| 4453 | // that aBoundary2 refers a descendant of the child. So, aBoundary2 refers a | |||
| 4454 | // descendant of aBoundary1. | |||
| 4455 | if (!*comp) { | |||
| 4456 | MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4457 | aKind != TreeKind::FlatForSelection,do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4458 | *closestCommonAncestordo { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4459 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4460 | closestCommonAncestorChild2) ==do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4461 | *aBoundary1.Offset(kValidOrInvalidOffsets1))do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild2) == *aBoundary1 .Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4461); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4462 | return Some(-1); | |||
| 4463 | } | |||
| 4464 | // ComputeIndexInParentNode() is the index in the regular child list, which | |||
| 4465 | // native anonymous content is not part of. CompareChildNodes already | |||
| 4466 | // ordered NAC via GetIndexInParent, so skip the regular-index sanity checks | |||
| 4467 | // for it. | |||
| 4468 | const DebugOnly<bool> child2IsNAC = | |||
| 4469 | closestCommonAncestorChild2->IsRootOfNativeAnonymousSubtree(); | |||
| 4470 | MOZ_ASSERT_IF(do { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4471 | !child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection,do { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4472 | *aBoundary1.Offset(kValidOrInvalidOffsets1) <do { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4473 | *closestCommonAncestordo { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4474 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4475 | closestCommonAncestorChild2))do { if (!child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary1.Offset (kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4475); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)" ")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4476 | MOZ_ASSERT_IF(do { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4477 | !child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection,do { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4478 | *closestCommonAncestordo { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4479 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4480 | closestCommonAncestorChild2) <do { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4481 | *aBoundary1.Offset(kValidOrInvalidOffsets1))do { if (!child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild2) < *aBoundary1.Offset( kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4481); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)" ")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4482 | return comp; | |||
| 4483 | } | |||
| 4484 | ||||
| 4485 | MOZ_ASSERT(closestCommonAncestorChild1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(closestCommonAncestorChild1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4485); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence (__null, 4485); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4486 | MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1 ) == aBoundary2.GetContainer())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4487); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()" ")"); do { MOZ_CrashSequence(__null, 4487); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4487 | closestCommonAncestorChild1) == aBoundary2.GetContainer())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1 ) == aBoundary2.GetContainer())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison< aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4487); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()" ")"); do { MOZ_CrashSequence(__null, 4487); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4488 | // FIXME: bug 1946003 and bug 1946008. | |||
| 4489 | if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment ()), 0))) { | |||
| 4490 | // XXX Keep the odd traditional behavior for now. | |||
| 4491 | return Some(-1); | |||
| 4492 | } | |||
| 4493 | // If the common ancestor is a shadow host, closestCommonAncestorChild1 must | |||
| 4494 | // be a child node of the host and we shouldn't handle the flattened tree. | |||
| 4495 | // Therefore, we can compare closestCommonAncestorChild1 and the child at | |||
| 4496 | // aBoundary2 can be compared within TreeKind::DOM tree. | |||
| 4497 | // NOTE: When aKind is TreeKind::FlatForSelection, | |||
| 4498 | // GetParentNodeForComparison returns the shadow host as the parent node | |||
| 4499 | // of a child node even if it's not assigned to any <slot>. Therefore, even | |||
| 4500 | // when we should return Nothing, we may return Some value for now. | |||
| 4501 | // Therefore, we need to relax this assertion for TreeKind::FlatForSelection | |||
| 4502 | // until fixing bug 2014622. And it's okay to compare the child nodes not a | |||
| 4503 | // part of flattened tree as in the DOM since anyway we return wrong value. | |||
| 4504 | MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4507); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4505 | aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4507); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4506 | closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4507); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4507 | closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor ->GetShadowRoot<aKind>()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(closestCommonAncestorChild1 ->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1-> GetParentNode() == closestCommonAncestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4507); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor" ")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4508 | const Maybe<int32_t> comp = | |||
| 4509 | nsContentUtils::CompareChildNodes<TreeKindToCompareChildren<aKind>()>( | |||
| 4510 | *closestCommonAncestor, closestCommonAncestorChild1, | |||
| 4511 | aBoundary2.GetChildAtOffset(), aIndexCache); | |||
| 4512 | NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); MOZ_PretendNoReturn (); } } while (0) | |||
| 4513 | "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); MOZ_PretendNoReturn (); } } while (0) | |||
| 4514 | "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION , "nsContentUtils::CompareChildNodes() must return Some here. " "It should've already checked before we call it.", "comp.isSome()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); MOZ_PretendNoReturn (); } } while (0); | |||
| 4515 | if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4515)) { | |||
| 4516 | // XXX Keep the odd traditional behavior for now. | |||
| 4517 | return Some(-1); | |||
| 4518 | } | |||
| 4519 | // If the child of the closet common ancestor is at aBoundary2, it means that | |||
| 4520 | // aBoundary1 refers a descendant of the child. So, aBoundary1 refers a | |||
| 4521 | // descendant of aBoundary2. | |||
| 4522 | if (!*comp) { | |||
| 4523 | MOZ_ASSERT_IF(aKind != TreeKind::FlatForSelection,do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild1) == *aBoundary2 .Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4527); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4524 | *closestCommonAncestordo { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild1) == *aBoundary2 .Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4527); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4525 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild1) == *aBoundary2 .Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4527); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4526 | closestCommonAncestorChild1) ==do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild1) == *aBoundary2 .Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4527); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4527 | *aBoundary2.Offset(kValidOrInvalidOffsets2))do { if (aKind != TreeKind::FlatForSelection) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren <aKind>()>( closestCommonAncestorChild1) == *aBoundary2 .Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4527); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4528 | return Some(1); | |||
| 4529 | } | |||
| 4530 | // ComputeIndexInParentNode() is the index in the regular child list, which | |||
| 4531 | // native anonymous content is not part of. CompareChildNodes already ordered | |||
| 4532 | // NAC via GetIndexInParent, so skip the regular-index sanity checks for it. | |||
| 4533 | const DebugOnly<bool> child1IsNAC = | |||
| 4534 | closestCommonAncestorChild1->IsRootOfNativeAnonymousSubtree(); | |||
| 4535 | MOZ_ASSERT_IF(do { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4536 | !child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection,do { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4537 | *closestCommonAncestordo { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4538 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4539 | closestCommonAncestorChild1) <do { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4540 | *aBoundary2.Offset(kValidOrInvalidOffsets2))do { if (!child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1) < *aBoundary2.Offset( kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor -> ComputeIndexOf<TreeKindToCompareChildren<aKind>()> ( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)" ")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4541 | MOZ_ASSERT_IF(do { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4542 | !child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection,do { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4543 | *aBoundary2.Offset(kValidOrInvalidOffsets2) <do { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4544 | *closestCommonAncestordo { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4545 | ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 4546 | closestCommonAncestorChild1))do { if (!child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(*aBoundary2.Offset (kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf <TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1 ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind> ()>( closestCommonAncestorChild1)))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4546); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)" ")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 4547 | return comp; | |||
| 4548 | } | |||
| 4549 | ||||
| 4550 | inline bool IsCharInSet(const char* aSet, const char16_t aChar) { | |||
| 4551 | char16_t ch; | |||
| 4552 | while ((ch = *aSet)) { | |||
| 4553 | if (aChar == char16_t(ch)) { | |||
| 4554 | return true; | |||
| 4555 | } | |||
| 4556 | ++aSet; | |||
| 4557 | } | |||
| 4558 | return false; | |||
| 4559 | } | |||
| 4560 | ||||
| 4561 | /** | |||
| 4562 | * This method strips leading/trailing chars, in given set, from string. | |||
| 4563 | */ | |||
| 4564 | ||||
| 4565 | // static | |||
| 4566 | const nsDependentSubstring nsContentUtils::TrimCharsInSet( | |||
| 4567 | const char* aSet, const nsAString& aValue) { | |||
| 4568 | nsAString::const_iterator valueCurrent, valueEnd; | |||
| 4569 | ||||
| 4570 | aValue.BeginReading(valueCurrent); | |||
| 4571 | aValue.EndReading(valueEnd); | |||
| 4572 | ||||
| 4573 | // Skip characters in the beginning | |||
| 4574 | while (valueCurrent != valueEnd) { | |||
| 4575 | if (!IsCharInSet(aSet, *valueCurrent)) { | |||
| 4576 | break; | |||
| 4577 | } | |||
| 4578 | ++valueCurrent; | |||
| 4579 | } | |||
| 4580 | ||||
| 4581 | if (valueCurrent != valueEnd) { | |||
| 4582 | for (;;) { | |||
| 4583 | --valueEnd; | |||
| 4584 | if (!IsCharInSet(aSet, *valueEnd)) { | |||
| 4585 | break; | |||
| 4586 | } | |||
| 4587 | } | |||
| 4588 | ++valueEnd; // Step beyond the last character we want in the value. | |||
| 4589 | } | |||
| 4590 | ||||
| 4591 | // valueEnd should point to the char after the last to copy | |||
| 4592 | return Substring(valueCurrent, valueEnd); | |||
| 4593 | } | |||
| 4594 | ||||
| 4595 | /** | |||
| 4596 | * This method strips leading and trailing whitespace from a string. | |||
| 4597 | */ | |||
| 4598 | ||||
| 4599 | // static | |||
| 4600 | template <bool IsWhitespace(char16_t)> | |||
| 4601 | const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr, | |||
| 4602 | bool aTrimTrailing) { | |||
| 4603 | nsAString::const_iterator start, end; | |||
| 4604 | ||||
| 4605 | aStr.BeginReading(start); | |||
| 4606 | aStr.EndReading(end); | |||
| 4607 | ||||
| 4608 | // Skip whitespace characters in the beginning | |||
| 4609 | while (start != end && IsWhitespace(*start)) { | |||
| 4610 | ++start; | |||
| 4611 | } | |||
| 4612 | ||||
| 4613 | if (aTrimTrailing) { | |||
| 4614 | // Skip whitespace characters in the end. | |||
| 4615 | while (end != start) { | |||
| 4616 | --end; | |||
| 4617 | ||||
| 4618 | if (!IsWhitespace(*end)) { | |||
| 4619 | // Step back to the last non-whitespace character. | |||
| 4620 | ++end; | |||
| 4621 | ||||
| 4622 | break; | |||
| 4623 | } | |||
| 4624 | } | |||
| 4625 | } | |||
| 4626 | ||||
| 4627 | // Return a substring for the string w/o leading and/or trailing | |||
| 4628 | // whitespace | |||
| 4629 | ||||
| 4630 | return Substring(start, end); | |||
| 4631 | } | |||
| 4632 | ||||
| 4633 | // Declaring the templates we are going to use avoid linking issues without | |||
| 4634 | // inlining the method. Considering there is not so much spaces checking | |||
| 4635 | // methods we can consider this to be better than inlining. | |||
| 4636 | template const nsDependentSubstring | |||
| 4637 | nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool); | |||
| 4638 | template const nsDependentSubstring nsContentUtils::TrimWhitespace< | |||
| 4639 | nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool); | |||
| 4640 | template const nsDependentSubstring nsContentUtils::TrimWhitespace< | |||
| 4641 | nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool); | |||
| 4642 | ||||
| 4643 | static inline void KeyAppendSep(nsACString& aKey) { | |||
| 4644 | if (!aKey.IsEmpty()) { | |||
| 4645 | aKey.Append('>'); | |||
| 4646 | } | |||
| 4647 | } | |||
| 4648 | ||||
| 4649 | static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) { | |||
| 4650 | KeyAppendSep(aKey); | |||
| 4651 | ||||
| 4652 | // Could escape separator here if collisions happen. > is not a legal char | |||
| 4653 | // for a name or type attribute, so we should be safe avoiding that extra | |||
| 4654 | // work. | |||
| 4655 | ||||
| 4656 | AppendUTF16toUTF8(aString, aKey); | |||
| 4657 | } | |||
| 4658 | ||||
| 4659 | static inline void KeyAppendString(const nsACString& aString, | |||
| 4660 | nsACString& aKey) { | |||
| 4661 | KeyAppendSep(aKey); | |||
| 4662 | ||||
| 4663 | // Could escape separator here if collisions happen. > is not a legal char | |||
| 4664 | // for a name or type attribute, so we should be safe avoiding that extra | |||
| 4665 | // work. | |||
| 4666 | ||||
| 4667 | aKey.Append(aString); | |||
| 4668 | } | |||
| 4669 | ||||
| 4670 | static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) { | |||
| 4671 | KeyAppendSep(aKey); | |||
| 4672 | ||||
| 4673 | aKey.AppendInt(aInt); | |||
| 4674 | } | |||
| 4675 | ||||
| 4676 | static inline bool IsAutocompleteOff(const nsIContent* aContent) { | |||
| 4677 | return aContent->IsElement() && | |||
| 4678 | aContent->AsElement()->AttrValueIs(kNameSpaceID_None, | |||
| 4679 | nsGkAtoms::autocomplete, u"off"_ns, | |||
| 4680 | eIgnoreCase); | |||
| 4681 | } | |||
| 4682 | ||||
| 4683 | /*static*/ | |||
| 4684 | void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument, | |||
| 4685 | nsACString& aKey) { | |||
| 4686 | MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { MOZ_CrashSequence(__null, 4686); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4687 | ||||
| 4688 | aKey.Truncate(); | |||
| 4689 | ||||
| 4690 | uint32_t partID = aDocument ? aDocument->GetPartID() : 0; | |||
| 4691 | ||||
| 4692 | // Don't capture state for anonymous content | |||
| 4693 | if (aContent->IsInNativeAnonymousSubtree()) { | |||
| 4694 | return; | |||
| 4695 | } | |||
| 4696 | ||||
| 4697 | if (IsAutocompleteOff(aContent)) { | |||
| 4698 | return; | |||
| 4699 | } | |||
| 4700 | ||||
| 4701 | RefPtr<Document> doc = aContent->GetUncomposedDoc(); | |||
| 4702 | ||||
| 4703 | KeyAppendInt(partID, aKey); // first append a partID | |||
| 4704 | bool generatedUniqueKey = false; | |||
| 4705 | ||||
| 4706 | if (doc && doc->IsHTMLOrXHTML()) { | |||
| 4707 | nsHTMLDocument* htmlDoc = doc->AsHTMLDocument(); | |||
| 4708 | ||||
| 4709 | // If we have a form control and can calculate form information, use that | |||
| 4710 | // as the key - it is more reliable than just recording position in the | |||
| 4711 | // DOM. | |||
| 4712 | // XXXbz Is it, really? We have bugs on this, I think... | |||
| 4713 | // Important to have a unique key, and tag/type/name may not be. | |||
| 4714 | // | |||
| 4715 | // The format of the key depends on whether the control has a form, | |||
| 4716 | // and whether the element was parser inserted: | |||
| 4717 | // | |||
| 4718 | // [Has Form, Parser Inserted]: | |||
| 4719 | // fp>type>FormNum>IndOfControlInForm>FormName>name | |||
| 4720 | // | |||
| 4721 | // [No Form, Parser Inserted]: | |||
| 4722 | // dp>type>ControlNum>name | |||
| 4723 | // | |||
| 4724 | // [Has Form, Not Parser Inserted]: | |||
| 4725 | // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name | |||
| 4726 | // | |||
| 4727 | // [No Form, Not Parser Inserted]: | |||
| 4728 | // dn>type>IndOfControlInDoc>name | |||
| 4729 | // | |||
| 4730 | // XXX We don't need to use index if name is there | |||
| 4731 | // XXXbz We don't? Why not? I don't follow. | |||
| 4732 | // | |||
| 4733 | if (const auto* control = nsIFormControl::FromNode(aContent)) { | |||
| 4734 | // Get the control number if this was a parser inserted element from the | |||
| 4735 | // network. | |||
| 4736 | int32_t controlNumber = | |||
| 4737 | control->GetParserInsertedControlNumberForStateKey(); | |||
| 4738 | bool parserInserted = controlNumber != -1; | |||
| 4739 | ||||
| 4740 | RefPtr<ContentList> htmlForms; | |||
| 4741 | RefPtr<ContentList> htmlFormControls; | |||
| 4742 | if (!parserInserted) { | |||
| 4743 | // Getting these lists is expensive, as we need to keep them up to date | |||
| 4744 | // as the document loads, so we avoid it if we don't need them. | |||
| 4745 | htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms), | |||
| 4746 | getter_AddRefs(htmlFormControls)); | |||
| 4747 | } | |||
| 4748 | ||||
| 4749 | // Append the control type | |||
| 4750 | KeyAppendInt(int32_t(control->ControlType()), aKey); | |||
| 4751 | ||||
| 4752 | // If in a form, add form name / index of form / index in form | |||
| 4753 | HTMLFormElement* formElement = control->GetFormInternal(); | |||
| 4754 | if (formElement) { | |||
| 4755 | if (IsAutocompleteOff(formElement)) { | |||
| 4756 | aKey.Truncate(); | |||
| 4757 | return; | |||
| 4758 | } | |||
| 4759 | ||||
| 4760 | // Append the form number, if this is a parser inserted control, or | |||
| 4761 | // the index of the form in the document otherwise. | |||
| 4762 | bool appendedForm = false; | |||
| 4763 | if (parserInserted) { | |||
| 4764 | MOZ_ASSERT(formElement->GetFormNumberForStateKey() != -1,do { static_assert( mozilla::detail::AssertionConditionType< decltype(formElement->GetFormNumberForStateKey() != -1)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(formElement->GetFormNumberForStateKey() != -1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1" " (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4766 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1" ") (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")"); do { MOZ_CrashSequence(__null, 4766); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4765 | "when generating a state key for a parser inserted form "do { static_assert( mozilla::detail::AssertionConditionType< decltype(formElement->GetFormNumberForStateKey() != -1)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(formElement->GetFormNumberForStateKey() != -1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1" " (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4766 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1" ") (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")"); do { MOZ_CrashSequence(__null, 4766); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 4766 | "control we should have a parser inserted <form> element")do { static_assert( mozilla::detail::AssertionConditionType< decltype(formElement->GetFormNumberForStateKey() != -1)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(formElement->GetFormNumberForStateKey() != -1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1" " (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4766 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1" ") (" "when generating a state key for a parser inserted form " "control we should have a parser inserted <form> element" ")"); do { MOZ_CrashSequence(__null, 4766); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4767 | KeyAppendString("fp"_ns, aKey); | |||
| 4768 | KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey); | |||
| 4769 | appendedForm = true; | |||
| 4770 | } else { | |||
| 4771 | KeyAppendString("fn"_ns, aKey); | |||
| 4772 | int32_t index = htmlForms->IndexOf(formElement, false); | |||
| 4773 | if (index <= -1) { | |||
| 4774 | // | |||
| 4775 | // XXX HACK this uses some state that was dumped into the document | |||
| 4776 | // specifically to fix bug 138892. What we are trying to do is | |||
| 4777 | // *guess* which form this control's state is found in, with the | |||
| 4778 | // highly likely guess that the highest form parsed so far is the | |||
| 4779 | // one. This code should not be on trunk, only branch. | |||
| 4780 | // | |||
| 4781 | index = htmlDoc->GetNumFormsSynchronous() - 1; | |||
| 4782 | } | |||
| 4783 | if (index > -1) { | |||
| 4784 | KeyAppendInt(index, aKey); | |||
| 4785 | appendedForm = true; | |||
| 4786 | } | |||
| 4787 | } | |||
| 4788 | ||||
| 4789 | if (appendedForm) { | |||
| 4790 | // Append the index of the control in the form | |||
| 4791 | int32_t index = formElement->IndexOfContent(aContent); | |||
| 4792 | ||||
| 4793 | if (index > -1) { | |||
| 4794 | KeyAppendInt(index, aKey); | |||
| 4795 | generatedUniqueKey = true; | |||
| 4796 | } | |||
| 4797 | } | |||
| 4798 | ||||
| 4799 | // Append the form name | |||
| 4800 | nsAutoString formName; | |||
| 4801 | formElement->GetAttr(nsGkAtoms::name, formName); | |||
| 4802 | KeyAppendString(formName, aKey); | |||
| 4803 | } else { | |||
| 4804 | // Not in a form. Append the control number, if this is a parser | |||
| 4805 | // inserted control, or the index of the control in the document | |||
| 4806 | // otherwise. | |||
| 4807 | if (parserInserted) { | |||
| 4808 | KeyAppendString("dp"_ns, aKey); | |||
| 4809 | KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(), | |||
| 4810 | aKey); | |||
| 4811 | generatedUniqueKey = true; | |||
| 4812 | } else { | |||
| 4813 | KeyAppendString("dn"_ns, aKey); | |||
| 4814 | int32_t index = htmlFormControls->IndexOf(aContent, true); | |||
| 4815 | if (index > -1) { | |||
| 4816 | KeyAppendInt(index, aKey); | |||
| 4817 | generatedUniqueKey = true; | |||
| 4818 | } | |||
| 4819 | } | |||
| 4820 | ||||
| 4821 | // Append the control name | |||
| 4822 | nsAutoString name; | |||
| 4823 | aContent->AsElement()->GetAttr(nsGkAtoms::name, name); | |||
| 4824 | KeyAppendString(name, aKey); | |||
| 4825 | } | |||
| 4826 | } | |||
| 4827 | } | |||
| 4828 | ||||
| 4829 | if (!generatedUniqueKey) { | |||
| 4830 | // Either we didn't have a form control or we aren't in an HTML document so | |||
| 4831 | // we can't figure out form info. Append the tag name if it's an element | |||
| 4832 | // to avoid restoring state for one type of element on another type. | |||
| 4833 | if (aContent->IsElement()) { | |||
| 4834 | KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()), | |||
| 4835 | aKey); | |||
| 4836 | } else { | |||
| 4837 | // Append a character that is not "d" or "f" to disambiguate from | |||
| 4838 | // the case when we were a form control in an HTML document. | |||
| 4839 | KeyAppendString("o"_ns, aKey); | |||
| 4840 | } | |||
| 4841 | ||||
| 4842 | // Now start at aContent and append the indices of it and all its ancestors | |||
| 4843 | // in their containers. That should at least pin down its position in the | |||
| 4844 | // DOM... | |||
| 4845 | nsINode* parent = aContent->GetParentNode(); | |||
| 4846 | nsINode* content = aContent; | |||
| 4847 | while (parent) { | |||
| 4848 | if (content->IsShadowRoot()) { | |||
| 4849 | KeyAppendString("s"_ns, aKey); | |||
| 4850 | } else { | |||
| 4851 | KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey); | |||
| 4852 | } | |||
| 4853 | content = parent; | |||
| 4854 | parent = content->GetParentOrShadowHostNode(); | |||
| 4855 | } | |||
| 4856 | } | |||
| 4857 | } | |||
| 4858 | ||||
| 4859 | // static | |||
| 4860 | nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) { | |||
| 4861 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4861); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 4861); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4862 | ||||
| 4863 | // As opposed to SubjectPrincipal(), we do in fact assume that | |||
| 4864 | // we're in a realm here; anyone who calls this function in | |||
| 4865 | // situations where that's not the case is doing it wrong. | |||
| 4866 | JS::Realm* realm = js::GetContextRealm(aCx); | |||
| 4867 | MOZ_ASSERT(realm)do { static_assert( mozilla::detail::AssertionConditionType< decltype(realm)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(realm))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("realm", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")") ; do { MOZ_CrashSequence(__null, 4867); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4868 | ||||
| 4869 | JSPrincipals* principals = JS::GetRealmPrincipals(realm); | |||
| 4870 | return nsJSPrincipals::get(principals); | |||
| 4871 | } | |||
| 4872 | ||||
| 4873 | // static | |||
| 4874 | nsIPrincipal* nsContentUtils::SubjectPrincipal() { | |||
| 4875 | MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInitialized()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4875); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence (__null, 4875); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4876 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4876); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 4876); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 4877 | JSContext* cx = GetCurrentJSContext(); | |||
| 4878 | if (!cx) { | |||
| 4879 | MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__ ((nomerge)) ::abort(); } while (false); } while (false) | |||
| 4880 | "Accessing the Subject Principal without an AutoJSAPI on the stack is "do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__ ((nomerge)) ::abort(); } while (false); } while (false) | |||
| 4881 | "forbidden")do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__ ((nomerge)) ::abort(); } while (false); } while (false); | |||
| 4882 | } | |||
| 4883 | ||||
| 4884 | JS::Realm* realm = js::GetContextRealm(cx); | |||
| 4885 | ||||
| 4886 | // When an AutoJSAPI is instantiated, we are in a null realm until the | |||
| 4887 | // first JSAutoRealm, which is kind of a purgatory as far as permissions | |||
| 4888 | // go. It would be nice to just hard-abort if somebody does a security check | |||
| 4889 | // in this purgatory zone, but that would be too fragile, since it could be | |||
| 4890 | // triggered by random IsCallerChrome() checks 20-levels deep. | |||
| 4891 | // | |||
| 4892 | // So we want to return _something_ here - and definitely not the System | |||
| 4893 | // Principal, since that would make an AutoJSAPI a very dangerous thing to | |||
| 4894 | // instantiate. | |||
| 4895 | // | |||
| 4896 | // The natural thing to return is a null principal. Ideally, we'd return a | |||
| 4897 | // different null principal each time, to avoid any unexpected interactions | |||
| 4898 | // when the principal accidentally gets inherited somewhere. But | |||
| 4899 | // SubjectPrincipal doesn't return strong references, so there's no way to | |||
| 4900 | // sanely manage the lifetime of multiple null principals. | |||
| 4901 | // | |||
| 4902 | // So we use a singleton null principal. To avoid it being accidentally | |||
| 4903 | // inherited and becoming a "real" subject or object principal, we do a | |||
| 4904 | // release-mode assert during realm creation against using this principal on | |||
| 4905 | // an actual global. | |||
| 4906 | if (!realm) { | |||
| 4907 | return sNullSubjectPrincipal; | |||
| 4908 | } | |||
| 4909 | ||||
| 4910 | return SubjectPrincipal(cx); | |||
| 4911 | } | |||
| 4912 | ||||
| 4913 | // static | |||
| 4914 | nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) { | |||
| 4915 | #ifdef DEBUG1 | |||
| 4916 | JS::AssertObjectBelongsToCurrentThread(aObj); | |||
| 4917 | #endif | |||
| 4918 | ||||
| 4919 | MOZ_DIAGNOSTIC_ASSERT(!js::IsCrossCompartmentWrapper(aObj))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!js::IsCrossCompartmentWrapper(aObj))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!js::IsCrossCompartmentWrapper (aObj)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!js::IsCrossCompartmentWrapper(aObj)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 4919); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)" ")"); do { MOZ_CrashSequence(__null, 4919); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 4920 | ||||
| 4921 | JS::Realm* realm = js::GetNonCCWObjectRealm(aObj); | |||
| 4922 | JSPrincipals* principals = JS::GetRealmPrincipals(realm); | |||
| 4923 | return nsJSPrincipals::get(principals); | |||
| 4924 | } | |||
| 4925 | ||||
| 4926 | // static | |||
| 4927 | nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult, | |||
| 4928 | const nsAString& aSpec, | |||
| 4929 | Document* aDocument, | |||
| 4930 | nsIURI* aBaseURI) { | |||
| 4931 | if (aDocument) { | |||
| 4932 | return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(), | |||
| 4933 | aBaseURI); | |||
| 4934 | } | |||
| 4935 | return NS_NewURI(aResult, aSpec, nullptr, aBaseURI); | |||
| 4936 | } | |||
| 4937 | ||||
| 4938 | // static | |||
| 4939 | bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) { | |||
| 4940 | const uint32_t len = aAtom->GetLength(); | |||
| 4941 | if (!len) { | |||
| 4942 | return false; | |||
| 4943 | } | |||
| 4944 | const char16_t* name = aAtom->GetUTF16String(); | |||
| 4945 | uint32_t i = 0; | |||
| 4946 | while (i < len) { | |||
| 4947 | if (name[i] == aChar) { | |||
| 4948 | return true; | |||
| 4949 | } | |||
| 4950 | i++; | |||
| 4951 | } | |||
| 4952 | return false; | |||
| 4953 | } | |||
| 4954 | ||||
| 4955 | // static | |||
| 4956 | bool nsContentUtils::IsNameWithDash(nsAtom* aName) { | |||
| 4957 | // A valid custom element name is a sequence of characters name which | |||
| 4958 | // must match the PotentialCustomElementName production: | |||
| 4959 | // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)* | |||
| 4960 | const char16_t* name = aName->GetUTF16String(); | |||
| 4961 | uint32_t len = aName->GetLength(); | |||
| 4962 | bool hasDash = false; | |||
| 4963 | ||||
| 4964 | // A string name is a valid custom element name if all of the following are | |||
| 4965 | // true: | |||
| 4966 | ||||
| 4967 | // name's 0th code point is an ASCII lower alpha; | |||
| 4968 | if (!len || name[0] < 'a' || name[0] > 'z') { | |||
| 4969 | return false; | |||
| 4970 | } | |||
| 4971 | ||||
| 4972 | uint32_t i = 1; | |||
| 4973 | while (i < len) { | |||
| 4974 | // name does not contain any ASCII upper alphas | |||
| 4975 | if (name[i] >= 'A' && name[i] <= 'Z') { | |||
| 4976 | return false; | |||
| 4977 | } | |||
| 4978 | ||||
| 4979 | // name is a valid element local name; | |||
| 4980 | // | |||
| 4981 | // // https://dom.spec.whatwg.org/#valid-element-local-name | |||
| 4982 | // Step 2.1. | |||
| 4983 | // If name contains ASCII whitespace, U+0000 NULL, U+002F (/), or U+003E | |||
| 4984 | // (>), then return false. | |||
| 4985 | // | |||
| 4986 | // ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or | |||
| 4987 | // U+0020 SPACE. | |||
| 4988 | if (name[i] == 0x0000 || // null | |||
| 4989 | name[i] == 0x0009 || // tab | |||
| 4990 | name[i] == 0x000A || // newline | |||
| 4991 | name[i] == 0x000C || // form feed | |||
| 4992 | name[i] == 0x000D || // carriage return | |||
| 4993 | name[i] == 0x0020 || // space | |||
| 4994 | name[i] == 0x002F || // / | |||
| 4995 | name[i] == 0x003E) { // > | |||
| 4996 | return false; | |||
| 4997 | } | |||
| 4998 | ||||
| 4999 | if (name[i] == '-') { | |||
| 5000 | hasDash = true; | |||
| 5001 | } | |||
| 5002 | ||||
| 5003 | i++; | |||
| 5004 | } | |||
| 5005 | return hasDash; | |||
| 5006 | } | |||
| 5007 | ||||
| 5008 | // static | |||
| 5009 | bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) { | |||
| 5010 | // Allow non-dashed names in XUL for XBL to Custom Element migrations. | |||
| 5011 | if (aNameSpaceID == kNameSpaceID_XUL8) { | |||
| 5012 | return true; | |||
| 5013 | } | |||
| 5014 | ||||
| 5015 | bool hasDash = IsNameWithDash(aName); | |||
| 5016 | if (!hasDash) { | |||
| 5017 | return false; | |||
| 5018 | } | |||
| 5019 | ||||
| 5020 | // The custom element name must not be one of the following values: | |||
| 5021 | // annotation-xml | |||
| 5022 | // color-profile | |||
| 5023 | // font-face | |||
| 5024 | // font-face-src | |||
| 5025 | // font-face-uri | |||
| 5026 | // font-face-format | |||
| 5027 | // font-face-name | |||
| 5028 | // missing-glyph | |||
| 5029 | return aName != nsGkAtoms::annotation_xml && | |||
| 5030 | aName != nsGkAtoms::color_profile && aName != nsGkAtoms::font_face && | |||
| 5031 | aName != nsGkAtoms::font_face_src && | |||
| 5032 | aName != nsGkAtoms::font_face_uri && | |||
| 5033 | aName != nsGkAtoms::font_face_format && | |||
| 5034 | aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph; | |||
| 5035 | } | |||
| 5036 | ||||
| 5037 | bool nsContentUtils::IsValidShadowHostName(nsAtom* aName, | |||
| 5038 | uint32_t aNameSpaceID) { | |||
| 5039 | return IsCustomElementName(aName, aNameSpaceID) || | |||
| 5040 | aName == nsGkAtoms::article || aName == nsGkAtoms::aside || | |||
| 5041 | aName == nsGkAtoms::blockquote || aName == nsGkAtoms::body || | |||
| 5042 | aName == nsGkAtoms::div || aName == nsGkAtoms::footer || | |||
| 5043 | aName == nsGkAtoms::h1 || aName == nsGkAtoms::h2 || | |||
| 5044 | aName == nsGkAtoms::h3 || aName == nsGkAtoms::h4 || | |||
| 5045 | aName == nsGkAtoms::h5 || aName == nsGkAtoms::h6 || | |||
| 5046 | aName == nsGkAtoms::header || aName == nsGkAtoms::main || | |||
| 5047 | aName == nsGkAtoms::nav || aName == nsGkAtoms::p || | |||
| 5048 | aName == nsGkAtoms::section || aName == nsGkAtoms::span; | |||
| 5049 | } | |||
| 5050 | ||||
| 5051 | // static | |||
| 5052 | nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName, | |||
| 5053 | bool aNamespaceAware, | |||
| 5054 | const char16_t** aColon) { | |||
| 5055 | const char* colon = nullptr; | |||
| 5056 | const char16_t* begin = aQualifiedName.BeginReading(); | |||
| 5057 | const char16_t* end = aQualifiedName.EndReading(); | |||
| 5058 | ||||
| 5059 | int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin), | |||
| 5060 | reinterpret_cast<const char*>(end), | |||
| 5061 | aNamespaceAware, &colon); | |||
| 5062 | ||||
| 5063 | if (!result) { | |||
| 5064 | if (aColon) { | |||
| 5065 | *aColon = reinterpret_cast<const char16_t*>(colon); | |||
| 5066 | } | |||
| 5067 | ||||
| 5068 | return NS_OK; | |||
| 5069 | } | |||
| 5070 | ||||
| 5071 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5072 | } | |||
| 5073 | ||||
| 5074 | static inline bool IsValidRestrictedContinuation(char16_t c) { | |||
| 5075 | return mozilla::IsAsciiAlpha(c) || mozilla::IsAsciiDigit(c) || c == '-' || | |||
| 5076 | c == '.' || c == ':' || c == '_' || c >= 0x80; | |||
| 5077 | } | |||
| 5078 | ||||
| 5079 | // static | |||
| 5080 | // https://dom.spec.whatwg.org/#valid-element-local-name | |||
| 5081 | // Two paths: | |||
| 5082 | // 1. Starts with [A-Za-z]: continuation can be any char except | |||
| 5083 | // null/whitespace/>/'/' | |||
| 5084 | // 2. Starts with [:_>=0x80]: continuation must be [A-Za-z0-9-.:_>=0x80] | |||
| 5085 | bool nsContentUtils::IsValidElementLocalName(const nsAString& aName) { | |||
| 5086 | if (aName.IsEmpty()) { | |||
| 5087 | return false; | |||
| 5088 | } | |||
| 5089 | ||||
| 5090 | const char16_t* ptr = aName.BeginReading(); | |||
| 5091 | const char16_t* end = aName.EndReading(); | |||
| 5092 | char16_t first = *ptr; | |||
| 5093 | ||||
| 5094 | if (mozilla::IsAsciiAlpha(first)) { | |||
| 5095 | // Path 1: ASCII alpha start - any continuation except forbidden chars. | |||
| 5096 | for (++ptr; ptr < end; ++ptr) { | |||
| 5097 | char16_t c = *ptr; | |||
| 5098 | if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') { | |||
| 5099 | return false; | |||
| 5100 | } | |||
| 5101 | } | |||
| 5102 | return true; | |||
| 5103 | } | |||
| 5104 | ||||
| 5105 | if (first == ':' || first == '_' || first >= 0x80) { | |||
| 5106 | // Path 2: Colon, underscore, or non-ASCII start - restricted continuation. | |||
| 5107 | for (++ptr; ptr < end; ++ptr) { | |||
| 5108 | if (!IsValidRestrictedContinuation(*ptr)) { | |||
| 5109 | return false; | |||
| 5110 | } | |||
| 5111 | } | |||
| 5112 | return true; | |||
| 5113 | } | |||
| 5114 | ||||
| 5115 | // Starting with anything else (e.g., digits, other ASCII) is invalid. | |||
| 5116 | return false; | |||
| 5117 | } | |||
| 5118 | ||||
| 5119 | // static | |||
| 5120 | // https://dom.spec.whatwg.org/#valid-attribute-local-name | |||
| 5121 | bool nsContentUtils::IsValidAttributeLocalName(const nsAString& aName) { | |||
| 5122 | if (aName.IsEmpty()) { | |||
| 5123 | return false; | |||
| 5124 | } | |||
| 5125 | for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading(); | |||
| 5126 | ptr++) { | |||
| 5127 | char16_t c = *ptr; | |||
| 5128 | if (c == 0 || IsHTMLWhitespace(c) || c == '>' || c == '/' || c == '=') { | |||
| 5129 | return false; | |||
| 5130 | } | |||
| 5131 | } | |||
| 5132 | return true; | |||
| 5133 | } | |||
| 5134 | ||||
| 5135 | // static | |||
| 5136 | // https://dom.spec.whatwg.org/#valid-namespace-prefix | |||
| 5137 | bool nsContentUtils::IsValidNamespacePrefix(const nsAString& aPrefix) { | |||
| 5138 | // Empty prefix is valid (means no prefix). | |||
| 5139 | if (aPrefix.IsEmpty()) { | |||
| 5140 | return true; | |||
| 5141 | } | |||
| 5142 | for (const char16_t* ptr = aPrefix.BeginReading(); ptr < aPrefix.EndReading(); | |||
| 5143 | ptr++) { | |||
| 5144 | char16_t c = *ptr; | |||
| 5145 | if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') { | |||
| 5146 | return false; | |||
| 5147 | } | |||
| 5148 | } | |||
| 5149 | return true; | |||
| 5150 | } | |||
| 5151 | ||||
| 5152 | // static | |||
| 5153 | // https://dom.spec.whatwg.org/#valid-doctype-name | |||
| 5154 | bool nsContentUtils::IsValidDoctypeName(const nsAString& aName) { | |||
| 5155 | // Empty doctype name is valid per spec (it just can't contain bad chars). | |||
| 5156 | for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading(); | |||
| 5157 | ptr++) { | |||
| 5158 | char16_t c = *ptr; | |||
| 5159 | if (c == 0 || IsHTMLWhitespace(c) || c == '>') { | |||
| 5160 | return false; | |||
| 5161 | } | |||
| 5162 | } | |||
| 5163 | return true; | |||
| 5164 | } | |||
| 5165 | ||||
| 5166 | // static | |||
| 5167 | // https://dom.spec.whatwg.org/#validate-and-extract | |||
| 5168 | // This implements only the validation and parsing portion of the algorithm. | |||
| 5169 | // Namespace resolution (steps involving namespace lookups) is handled by | |||
| 5170 | // callers. | |||
| 5171 | nsresult nsContentUtils::ParseQualifiedNameRelaxed( | |||
| 5172 | const nsAString& aQualifiedName, uint16_t aNodeType, | |||
| 5173 | const char16_t** aColon, const char16_t** aLocalNameEnd) { | |||
| 5174 | if (aColon) { | |||
| 5175 | *aColon = nullptr; | |||
| 5176 | } | |||
| 5177 | if (aLocalNameEnd) { | |||
| 5178 | *aLocalNameEnd = nullptr; | |||
| 5179 | } | |||
| 5180 | ||||
| 5181 | if (aQualifiedName.IsEmpty()) { | |||
| 5182 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5183 | } | |||
| 5184 | ||||
| 5185 | const char16_t* begin = aQualifiedName.BeginReading(); | |||
| 5186 | const char16_t* end = aQualifiedName.EndReading(); | |||
| 5187 | const char16_t* firstColon = nullptr; | |||
| 5188 | ||||
| 5189 | for (const char16_t* ptr = begin; ptr < end; ptr++) { | |||
| 5190 | if (*ptr == ':') { | |||
| 5191 | firstColon = ptr; | |||
| 5192 | break; | |||
| 5193 | } | |||
| 5194 | } | |||
| 5195 | ||||
| 5196 | if (firstColon) { | |||
| 5197 | nsDependentSubstring prefix(begin, firstColon); | |||
| 5198 | ||||
| 5199 | if (prefix.IsEmpty()) { | |||
| 5200 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5201 | } | |||
| 5202 | ||||
| 5203 | if (!IsValidNamespacePrefix(prefix)) { | |||
| 5204 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5205 | } | |||
| 5206 | ||||
| 5207 | // Local name is everything after the first colon. | |||
| 5208 | nsDependentSubstring localName(firstColon + 1, end); | |||
| 5209 | ||||
| 5210 | // Local name must not be empty. | |||
| 5211 | if (localName.IsEmpty()) { | |||
| 5212 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5213 | } | |||
| 5214 | ||||
| 5215 | // Validate local name based on node type. | |||
| 5216 | if (aNodeType == nsINode::ATTRIBUTE_NODE) { | |||
| 5217 | if (!IsValidAttributeLocalName(localName)) { | |||
| 5218 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5219 | } | |||
| 5220 | } else { | |||
| 5221 | if (!IsValidElementLocalName(localName)) { | |||
| 5222 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5223 | } | |||
| 5224 | } | |||
| 5225 | ||||
| 5226 | if (aColon) { | |||
| 5227 | *aColon = firstColon; | |||
| 5228 | } | |||
| 5229 | if (aLocalNameEnd) { | |||
| 5230 | *aLocalNameEnd = end; | |||
| 5231 | } | |||
| 5232 | } else { | |||
| 5233 | // No colon, the whole string is the local name. | |||
| 5234 | if (aNodeType == nsINode::ATTRIBUTE_NODE) { | |||
| 5235 | if (!IsValidAttributeLocalName(aQualifiedName)) { | |||
| 5236 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5237 | } | |||
| 5238 | } else { | |||
| 5239 | if (!IsValidElementLocalName(aQualifiedName)) { | |||
| 5240 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
| 5241 | } | |||
| 5242 | } | |||
| 5243 | } | |||
| 5244 | ||||
| 5245 | return NS_OK; | |||
| 5246 | } | |||
| 5247 | ||||
| 5248 | // static | |||
| 5249 | nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver, | |||
| 5250 | const nsString& aQName, int32_t* aNamespace, | |||
| 5251 | nsAtom** aLocalName) { | |||
| 5252 | const char16_t* colon; | |||
| 5253 | nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon); | |||
| 5254 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5254); return rv; } } while (false); | |||
| 5255 | ||||
| 5256 | if (colon) { | |||
| 5257 | const char16_t* end; | |||
| 5258 | aQName.EndReading(end); | |||
| 5259 | nsAutoString nameSpace; | |||
| 5260 | rv = aNamespaceResolver->LookupNamespaceURIInternal( | |||
| 5261 | Substring(aQName.get(), colon), nameSpace); | |||
| 5262 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5262); return rv; } } while (false); | |||
| 5263 | ||||
| 5264 | *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID( | |||
| 5265 | nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc())); | |||
| 5266 | if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE; | |||
| 5267 | ||||
| 5268 | *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take(); | |||
| 5269 | } else { | |||
| 5270 | *aNamespace = kNameSpaceID_None; | |||
| 5271 | *aLocalName = NS_AtomizeMainThread(aQName).take(); | |||
| 5272 | } | |||
| 5273 | NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(aLocalName)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aLocalName" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5273 ); return NS_ERROR_OUT_OF_MEMORY; } } while (false); | |||
| 5274 | return NS_OK; | |||
| 5275 | } | |||
| 5276 | ||||
| 5277 | // static | |||
| 5278 | nsresult nsContentUtils::GetNodeInfoFromQName( | |||
| 5279 | const nsAString& aNamespaceURI, const nsAString& aQualifiedName, | |||
| 5280 | nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType, | |||
| 5281 | mozilla::dom::NodeInfo** aNodeInfo) { | |||
| 5282 | const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName); | |||
| 5283 | const char16_t* colon; | |||
| 5284 | const char16_t* localNameEnd; | |||
| 5285 | nsresult rv = nsContentUtils::ParseQualifiedNameRelaxed( | |||
| 5286 | qName, aNodeType, &colon, &localNameEnd); | |||
| 5287 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5287); return rv; } } while (false); | |||
| 5288 | ||||
| 5289 | int32_t nsID; | |||
| 5290 | nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID); | |||
| 5291 | if (colon) { | |||
| 5292 | RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon)); | |||
| 5293 | ||||
| 5294 | rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, localNameEnd), | |||
| 5295 | prefix, nsID, aNodeType, aNodeInfo); | |||
| 5296 | } else { | |||
| 5297 | rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType, | |||
| 5298 | aNodeInfo); | |||
| 5299 | } | |||
| 5300 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5300); return rv; } } while (false); | |||
| 5301 | ||||
| 5302 | return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(), | |||
| 5303 | (*aNodeInfo)->GetPrefixAtom(), | |||
| 5304 | (*aNodeInfo)->NamespaceID()) | |||
| 5305 | ? NS_OK | |||
| 5306 | : NS_ERROR_DOM_NAMESPACE_ERR; | |||
| 5307 | } | |||
| 5308 | ||||
| 5309 | // static | |||
| 5310 | void nsContentUtils::SplitExpatName(const char16_t* aExpatName, | |||
| 5311 | nsAtom** aPrefix, nsAtom** aLocalName, | |||
| 5312 | int32_t* aNameSpaceID) { | |||
| 5313 | /** | |||
| 5314 | * Expat can send the following: | |||
| 5315 | * localName | |||
| 5316 | * namespaceURI<separator>localName | |||
| 5317 | * namespaceURI<separator>localName<separator>prefix | |||
| 5318 | * | |||
| 5319 | * and we use 0xFFFF for the <separator>. | |||
| 5320 | * | |||
| 5321 | */ | |||
| 5322 | ||||
| 5323 | const char16_t* uriEnd = nullptr; | |||
| 5324 | const char16_t* nameEnd = nullptr; | |||
| 5325 | const char16_t* pos; | |||
| 5326 | for (pos = aExpatName; *pos; ++pos) { | |||
| 5327 | if (*pos == 0xFFFF) { | |||
| 5328 | if (uriEnd) { | |||
| 5329 | nameEnd = pos; | |||
| 5330 | } else { | |||
| 5331 | uriEnd = pos; | |||
| 5332 | } | |||
| 5333 | } | |||
| 5334 | } | |||
| 5335 | ||||
| 5336 | const char16_t* nameStart; | |||
| 5337 | if (uriEnd) { | |||
| 5338 | nsNameSpaceManager::GetInstance()->RegisterNameSpace( | |||
| 5339 | nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID); | |||
| 5340 | ||||
| 5341 | nameStart = (uriEnd + 1); | |||
| 5342 | if (nameEnd) { | |||
| 5343 | const char16_t* prefixStart = nameEnd + 1; | |||
| 5344 | *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take(); | |||
| 5345 | } else { | |||
| 5346 | nameEnd = pos; | |||
| 5347 | *aPrefix = nullptr; | |||
| 5348 | } | |||
| 5349 | } else { | |||
| 5350 | *aNameSpaceID = kNameSpaceID_None; | |||
| 5351 | nameStart = aExpatName; | |||
| 5352 | nameEnd = pos; | |||
| 5353 | *aPrefix = nullptr; | |||
| 5354 | } | |||
| 5355 | *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take(); | |||
| 5356 | } | |||
| 5357 | ||||
| 5358 | // static | |||
| 5359 | PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) { | |||
| 5360 | Document* doc = aContent->GetComposedDoc(); | |||
| 5361 | if (!doc) { | |||
| 5362 | return nullptr; | |||
| 5363 | } | |||
| 5364 | return doc->GetPresShell(); | |||
| 5365 | } | |||
| 5366 | ||||
| 5367 | // static | |||
| 5368 | nsPresContext* nsContentUtils::GetContextForContent( | |||
| 5369 | const nsIContent* aContent) { | |||
| 5370 | PresShell* presShell = GetPresShellForContent(aContent); | |||
| 5371 | if (!presShell) { | |||
| 5372 | return nullptr; | |||
| 5373 | } | |||
| 5374 | return presShell->GetPresContext(); | |||
| 5375 | } | |||
| 5376 | ||||
| 5377 | // static | |||
| 5378 | bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) { | |||
| 5379 | if (!aLoadGroup) { | |||
| 5380 | return false; | |||
| 5381 | } | |||
| 5382 | // See duplicated code in Document::Reset/ResetToURI | |||
| 5383 | bool isPrivate = false; | |||
| 5384 | nsCOMPtr<nsIInterfaceRequestor> callbacks; | |||
| 5385 | aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); | |||
| 5386 | if (callbacks) { | |||
| 5387 | nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); | |||
| 5388 | isPrivate = loadContext && loadContext->UsePrivateBrowsing(); | |||
| 5389 | } | |||
| 5390 | return isPrivate; | |||
| 5391 | } | |||
| 5392 | ||||
| 5393 | // FIXME(emilio): This is (effectively) almost but not quite the same as | |||
| 5394 | // Document::ShouldLoadImages(), which one is right? | |||
| 5395 | bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) { | |||
| 5396 | if (!aDocument) { | |||
| 5397 | return false; | |||
| 5398 | } | |||
| 5399 | if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() || | |||
| 5400 | aDocument->IsStaticDocument()) { | |||
| 5401 | return false; | |||
| 5402 | } | |||
| 5403 | nsCOMPtr<nsPIDOMWindowInner> win = | |||
| 5404 | do_QueryInterface(aDocument->GetScopeObject()); | |||
| 5405 | return !win || !win->GetDocShell(); | |||
| 5406 | } | |||
| 5407 | ||||
| 5408 | imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) { | |||
| 5409 | NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr)do { if ((__builtin_expect(!!(!(!DocumentInactiveForImageLoads (aDoc))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!DocumentInactiveForImageLoads(aDoc)" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5409); return nullptr; } } while (false); | |||
| 5410 | ||||
| 5411 | if (!aDoc) { | |||
| 5412 | return imgLoader::NormalLoader(); | |||
| 5413 | } | |||
| 5414 | const bool isPrivate = aDoc->IsInPrivateBrowsing(); | |||
| 5415 | return isPrivate ? imgLoader::PrivateBrowsingLoader() | |||
| 5416 | : imgLoader::NormalLoader(); | |||
| 5417 | } | |||
| 5418 | ||||
| 5419 | // static | |||
| 5420 | imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel, | |||
| 5421 | Document* aContext) { | |||
| 5422 | NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr)do { if ((__builtin_expect(!!(!(!DocumentInactiveForImageLoads (aContext))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!DocumentInactiveForImageLoads(aContext)" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5422); return nullptr; } } while (false); | |||
| 5423 | ||||
| 5424 | if (!aChannel) { | |||
| 5425 | return imgLoader::NormalLoader(); | |||
| 5426 | } | |||
| 5427 | return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader() | |||
| 5428 | : imgLoader::NormalLoader(); | |||
| 5429 | } | |||
| 5430 | ||||
| 5431 | // static | |||
| 5432 | int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) { | |||
| 5433 | switch (aMode) { | |||
| 5434 | case CORS_ANONYMOUS: | |||
| 5435 | return imgILoader::LOAD_CORS_ANONYMOUS; | |||
| 5436 | case CORS_USE_CREDENTIALS: | |||
| 5437 | return imgILoader::LOAD_CORS_USE_CREDENTIALS; | |||
| 5438 | default: | |||
| 5439 | return 0; | |||
| 5440 | } | |||
| 5441 | } | |||
| 5442 | ||||
| 5443 | // static | |||
| 5444 | nsresult nsContentUtils::LoadImage( | |||
| 5445 | nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument, | |||
| 5446 | nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID, | |||
| 5447 | nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver, | |||
| 5448 | int32_t aLoadFlags, const nsAString& initiatorType, | |||
| 5449 | imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType, | |||
| 5450 | bool aUseUrgentStartForChannel, bool aLinkPreload, | |||
| 5451 | uint64_t aEarlyHintPreloaderId, | |||
| 5452 | mozilla::dom::FetchPriority aFetchPriority) { | |||
| 5453 | MOZ_ASSERT(aURI, "Must have a URI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "Must have a URI" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5453); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { MOZ_CrashSequence (__null, 5453); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 5454 | MOZ_ASSERT(aContext, "Must have a context")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContext" " (" "Must have a context" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5454 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") (" "Must have a context" ")"); do { MOZ_CrashSequence(__null, 5454); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5455 | MOZ_ASSERT(aLoadingDocument, "Must have a document")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadingDocument)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadingDocument))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadingDocument" " (" "Must have a document" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument" ") (" "Must have a document" ")"); do { MOZ_CrashSequence(__null , 5455); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 5456 | MOZ_ASSERT(aLoadingPrincipal, "Must have a principal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal" " (" "Must have a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Must have a principal" ")"); do { MOZ_CrashSequence(__null , 5456); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 5457 | MOZ_ASSERT(aRequest, "Null out param")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aRequest)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aRequest))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest" " (" "Null out param" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5457 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") (" "Null out param" ")"); do { MOZ_CrashSequence(__null, 5457); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5458 | ||||
| 5459 | imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument); | |||
| 5460 | if (!imgLoader) { | |||
| 5461 | // nothing we can do here | |||
| 5462 | return NS_ERROR_FAILURE; | |||
| 5463 | } | |||
| 5464 | ||||
| 5465 | nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup(); | |||
| 5466 | ||||
| 5467 | nsIURI* documentURI = aLoadingDocument->GetDocumentURI(); | |||
| 5468 | ||||
| 5469 | NS_ASSERTION(loadGroup || aLoadingDocument->IsSVGGlyphsDocument(),do { if (!(loadGroup || aLoadingDocument->IsSVGGlyphsDocument ())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Could not get loadgroup; onload may fire too early" , "loadGroup || aLoadingDocument->IsSVGGlyphsDocument()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5470); MOZ_PretendNoReturn(); } } while (0) | |||
| 5470 | "Could not get loadgroup; onload may fire too early")do { if (!(loadGroup || aLoadingDocument->IsSVGGlyphsDocument ())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Could not get loadgroup; onload may fire too early" , "loadGroup || aLoadingDocument->IsSVGGlyphsDocument()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5470); MOZ_PretendNoReturn(); } } while (0); | |||
| 5471 | ||||
| 5472 | // XXXbz using "documentURI" for the initialDocumentURI is not quite | |||
| 5473 | // right, but the best we can do here... | |||
| 5474 | return imgLoader->LoadImage(aURI, /* uri to load */ | |||
| 5475 | documentURI, /* initialDocumentURI */ | |||
| 5476 | aReferrerInfo, /* referrerInfo */ | |||
| 5477 | aLoadingPrincipal, /* loading principal */ | |||
| 5478 | aRequestContextID, /* request context ID */ | |||
| 5479 | loadGroup, /* loadgroup */ | |||
| 5480 | aObserver, /* imgINotificationObserver */ | |||
| 5481 | aContext, /* loading context */ | |||
| 5482 | aLoadingDocument, /* uniquification key */ | |||
| 5483 | aLoadFlags, /* load flags */ | |||
| 5484 | nullptr, /* cache key */ | |||
| 5485 | aContentPolicyType, /* content policy type */ | |||
| 5486 | initiatorType, /* the load initiator */ | |||
| 5487 | aUseUrgentStartForChannel, /* urgent-start flag */ | |||
| 5488 | aLinkPreload, /* <link preload> initiator */ | |||
| 5489 | aEarlyHintPreloaderId, aFetchPriority, aRequest); | |||
| 5490 | } | |||
| 5491 | ||||
| 5492 | // static | |||
| 5493 | already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent( | |||
| 5494 | nsIImageLoadingContent* aContent, imgIRequest** aRequest) { | |||
| 5495 | if (aRequest) { | |||
| 5496 | *aRequest = nullptr; | |||
| 5497 | } | |||
| 5498 | ||||
| 5499 | NS_ENSURE_TRUE(aContent, nullptr)do { if ((__builtin_expect(!!(!(aContent)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContent" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5499); return nullptr; } } while (false); | |||
| 5500 | ||||
| 5501 | nsCOMPtr<imgIRequest> imgRequest; | |||
| 5502 | aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, | |||
| 5503 | getter_AddRefs(imgRequest)); | |||
| 5504 | if (!imgRequest) { | |||
| 5505 | return nullptr; | |||
| 5506 | } | |||
| 5507 | ||||
| 5508 | nsCOMPtr<imgIContainer> imgContainer; | |||
| 5509 | imgRequest->GetImage(getter_AddRefs(imgContainer)); | |||
| 5510 | ||||
| 5511 | if (!imgContainer) { | |||
| 5512 | return nullptr; | |||
| 5513 | } | |||
| 5514 | ||||
| 5515 | if (aRequest) { | |||
| 5516 | // If the consumer wants the request, verify it has actually loaded | |||
| 5517 | // successfully. | |||
| 5518 | uint32_t imgStatus; | |||
| 5519 | imgRequest->GetImageStatus(&imgStatus); | |||
| 5520 | if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE && | |||
| 5521 | !(imgStatus & imgIRequest::STATUS_ERROR)) { | |||
| 5522 | imgRequest.swap(*aRequest); | |||
| 5523 | } | |||
| 5524 | } | |||
| 5525 | ||||
| 5526 | return imgContainer.forget(); | |||
| 5527 | } | |||
| 5528 | ||||
| 5529 | static bool IsLinkWithURI(const nsIContent& aContent) { | |||
| 5530 | const auto* element = Element::FromNode(aContent); | |||
| 5531 | if (!element || !element->IsLink()) { | |||
| 5532 | return false; | |||
| 5533 | } | |||
| 5534 | nsCOMPtr<nsIURI> absURI = element->GetHrefURI(); | |||
| 5535 | return !!absURI; | |||
| 5536 | } | |||
| 5537 | ||||
| 5538 | static bool HasImageRequest(nsIContent& aContent) { | |||
| 5539 | nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent)); | |||
| 5540 | if (!imageContent) { | |||
| 5541 | return false; | |||
| 5542 | } | |||
| 5543 | ||||
| 5544 | nsCOMPtr<imgIRequest> imgRequest; | |||
| 5545 | imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, | |||
| 5546 | getter_AddRefs(imgRequest)); | |||
| 5547 | ||||
| 5548 | // XXXbz It may be draggable even if the request resulted in an error. Why? | |||
| 5549 | // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did. | |||
| 5550 | return !!imgRequest; | |||
| 5551 | } | |||
| 5552 | ||||
| 5553 | static Maybe<bool> DraggableOverride(const nsIContent& aContent) { | |||
| 5554 | if (auto* el = nsGenericHTMLElement::FromNode(aContent)) { | |||
| 5555 | if (el->Draggable()) { | |||
| 5556 | return Some(true); | |||
| 5557 | } | |||
| 5558 | ||||
| 5559 | if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, | |||
| 5560 | nsGkAtoms::_false, eIgnoreCase)) { | |||
| 5561 | return Some(false); | |||
| 5562 | } | |||
| 5563 | } | |||
| 5564 | if (aContent.IsSVGElement()) { | |||
| 5565 | return Some(false); | |||
| 5566 | } | |||
| 5567 | return Nothing(); | |||
| 5568 | } | |||
| 5569 | ||||
| 5570 | // static | |||
| 5571 | bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) { | |||
| 5572 | MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { MOZ_CrashSequence(__null, 5572); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5573 | ||||
| 5574 | if (auto draggable = DraggableOverride(*aContent)) { | |||
| 5575 | return *draggable; | |||
| 5576 | } | |||
| 5577 | ||||
| 5578 | // special handling for content area image and link dragging | |||
| 5579 | return HasImageRequest(*aContent) || IsLinkWithURI(*aContent); | |||
| 5580 | } | |||
| 5581 | ||||
| 5582 | // static | |||
| 5583 | bool nsContentUtils::IsDraggableImage(nsIContent* aContent) { | |||
| 5584 | MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { MOZ_CrashSequence(__null, 5584); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5585 | return HasImageRequest(*aContent) && | |||
| 5586 | DraggableOverride(*aContent).valueOr(true); | |||
| 5587 | } | |||
| 5588 | ||||
| 5589 | // static | |||
| 5590 | bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) { | |||
| 5591 | MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { MOZ_CrashSequence(__null, 5591); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5592 | return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true); | |||
| 5593 | } | |||
| 5594 | ||||
| 5595 | // static | |||
| 5596 | nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo, | |||
| 5597 | nsAtom* aName, | |||
| 5598 | mozilla::dom::NodeInfo** aResult) { | |||
| 5599 | nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager(); | |||
| 5600 | ||||
| 5601 | *aResult = niMgr | |||
| 5602 | ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(), | |||
| 5603 | aNodeInfo->NodeType(), aNodeInfo->GetExtraName()) | |||
| 5604 | .take(); | |||
| 5605 | return NS_OK; | |||
| 5606 | } | |||
| 5607 | ||||
| 5608 | static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType, | |||
| 5609 | uint32_t aPerm, bool aExactHostMatch) { | |||
| 5610 | if (!aPrincipal) { | |||
| 5611 | // We always deny (i.e. don't allow) the permission if we don't have a | |||
| 5612 | // principal. | |||
| 5613 | return aPerm != nsIPermissionManager::ALLOW_ACTION; | |||
| 5614 | } | |||
| 5615 | ||||
| 5616 | nsCOMPtr<nsIPermissionManager> permMgr = | |||
| 5617 | components::PermissionManager::Service(); | |||
| 5618 | NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5618); return false; } } while (false); | |||
| 5619 | ||||
| 5620 | uint32_t perm; | |||
| 5621 | nsresult rv; | |||
| 5622 | if (aExactHostMatch) { | |||
| 5623 | rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
| 5624 | } else { | |||
| 5625 | rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
| 5626 | } | |||
| 5627 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5627); return false; } } while (false); | |||
| 5628 | ||||
| 5629 | return perm == aPerm; | |||
| 5630 | } | |||
| 5631 | ||||
| 5632 | bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, | |||
| 5633 | const nsACString& aType) { | |||
| 5634 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, | |||
| 5635 | false); | |||
| 5636 | } | |||
| 5637 | ||||
| 5638 | bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal, | |||
| 5639 | const nsACString& aType) { | |||
| 5640 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, | |||
| 5641 | false); | |||
| 5642 | } | |||
| 5643 | ||||
| 5644 | bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal, | |||
| 5645 | const nsACString& aType) { | |||
| 5646 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, | |||
| 5647 | true); | |||
| 5648 | } | |||
| 5649 | ||||
| 5650 | bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal, | |||
| 5651 | const nsACString& aType) { | |||
| 5652 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, | |||
| 5653 | true); | |||
| 5654 | } | |||
| 5655 | ||||
| 5656 | bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal, | |||
| 5657 | const nsACString& aType) { | |||
| 5658 | if (!aPrincipal) { | |||
| 5659 | return false; | |||
| 5660 | } | |||
| 5661 | ||||
| 5662 | nsCOMPtr<nsIPermissionManager> permMgr = | |||
| 5663 | components::PermissionManager::Service(); | |||
| 5664 | NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5664); return false; } } while (false); | |||
| 5665 | ||||
| 5666 | uint32_t perm; | |||
| 5667 | nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
| 5668 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5668); return false; } } while (false); | |||
| 5669 | ||||
| 5670 | return perm != nsIPermissionManager::UNKNOWN_ACTION; | |||
| 5671 | } | |||
| 5672 | ||||
| 5673 | static const char* gEventNames[] = {"event"}; | |||
| 5674 | static const char* gSVGEventNames[] = {"evt"}; | |||
| 5675 | // for b/w compat, the first name to onerror is still 'event', even though it | |||
| 5676 | // is actually the error message | |||
| 5677 | static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno", | |||
| 5678 | "error"}; | |||
| 5679 | ||||
| 5680 | // static | |||
| 5681 | void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName, | |||
| 5682 | bool aIsForWindow, uint32_t* aArgCount, | |||
| 5683 | const char*** aArgArray) { | |||
| 5684 | #define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names ; \ | |||
| 5685 | *aArgCount = sizeof(names) / sizeof(names[0]); \ | |||
| 5686 | *aArgArray = names; | |||
| 5687 | ||||
| 5688 | // JSEventHandler is what does the arg magic for onerror, and it does | |||
| 5689 | // not seem to take the namespace into account. So we let onerror in all | |||
| 5690 | // namespaces get the 3 arg names. | |||
| 5691 | if (aEventName == nsGkAtoms::onerror && aIsForWindow) { | |||
| 5692 | SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0]) ; *aArgArray = gOnErrorNames;; | |||
| 5693 | } else if (aNameSpaceID == kNameSpaceID_SVG9) { | |||
| 5694 | SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0 ]); *aArgArray = gSVGEventNames;; | |||
| 5695 | } else { | |||
| 5696 | SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray = gEventNames;; | |||
| 5697 | } | |||
| 5698 | } | |||
| 5699 | ||||
| 5700 | // Note: The list of content bundles in nsStringBundle.cpp should be updated | |||
| 5701 | // whenever entries are added or removed from this list. | |||
| 5702 | static const char* gPropertiesFiles[kPropertiesFileCount] = { | |||
| 5703 | // Must line up with the enum values in |PropertiesFile| enum. | |||
| 5704 | "chrome://global/locale/css.properties", | |||
| 5705 | "chrome://global/locale/xul.properties", | |||
| 5706 | "chrome://global/locale/layout_errors.properties", | |||
| 5707 | "chrome://global/locale/layout/HtmlForm.properties", | |||
| 5708 | "chrome://global/locale/printing.properties", | |||
| 5709 | "chrome://global/locale/dom/dom.properties", | |||
| 5710 | "chrome://global/locale/layout/htmlparser.properties", | |||
| 5711 | "chrome://global/locale/svg/svg.properties", | |||
| 5712 | "chrome://branding/locale/brand.properties", | |||
| 5713 | "chrome://global/locale/commonDialogs.properties", | |||
| 5714 | "chrome://global/locale/mathml/mathml.properties", | |||
| 5715 | "chrome://global/locale/security/security.properties", | |||
| 5716 | "chrome://necko/locale/necko.properties", | |||
| 5717 | "resource://gre/res/locale/layout/HtmlForm.properties", | |||
| 5718 | "resource://gre/res/locale/dom/dom.properties", | |||
| 5719 | "resource://gre/res/locale/necko/necko.properties", | |||
| 5720 | }; | |||
| 5721 | ||||
| 5722 | /* static */ | |||
| 5723 | nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) { | |||
| 5724 | MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Should not create bundles off main thread." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5725); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()" ") (" "Should not create bundles off main thread." ")"); do { MOZ_CrashSequence(__null, 5725); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
| 5725 | "Should not create bundles off main thread.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Should not create bundles off main thread." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5725); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()" ") (" "Should not create bundles off main thread." ")"); do { MOZ_CrashSequence(__null, 5725); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 5726 | if (!sStringBundles[size_t(aFile)]) { | |||
| 5727 | if (!sStringBundleService) { | |||
| 5728 | nsresult rv = | |||
| 5729 | CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService); | |||
| 5730 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5730); return rv; } } while (false); | |||
| 5731 | } | |||
| 5732 | RefPtr<nsIStringBundle> bundle; | |||
| 5733 | MOZ_TRY(sStringBundleService->CreateBundle(gPropertiesFiles[size_t(aFile)],__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (sStringBundleService->CreateBundle(gPropertiesFiles[size_t (aFile)], getter_AddRefs(bundle))); if ((__builtin_expect(!!( mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }) | |||
| 5734 | getter_AddRefs(bundle)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (sStringBundleService->CreateBundle(gPropertiesFiles[size_t (aFile)], getter_AddRefs(bundle))); if ((__builtin_expect(!!( mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult .propagateErr(); } mozTryVarTempResult.unwrap(); }); | |||
| 5735 | sStringBundles[size_t(aFile)] = bundle.forget(); | |||
| 5736 | } | |||
| 5737 | return NS_OK; | |||
| 5738 | } | |||
| 5739 | ||||
| 5740 | /* static */ | |||
| 5741 | void nsContentUtils::AsyncPrecreateStringBundles() { | |||
| 5742 | // We only ever want to pre-create bundles in the parent process. | |||
| 5743 | // | |||
| 5744 | // All nsContentUtils bundles are shared between the parent and child | |||
| 5745 | // precesses, and the shared memory regions that back them *must* be created | |||
| 5746 | // in the parent, and then sent to all children. | |||
| 5747 | // | |||
| 5748 | // If we attempt to create a bundle in the child before its memory region is | |||
| 5749 | // available, we need to create a temporary non-shared bundle, and later | |||
| 5750 | // replace that with the shared memory copy. So attempting to pre-load in the | |||
| 5751 | // child is wasteful and unnecessary. | |||
| 5752 | MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType< decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5752); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence (__null, 5752); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 5753 | ||||
| 5754 | for (size_t bundleIndex = 0; bundleIndex < kPropertiesFileCount; | |||
| 5755 | ++bundleIndex) { | |||
| 5756 | nsresult rv = NS_DispatchToCurrentThreadQueue( | |||
| 5757 | NS_NewRunnableFunction("AsyncPrecreateStringBundles", | |||
| 5758 | [bundleIndex]() { | |||
| 5759 | PropertiesFile file = | |||
| 5760 | static_cast<PropertiesFile>(bundleIndex); | |||
| 5761 | EnsureStringBundle(file); | |||
| 5762 | nsIStringBundle* bundle = | |||
| 5763 | sStringBundles[size_t(file)]; | |||
| 5764 | bundle->AsyncPreload(); | |||
| 5765 | }), | |||
| 5766 | EventQueuePriority::Idle); | |||
| 5767 | (void)NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5767); | |||
| 5768 | } | |||
| 5769 | } | |||
| 5770 | ||||
| 5771 | static PropertiesFile GetMaybeSpoofedPropertiesFile(PropertiesFile aFile, | |||
| 5772 | const char* aKey, | |||
| 5773 | const Document* aDocument) { | |||
| 5774 | // When we spoof English, use en-US properties in strings that are accessible | |||
| 5775 | // by content. | |||
| 5776 | bool spoofLocale = nsContentUtils::ShouldResistFingerprinting( | |||
| 5777 | aDocument, RFPTarget::JSLocale); | |||
| 5778 | if (spoofLocale) { | |||
| 5779 | switch (aFile) { | |||
| 5780 | case PropertiesFile::FORMS_PROPERTIES: | |||
| 5781 | return PropertiesFile::FORMS_PROPERTIES_en_US; | |||
| 5782 | case PropertiesFile::DOM_PROPERTIES: | |||
| 5783 | return PropertiesFile::DOM_PROPERTIES_en_US; | |||
| 5784 | default: | |||
| 5785 | break; | |||
| 5786 | } | |||
| 5787 | } | |||
| 5788 | return aFile; | |||
| 5789 | } | |||
| 5790 | ||||
| 5791 | /* static */ | |||
| 5792 | nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile, | |||
| 5793 | const char* aKey, | |||
| 5794 | const Document* aDocument, | |||
| 5795 | nsAString& aResult) { | |||
| 5796 | return GetLocalizedString( | |||
| 5797 | GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult); | |||
| 5798 | } | |||
| 5799 | ||||
| 5800 | /* static */ | |||
| 5801 | nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile, | |||
| 5802 | const char* aKey, | |||
| 5803 | nsAString& aResult) { | |||
| 5804 | return FormatLocalizedString(aFile, aKey, {}, aResult); | |||
| 5805 | } | |||
| 5806 | ||||
| 5807 | /* static */ | |||
| 5808 | nsresult nsContentUtils::FormatMaybeLocalizedString( | |||
| 5809 | PropertiesFile aFile, const char* aKey, Document* aDocument, | |||
| 5810 | const nsTArray<nsString>& aParams, nsAString& aResult) { | |||
| 5811 | return FormatLocalizedString( | |||
| 5812 | GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams, | |||
| 5813 | aResult); | |||
| 5814 | } | |||
| 5815 | ||||
| 5816 | class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable { | |||
| 5817 | public: | |||
| 5818 | FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate, | |||
| 5819 | PropertiesFile aFile, const char* aKey, | |||
| 5820 | const nsTArray<nsString>& aParams, | |||
| 5821 | nsAString& aLocalizedString) | |||
| 5822 | : WorkerMainThreadRunnable(aWorkerPrivate, | |||
| 5823 | "FormatLocalizedStringRunnable"_ns), | |||
| 5824 | mFile(aFile), | |||
| 5825 | mKey(aKey), | |||
| 5826 | mParams(aParams), | |||
| 5827 | mLocalizedString(aLocalizedString) { | |||
| 5828 | MOZ_ASSERT(aWorkerPrivate)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWorkerPrivate)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWorkerPrivate))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWorkerPrivate" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5828); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aWorkerPrivate" ")"); do { MOZ_CrashSequence (__null, 5828); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 5829 | aWorkerPrivate->AssertIsOnWorkerThread(); | |||
| 5830 | } | |||
| 5831 | ||||
| 5832 | bool MainThreadRun() override { | |||
| 5833 | AssertIsOnMainThread(); | |||
| 5834 | ||||
| 5835 | mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams, | |||
| 5836 | mLocalizedString); | |||
| 5837 | (void)NS_WARN_IF(NS_FAILED(mResult))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mResult )), 0))), "NS_FAILED(mResult)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5837); | |||
| 5838 | return true; | |||
| 5839 | } | |||
| 5840 | ||||
| 5841 | nsresult GetResult() const { return mResult; } | |||
| 5842 | ||||
| 5843 | private: | |||
| 5844 | const PropertiesFile mFile; | |||
| 5845 | const char* mKey; | |||
| 5846 | const nsTArray<nsString>& mParams; | |||
| 5847 | nsresult mResult = NS_ERROR_FAILURE; | |||
| 5848 | nsAString& mLocalizedString; | |||
| 5849 | }; | |||
| 5850 | ||||
| 5851 | /* static */ | |||
| 5852 | nsresult nsContentUtils::FormatLocalizedString( | |||
| 5853 | PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams, | |||
| 5854 | nsAString& aResult) { | |||
| 5855 | if (!NS_IsMainThread()) { | |||
| 5856 | // nsIStringBundle is thread-safe but its creation is not, and in particular | |||
| 5857 | // we don't create and store nsIStringBundle objects in a thread-safe way. | |||
| 5858 | // | |||
| 5859 | // TODO(emilio): Maybe if we already have the right bundle created we could | |||
| 5860 | // just call into it, but we should make sure that Shutdown() doesn't get | |||
| 5861 | // called on the main thread when that happens which is a bit tricky to | |||
| 5862 | // prove? | |||
| 5863 | WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); | |||
| 5864 | if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5864)) { | |||
| 5865 | return NS_ERROR_UNEXPECTED; | |||
| 5866 | } | |||
| 5867 | ||||
| 5868 | auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>( | |||
| 5869 | workerPrivate, aFile, aKey, aParams, aResult); | |||
| 5870 | ||||
| 5871 | runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors()); | |||
| 5872 | return runnable->GetResult(); | |||
| 5873 | } | |||
| 5874 | ||||
| 5875 | MOZ_TRY(EnsureStringBundle(aFile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (EnsureStringBundle(aFile)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); | |||
| 5876 | nsIStringBundle* bundle = sStringBundles[size_t(aFile)]; | |||
| 5877 | if (aParams.IsEmpty()) { | |||
| 5878 | return bundle->GetStringFromName(aKey, aResult); | |||
| 5879 | } | |||
| 5880 | return bundle->FormatStringFromName(aKey, aParams, aResult); | |||
| 5881 | } | |||
| 5882 | ||||
| 5883 | /* static */ | |||
| 5884 | void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText, | |||
| 5885 | const nsACString& aCategory, | |||
| 5886 | bool aFromPrivateWindow, | |||
| 5887 | bool aFromChromeContext, | |||
| 5888 | uint32_t aErrorFlags) { | |||
| 5889 | nsCOMPtr<nsIScriptError> scriptError = | |||
| 5890 | do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"); | |||
| 5891 | if (scriptError) { | |||
| 5892 | nsCOMPtr<nsIConsoleService> console = | |||
| 5893 | do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1"); | |||
| 5894 | if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1))) | |||
| 5895 | aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1))) | |||
| 5896 | aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1)))) { | |||
| 5897 | console->LogMessage(scriptError); | |||
| 5898 | } | |||
| 5899 | } | |||
| 5900 | } | |||
| 5901 | ||||
| 5902 | /* static */ | |||
| 5903 | nsresult nsContentUtils::ReportToConsole( | |||
| 5904 | uint32_t aErrorFlags, const nsACString& aCategory, | |||
| 5905 | const Document* aDocument, PropertiesFile aFile, const char* aMessageName, | |||
| 5906 | const nsTArray<nsString>& aParams, const SourceLocation& aLoc) { | |||
| 5907 | nsresult rv; | |||
| 5908 | nsAutoString errorText; | |||
| 5909 | if (!aParams.IsEmpty()) { | |||
| 5910 | rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText); | |||
| 5911 | } else { | |||
| 5912 | rv = GetLocalizedString(aFile, aMessageName, errorText); | |||
| 5913 | } | |||
| 5914 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5914); return rv; } } while (false); | |||
| 5915 | return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory, | |||
| 5916 | aDocument, aLoc); | |||
| 5917 | } | |||
| 5918 | ||||
| 5919 | /* static */ | |||
| 5920 | void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) { | |||
| 5921 | ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc, | |||
| 5922 | PropertiesFile::DOM_PROPERTIES, "EmptyGetElementByIdParam"); | |||
| 5923 | } | |||
| 5924 | ||||
| 5925 | /* static */ | |||
| 5926 | nsresult nsContentUtils::ReportToConsoleNonLocalized( | |||
| 5927 | const nsAString& aErrorText, uint32_t aErrorFlags, | |||
| 5928 | const nsACString& aCategory, const Document* aDocument, | |||
| 5929 | const SourceLocation& aLoc) { | |||
| 5930 | uint64_t innerWindowID = aDocument ? aDocument->InnerWindowID() : 0; | |||
| 5931 | if (aLoc || !aDocument || !aDocument->GetDocumentURI()) { | |||
| 5932 | return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory, | |||
| 5933 | innerWindowID, aLoc); | |||
| 5934 | } | |||
| 5935 | return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory, | |||
| 5936 | innerWindowID, | |||
| 5937 | SourceLocation(aDocument->GetDocumentURI())); | |||
| 5938 | } | |||
| 5939 | ||||
| 5940 | /* static */ | |||
| 5941 | nsresult nsContentUtils::ReportToConsoleByWindowID( | |||
| 5942 | const nsAString& aErrorText, uint32_t aErrorFlags, | |||
| 5943 | const nsACString& aCategory, uint64_t aInnerWindowID, | |||
| 5944 | const SourceLocation& aLocation) { | |||
| 5945 | nsresult rv; | |||
| 5946 | if (!sConsoleService) { // only need to bother null-checking here | |||
| 5947 | rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService); | |||
| 5948 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5948); return rv; } } while (false); | |||
| 5949 | } | |||
| 5950 | ||||
| 5951 | nsCOMPtr<nsIScriptError> errorObject = | |||
| 5952 | do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv); | |||
| 5953 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5953); return rv; } } while (false); | |||
| 5954 | ||||
| 5955 | if (aLocation.mResource.is<nsCOMPtr<nsIURI>>()) { | |||
| 5956 | nsIURI* uri = aLocation.mResource.as<nsCOMPtr<nsIURI>>(); | |||
| 5957 | rv = errorObject->InitWithSourceURI(aErrorText, uri, aLocation.mLine, | |||
| 5958 | aLocation.mColumn, aErrorFlags, | |||
| 5959 | aCategory, aInnerWindowID); | |||
| 5960 | } else { | |||
| 5961 | rv = errorObject->InitWithWindowID( | |||
| 5962 | aErrorText, aLocation.mResource.as<nsCString>(), aLocation.mLine, | |||
| 5963 | aLocation.mColumn, aErrorFlags, aCategory, aInnerWindowID); | |||
| 5964 | } | |||
| 5965 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5965); return rv; } } while (false); | |||
| 5966 | ||||
| 5967 | return sConsoleService->LogMessage(errorObject); | |||
| 5968 | } | |||
| 5969 | ||||
| 5970 | namespace { | |||
| 5971 | ||||
| 5972 | #define DEPRECATED_OPERATION(_op) #_op, | |||
| 5973 | static const char* kDeprecatedOperations[] = { | |||
| 5974 | #include "nsDeprecatedOperationList.inc" | |||
| 5975 | nullptr}; | |||
| 5976 | #undef DEPRECATED_OPERATION | |||
| 5977 | ||||
| 5978 | } // anonymous namespace | |||
| 5979 | ||||
| 5980 | /* static */ | |||
| 5981 | void nsContentUtils::ReportDeprecation( | |||
| 5982 | nsIGlobalObject* aGlobal, const Document* aDoc, nsIURI* aURI, | |||
| 5983 | DeprecatedOperations aOperation, | |||
| 5984 | const mozilla::JSCallingLocation& aLocation) { | |||
| 5985 | MOZ_ASSERT(aGlobal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aGlobal", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")" ); do { MOZ_CrashSequence(__null, 5985); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5986 | MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 5986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")"); do { MOZ_CrashSequence(__null, 5986); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 5987 | ||||
| 5988 | nsAutoCString url; | |||
| 5989 | ReportingUtils::StripURL(aURI, url); | |||
| 5990 | ||||
| 5991 | const char* operation = | |||
| 5992 | kDeprecatedOperations[static_cast<size_t>(aOperation)]; | |||
| 5993 | nsAutoString type; | |||
| 5994 | type.AppendASCII(operation); | |||
| 5995 | ||||
| 5996 | nsAutoCString key; | |||
| 5997 | key.AssignLiteral(operation, strlen(operation)); | |||
| 5998 | key.AppendLiteral("Warning"); | |||
| 5999 | ||||
| 6000 | // XXX do we really want the localized string for deprecation report? | |||
| 6001 | nsAutoString msg; | |||
| 6002 | nsresult rv = nsContentUtils::GetMaybeLocalizedString( | |||
| 6003 | PropertiesFile::DOM_PROPERTIES, key.get(), aDoc, msg); | |||
| 6004 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6004)) { | |||
| 6005 | return; | |||
| 6006 | } | |||
| 6007 | ||||
| 6008 | Nullable<uint32_t> lineNumber; | |||
| 6009 | Nullable<uint32_t> columnNumber; | |||
| 6010 | nsAutoCString sourceFile; | |||
| 6011 | if (aLocation) { | |||
| 6012 | lineNumber.SetValue(aLocation.mLine); | |||
| 6013 | columnNumber.SetValue(aLocation.mColumn); | |||
| 6014 | ReportingUtils::StripLocationFileName(aLocation, sourceFile); | |||
| 6015 | } | |||
| 6016 | ||||
| 6017 | RefPtr<DeprecationReportBody> body = | |||
| 6018 | new DeprecationReportBody(aGlobal, type, nullptr /* date */, msg, | |||
| 6019 | sourceFile, lineNumber, columnNumber); | |||
| 6020 | ||||
| 6021 | ReportingUtils::Report(aGlobal, nsGkAtoms::deprecation, u"default"_ns, | |||
| 6022 | NS_ConvertUTF8toUTF16(url), body); | |||
| 6023 | } | |||
| 6024 | ||||
| 6025 | void nsContentUtils::LogMessageToConsole(const char* aMsg) { | |||
| 6026 | if (!sConsoleService) { // only need to bother null-checking here | |||
| 6027 | CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService); | |||
| 6028 | if (!sConsoleService) { | |||
| 6029 | return; | |||
| 6030 | } | |||
| 6031 | } | |||
| 6032 | sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get()); | |||
| 6033 | } | |||
| 6034 | ||||
| 6035 | bool nsContentUtils::IsChromeDoc(const Document* aDocument) { | |||
| 6036 | return aDocument && aDocument->NodePrincipal() == sSystemPrincipal; | |||
| 6037 | } | |||
| 6038 | ||||
| 6039 | bool nsContentUtils::IsAddonDoc(const Document* aDocument) { | |||
| 6040 | return aDocument && | |||
| 6041 | aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal(); | |||
| 6042 | } | |||
| 6043 | ||||
| 6044 | bool nsContentUtils::IsChildOfSameType(Document* aDoc) { | |||
| 6045 | if (BrowsingContext* bc = aDoc->GetBrowsingContext()) { | |||
| 6046 | return bc->GetParent(); | |||
| 6047 | } | |||
| 6048 | return false; | |||
| 6049 | } | |||
| 6050 | ||||
| 6051 | static bool IsJSONType(const nsACString& aContentType) { | |||
| 6052 | return aContentType.EqualsLiteral(TEXT_JSON"text/json") || | |||
| 6053 | aContentType.EqualsLiteral(APPLICATION_JSON"application/json"); | |||
| 6054 | } | |||
| 6055 | ||||
| 6056 | static bool IsNonPlainTextType(const nsACString& aContentType) { | |||
| 6057 | // MIME type suffixes which should not be plain text. | |||
| 6058 | static constexpr std::string_view kNonPlainTextTypes[] = { | |||
| 6059 | "html", | |||
| 6060 | "xml", | |||
| 6061 | "xsl", | |||
| 6062 | "calendar", | |||
| 6063 | "x-calendar", | |||
| 6064 | "x-vcalendar", | |||
| 6065 | "vcalendar", | |||
| 6066 | "vcard", | |||
| 6067 | "x-vcard", | |||
| 6068 | "directory", | |||
| 6069 | "ldif", | |||
| 6070 | "qif", | |||
| 6071 | "x-qif", | |||
| 6072 | "x-csv", | |||
| 6073 | "x-vcf", | |||
| 6074 | "rtf", | |||
| 6075 | "comma-separated-values", | |||
| 6076 | "csv", | |||
| 6077 | "tab-separated-values", | |||
| 6078 | "tsv", | |||
| 6079 | "ofx", | |||
| 6080 | "vnd.sun.j2me.app-descriptor", | |||
| 6081 | "x-ms-iqy", | |||
| 6082 | "x-ms-odc", | |||
| 6083 | "x-ms-rqy", | |||
| 6084 | "x-ms-contact"}; | |||
| 6085 | ||||
| 6086 | // Trim off the "text/" prefix for comparison. | |||
| 6087 | MOZ_ASSERT(StringBeginsWith(aContentType, "text/"_ns))do { static_assert( mozilla::detail::AssertionConditionType< decltype(StringBeginsWith(aContentType, "text/"_ns))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(StringBeginsWith(aContentType, "text/"_ns)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("StringBeginsWith(aContentType, \"text/\"_ns)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6087); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)" ")"); do { MOZ_CrashSequence(__null, 6087); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6088 | std::string_view suffix = aContentType; | |||
| 6089 | suffix.remove_prefix(5); | |||
| 6090 | ||||
| 6091 | for (std::string_view type : kNonPlainTextTypes) { | |||
| 6092 | if (type == suffix) { | |||
| 6093 | return true; | |||
| 6094 | } | |||
| 6095 | } | |||
| 6096 | return false; | |||
| 6097 | } | |||
| 6098 | ||||
| 6099 | bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) { | |||
| 6100 | // All `text/*`, any JSON type and any JavaScript type are considered "plain | |||
| 6101 | // text" types for the purposes of how to render them as a document. | |||
| 6102 | return (StringBeginsWith(aContentType, "text/"_ns) && | |||
| 6103 | !IsNonPlainTextType(aContentType)) || | |||
| 6104 | IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType); | |||
| 6105 | } | |||
| 6106 | ||||
| 6107 | bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) { | |||
| 6108 | // NOTE: This must be a subset of the list in IsPlainTextType(). | |||
| 6109 | return IsJSONType(aContentType) || | |||
| 6110 | aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") || | |||
| 6111 | aContentType.EqualsLiteral(TEXT_VTT"text/vtt"); | |||
| 6112 | } | |||
| 6113 | ||||
| 6114 | bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) { | |||
| 6115 | return aDocument && aDocument->IsInChromeDocShell(); | |||
| 6116 | } | |||
| 6117 | ||||
| 6118 | // static | |||
| 6119 | nsIContentPolicy* nsContentUtils::GetContentPolicy() { | |||
| 6120 | if (!sTriedToGetContentPolicy) { | |||
| 6121 | CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService); | |||
| 6122 | // It's OK to not have a content policy service | |||
| 6123 | sTriedToGetContentPolicy = true; | |||
| 6124 | } | |||
| 6125 | ||||
| 6126 | return sContentPolicyService; | |||
| 6127 | } | |||
| 6128 | ||||
| 6129 | // static | |||
| 6130 | bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) { | |||
| 6131 | const char16_t* name = aName->GetUTF16String(); | |||
| 6132 | if (name[0] != 'o' || name[1] != 'n') { | |||
| 6133 | return false; | |||
| 6134 | } | |||
| 6135 | ||||
| 6136 | EventNameMapping mapping; | |||
| 6137 | return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType); | |||
| 6138 | } | |||
| 6139 | ||||
| 6140 | // static | |||
| 6141 | EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) { | |||
| 6142 | MOZ_ASSERT(NS_IsMainThread(), "sAtomEventTable is not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "sAtomEventTable is not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "sAtomEventTable is not threadsafe" ")"); do { MOZ_CrashSequence (__null, 6142); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6143 | if (aName) { | |||
| 6144 | EventNameMapping mapping; | |||
| 6145 | if (sAtomEventTable->Get(aName, &mapping)) { | |||
| 6146 | return mapping.mMessage; | |||
| 6147 | } | |||
| 6148 | } | |||
| 6149 | ||||
| 6150 | return eUnidentifiedEvent; | |||
| 6151 | } | |||
| 6152 | ||||
| 6153 | // static | |||
| 6154 | void nsContentUtils::ForEachEventAttributeName( | |||
| 6155 | int32_t aType, const FunctionRef<void(nsAtom*)> aFunc) { | |||
| 6156 | for (auto iter = sAtomEventTable->ConstIter(); !iter.Done(); iter.Next()) { | |||
| 6157 | if (iter.Data().mType & aType) { | |||
| 6158 | aFunc(iter.Key()); | |||
| 6159 | } | |||
| 6160 | } | |||
| 6161 | } | |||
| 6162 | ||||
| 6163 | // static | |||
| 6164 | mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) { | |||
| 6165 | EventNameMapping mapping; | |||
| 6166 | if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID; | |||
| 6167 | ||||
| 6168 | return eBasicEventClass; | |||
| 6169 | } | |||
| 6170 | ||||
| 6171 | nsAtom* nsContentUtils::GetEventMessageAndAtom( | |||
| 6172 | const nsAString& aName, mozilla::EventClassID aEventClassID, | |||
| 6173 | EventMessage* aEventMessage) { | |||
| 6174 | MOZ_ASSERT(NS_IsMainThread(), "Our hashtables are not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Our hashtables are not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence (__null, 6174); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6175 | EventNameMapping mapping; | |||
| 6176 | if (sStringEventTable->Get(aName, &mapping)) { | |||
| 6177 | *aEventMessage = mapping.mEventClassID == aEventClassID | |||
| 6178 | ? mapping.mMessage | |||
| 6179 | : eUnidentifiedEvent; | |||
| 6180 | return mapping.mAtom; | |||
| 6181 | } | |||
| 6182 | ||||
| 6183 | // If we have cached lots of user defined event names, clear some of them. | |||
| 6184 | if (sUserDefinedEvents->Length() > 127) { | |||
| 6185 | while (sUserDefinedEvents->Length() > 64) { | |||
| 6186 | nsAtom* first = sUserDefinedEvents->ElementAt(0); | |||
| 6187 | sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2)); | |||
| 6188 | sUserDefinedEvents->RemoveElementAt(0); | |||
| 6189 | } | |||
| 6190 | } | |||
| 6191 | ||||
| 6192 | *aEventMessage = eUnidentifiedEvent; | |||
| 6193 | RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName); | |||
| 6194 | sUserDefinedEvents->AppendElement(atom); | |||
| 6195 | mapping.mAtom = atom; | |||
| 6196 | mapping.mMessage = eUnidentifiedEvent; | |||
| 6197 | mapping.mType = EventNameType_None; | |||
| 6198 | mapping.mEventClassID = eBasicEventClass; | |||
| 6199 | sStringEventTable->InsertOrUpdate(aName, mapping); | |||
| 6200 | return mapping.mAtom; | |||
| 6201 | } | |||
| 6202 | ||||
| 6203 | // static | |||
| 6204 | EventMessage nsContentUtils::GetEventMessageAndAtomForListener( | |||
| 6205 | const nsAString& aName, nsAtom** aOnName) { | |||
| 6206 | MOZ_ASSERT(NS_IsMainThread(), "Our hashtables are not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Our hashtables are not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence (__null, 6206); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6207 | ||||
| 6208 | // Check sStringEventTable for a matching entry. This will only fail for | |||
| 6209 | // user-defined event types. | |||
| 6210 | EventNameMapping mapping; | |||
| 6211 | if (sStringEventTable->Get(aName, &mapping)) { | |||
| 6212 | RefPtr<nsAtom> atom = mapping.mAtom; | |||
| 6213 | atom.forget(aOnName); | |||
| 6214 | return mapping.mMessage; | |||
| 6215 | } | |||
| 6216 | ||||
| 6217 | // sStringEventTable did not contain an entry for this event type string. | |||
| 6218 | // Call GetEventMessageAndAtom, which will create an event type atom and | |||
| 6219 | // cache it in sStringEventTable for future calls. | |||
| 6220 | EventMessage msg = eUnidentifiedEvent; | |||
| 6221 | RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg); | |||
| 6222 | atom.forget(aOnName); | |||
| 6223 | return msg; | |||
| 6224 | } | |||
| 6225 | ||||
| 6226 | static already_AddRefed<Event> GetEventWithTarget( | |||
| 6227 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6228 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
| 6229 | Trusted aTrusted, ErrorResult& aErrorResult) { | |||
| 6230 | RefPtr<Event> event = | |||
| 6231 | aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult); | |||
| 6232 | if (aErrorResult.Failed()) { | |||
| 6233 | return nullptr; | |||
| 6234 | } | |||
| 6235 | ||||
| 6236 | event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed); | |||
| 6237 | event->SetTrusted(aTrusted == Trusted::eYes); | |||
| 6238 | ||||
| 6239 | event->SetTarget(aTarget); | |||
| 6240 | ||||
| 6241 | return event.forget(); | |||
| 6242 | } | |||
| 6243 | ||||
| 6244 | // static | |||
| 6245 | nsIContent* nsContentUtils::GetEventTargetContent( | |||
| 6246 | nsIContent* aExplicitEventTargetContent, const WidgetEvent* aEvent) { | |||
| 6247 | if (!aExplicitEventTargetContent || | |||
| 6248 | aExplicitEventTargetContent->IsElement() || !aEvent || | |||
| 6249 | !IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) { | |||
| 6250 | return aExplicitEventTargetContent; | |||
| 6251 | } | |||
| 6252 | Element* const ancestorElement = | |||
| 6253 | aExplicitEventTargetContent->GetInclusiveFlattenedTreeAncestorElement(); | |||
| 6254 | return ancestorElement ? ancestorElement : aExplicitEventTargetContent; | |||
| 6255 | } | |||
| 6256 | ||||
| 6257 | // static | |||
| 6258 | nsresult nsContentUtils::DispatchTrustedEvent( | |||
| 6259 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6260 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
| 6261 | bool* aDefaultAction, SystemGroupOnly aSystemGroupOnly) { | |||
| 6262 | MOZ_ASSERT(!aEventName.EqualsLiteral("input") &&do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aEventName.EqualsLiteral("input") && !aEventName .EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input" ) && !aEventName.EqualsLiteral("beforeinput")))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" " (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence (__null, 6264); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 6263 | !aEventName.EqualsLiteral("beforeinput"),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aEventName.EqualsLiteral("input") && !aEventName .EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input" ) && !aEventName.EqualsLiteral("beforeinput")))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" " (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence (__null, 6264); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 6264 | "Use DispatchInputEvent() instead")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aEventName.EqualsLiteral("input") && !aEventName .EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input" ) && !aEventName.EqualsLiteral("beforeinput")))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" " (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence (__null, 6264); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6265 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
| 6266 | aComposed, Trusted::eYes, aDefaultAction, | |||
| 6267 | ChromeOnlyDispatch::eNo, aSystemGroupOnly); | |||
| 6268 | } | |||
| 6269 | ||||
| 6270 | // static | |||
| 6271 | nsresult nsContentUtils::DispatchUntrustedEvent( | |||
| 6272 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6273 | CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) { | |||
| 6274 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
| 6275 | Composed::eDefault, Trusted::eNo, aDefaultAction); | |||
| 6276 | } | |||
| 6277 | ||||
| 6278 | // static | |||
| 6279 | nsresult nsContentUtils::DispatchEvent( | |||
| 6280 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6281 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
| 6282 | Trusted aTrusted, bool* aDefaultAction, | |||
| 6283 | ChromeOnlyDispatch aOnlyChromeDispatch, SystemGroupOnly aSystemGroupOnly) { | |||
| 6284 | if (!aDoc || !aTarget) { | |||
| 6285 | return NS_ERROR_INVALID_ARG; | |||
| 6286 | } | |||
| 6287 | ||||
| 6288 | ErrorResult err; | |||
| 6289 | RefPtr<Event> event = | |||
| 6290 | GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
| 6291 | aComposed, aTrusted, err); | |||
| 6292 | if (err.Failed()) { | |||
| 6293 | return err.StealNSResult(); | |||
| 6294 | } | |||
| 6295 | event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = | |||
| 6296 | aOnlyChromeDispatch == ChromeOnlyDispatch::eYes; | |||
| 6297 | event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatch = | |||
| 6298 | aSystemGroupOnly == SystemGroupOnly::eYes; | |||
| 6299 | ||||
| 6300 | // For the performance reason, aDoc may be set to a raw pointer because it's | |||
| 6301 | // used only before dispatching the event. Therefore, we should not use aDoc | |||
| 6302 | // anymore. | |||
| 6303 | aDoc = nullptr; | |||
| 6304 | bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err); | |||
| 6305 | if (aDefaultAction) { | |||
| 6306 | *aDefaultAction = doDefault; | |||
| 6307 | } | |||
| 6308 | return err.StealNSResult(); | |||
| 6309 | } | |||
| 6310 | ||||
| 6311 | // static | |||
| 6312 | nsresult nsContentUtils::DispatchEvent( | |||
| 6313 | EventTarget* aTarget, WidgetEvent& aEvent, EventMessage aEventMessage, | |||
| 6314 | CanBubble aCanBubble, Cancelable aCancelable, Trusted aTrusted, | |||
| 6315 | bool* aDefaultAction, ChromeOnlyDispatch aOnlyChromeDispatch) { | |||
| 6316 | MOZ_ASSERT_IF(aOnlyChromeDispatch == ChromeOnlyDispatch::eYes,do { if (aOnlyChromeDispatch == ChromeOnlyDispatch::eYes) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTrusted == Trusted::eYes)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTrusted == Trusted::eYes))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTrusted == Trusted::eYes" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6317); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence (__null, 6317); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false) | |||
| 6317 | aTrusted == Trusted::eYes)do { if (aOnlyChromeDispatch == ChromeOnlyDispatch::eYes) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTrusted == Trusted::eYes)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTrusted == Trusted::eYes))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTrusted == Trusted::eYes" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6317); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence (__null, 6317); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false); | |||
| 6318 | ||||
| 6319 | aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage); | |||
| 6320 | aEvent.SetDefaultComposed(); | |||
| 6321 | aEvent.SetDefaultComposedInNativeAnonymousContent(); | |||
| 6322 | ||||
| 6323 | aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes; | |||
| 6324 | aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes; | |||
| 6325 | aEvent.mFlags.mOnlyChromeDispatch = | |||
| 6326 | aOnlyChromeDispatch == ChromeOnlyDispatch::eYes; | |||
| 6327 | ||||
| 6328 | aEvent.mTarget = aTarget; | |||
| 6329 | ||||
| 6330 | nsEventStatus status = nsEventStatus_eIgnore; | |||
| 6331 | nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr, | |||
| 6332 | nullptr, &status); | |||
| 6333 | if (aDefaultAction) { | |||
| 6334 | *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault); | |||
| 6335 | } | |||
| 6336 | return rv; | |||
| 6337 | } | |||
| 6338 | ||||
| 6339 | // static | |||
| 6340 | nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) { | |||
| 6341 | return DispatchInputEvent(aEventTarget, mozilla::eEditorInput, | |||
| 6342 | mozilla::EditorInputType::eUnknown, nullptr, | |||
| 6343 | InputEventOptions()); | |||
| 6344 | } | |||
| 6345 | ||||
| 6346 | // static | |||
| 6347 | nsresult nsContentUtils::DispatchInputEvent( | |||
| 6348 | Element* aEventTargetElement, EventMessage aEventMessage, | |||
| 6349 | EditorInputType aEditorInputType, EditorBase* aEditorBase, | |||
| 6350 | InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) { | |||
| 6351 | MOZ_ASSERT(aEventMessage == eEditorInput ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6352); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" ")"); do { MOZ_CrashSequence(__null, 6352); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 6352 | aEventMessage == eEditorBeforeInput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6352); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" ")"); do { MOZ_CrashSequence(__null, 6352); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6353 | ||||
| 6354 | if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6354)) { | |||
| 6355 | return NS_ERROR_INVALID_ARG; | |||
| 6356 | } | |||
| 6357 | ||||
| 6358 | // If this is called from editor, the instance should be set to aEditorBase. | |||
| 6359 | // Otherwise, we need to look for an editor for aEventTargetElement. | |||
| 6360 | // However, we don't need to do it for HTMLEditor since nobody shouldn't | |||
| 6361 | // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor | |||
| 6362 | // itself. | |||
| 6363 | bool useInputEvent = false; | |||
| 6364 | if (aEditorBase) { | |||
| 6365 | useInputEvent = true; | |||
| 6366 | } else if (const HTMLTextAreaElement* const textAreaElement = | |||
| 6367 | HTMLTextAreaElement::FromNode(aEventTargetElement)) { | |||
| 6368 | aEditorBase = textAreaElement->GetExtantTextEditor(); | |||
| 6369 | useInputEvent = true; | |||
| 6370 | } else if (const HTMLInputElement* const inputElement = | |||
| 6371 | HTMLInputElement::FromNode(aEventTargetElement)) { | |||
| 6372 | if (inputElement->IsInputEventTarget()) { | |||
| 6373 | aEditorBase = inputElement->GetExtantTextEditor(); | |||
| 6374 | useInputEvent = true; | |||
| 6375 | } | |||
| 6376 | } | |||
| 6377 | #ifdef DEBUG1 | |||
| 6378 | else { | |||
| 6379 | MOZ_ASSERT(!aEventTargetElement->IsTextControlElement(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aEventTargetElement->IsTextControlElement())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!aEventTargetElement->IsTextControlElement()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!aEventTargetElement->IsTextControlElement()" " (" "The event target may have editor, but we've not known it yet." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6380 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()" ") (" "The event target may have editor, but we've not known it yet." ")"); do { MOZ_CrashSequence(__null, 6380); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 6380 | "The event target may have editor, but we've not known it yet.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aEventTargetElement->IsTextControlElement())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!aEventTargetElement->IsTextControlElement()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!aEventTargetElement->IsTextControlElement()" " (" "The event target may have editor, but we've not known it yet." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6380 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()" ") (" "The event target may have editor, but we've not known it yet." ")"); do { MOZ_CrashSequence(__null, 6380); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6381 | } | |||
| 6382 | #endif // #ifdef DEBUG | |||
| 6383 | ||||
| 6384 | if (!useInputEvent) { | |||
| 6385 | MOZ_ASSERT(aEventMessage == eEditorInput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEventMessage == eEditorInput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aEventMessage == eEditorInput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEventMessage == eEditorInput", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput" ")"); do { MOZ_CrashSequence(__null, 6385); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6386 | MOZ_ASSERT(aEditorInputType == EditorInputType::eUnknown)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEditorInputType == EditorInputType::eUnknown)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEditorInputType == EditorInputType::eUnknown))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("aEditorInputType == EditorInputType::eUnknown" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6386); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown" ")"); do { MOZ_CrashSequence(__null, 6386); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6387 | MOZ_ASSERT(!aOptions.mNeverCancelable)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aOptions.mNeverCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6387); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence (__null, 6387); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6388 | // Dispatch "input" event with Event instance. | |||
| 6389 | WidgetEvent widgetEvent(true, eUnidentifiedEvent); | |||
| 6390 | widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput; | |||
| 6391 | widgetEvent.mFlags.mCancelable = false; | |||
| 6392 | widgetEvent.mFlags.mComposed = true; | |||
| 6393 | MOZ_LOG(gInputEventLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s" , ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript ()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str ()); } } while (0) | |||
| 6394 | ("Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s",do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s" , ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript ()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str ()); } } while (0) | |||
| 6395 | ToChar(widgetEvent.mMessage),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s" , ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript ()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str ()); } } while (0) | |||
| 6396 | YesOrNo(nsContentUtils::IsSafeToRunScript()), aEditorBase,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s" , ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript ()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str ()); } } while (0) | |||
| 6397 | ToString(RefPtr{aEventTargetElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s" , ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript ()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str ()); } } while (0); | |||
| 6398 | return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement, | |||
| 6399 | widgetEvent, aEventStatus); | |||
| 6400 | } | |||
| 6401 | ||||
| 6402 | MOZ_ASSERT_IF(aEventMessage != eEditorBeforeInput,do { if (aEventMessage != eEditorBeforeInput) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!aOptions .mNeverCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6403); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence (__null, 6403); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false) | |||
| 6403 | !aOptions.mNeverCancelable)do { if (aEventMessage != eEditorBeforeInput) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!aOptions .mNeverCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6403); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence (__null, 6403); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); } } while (false); | |||
| 6404 | MOZ_ASSERT_IF(do { if (aEventMessage == eEditorBeforeInput && aOptions .mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(aEditorInputType == EditorInputType::eInsertReplacementText )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEditorInputType == EditorInputType::eInsertReplacementText" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6406); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 6405 | aEventMessage == eEditorBeforeInput && aOptions.mNeverCancelable,do { if (aEventMessage == eEditorBeforeInput && aOptions .mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(aEditorInputType == EditorInputType::eInsertReplacementText )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEditorInputType == EditorInputType::eInsertReplacementText" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6406); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
| 6406 | aEditorInputType == EditorInputType::eInsertReplacementText)do { if (aEventMessage == eEditorBeforeInput && aOptions .mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(aEditorInputType == EditorInputType::eInsertReplacementText )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aEditorInputType == EditorInputType::eInsertReplacementText" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6406); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 6407 | ||||
| 6408 | nsCOMPtr<nsIWidget> widget; | |||
| 6409 | if (aEditorBase) { | |||
| 6410 | widget = aEditorBase->GetWidget(); | |||
| 6411 | if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6411)) { | |||
| 6412 | return NS_ERROR_FAILURE; | |||
| 6413 | } | |||
| 6414 | } else { | |||
| 6415 | Document* document = aEventTargetElement->OwnerDoc(); | |||
| 6416 | if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6416)) { | |||
| 6417 | return NS_ERROR_FAILURE; | |||
| 6418 | } | |||
| 6419 | // If we're running xpcshell tests, we fail to get presShell here. | |||
| 6420 | // Even in such case, we need to dispatch "input" event without widget. | |||
| 6421 | PresShell* presShell = document->GetPresShell(); | |||
| 6422 | if (presShell) { | |||
| 6423 | nsPresContext* presContext = presShell->GetPresContext(); | |||
| 6424 | if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6424)) { | |||
| 6425 | return NS_ERROR_FAILURE; | |||
| 6426 | } | |||
| 6427 | widget = presContext->GetRootWidget(); | |||
| 6428 | if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6428)) { | |||
| 6429 | return NS_ERROR_FAILURE; | |||
| 6430 | } | |||
| 6431 | } | |||
| 6432 | } | |||
| 6433 | ||||
| 6434 | // Dispatch "input" event with InputEvent instance. | |||
| 6435 | InternalEditorInputEvent inputEvent(true, aEventMessage, widget); | |||
| 6436 | ||||
| 6437 | inputEvent.mFlags.mCancelable = | |||
| 6438 | !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput && | |||
| 6439 | IsCancelableBeforeInputEvent(aEditorInputType); | |||
| 6440 | MOZ_ASSERT(!inputEvent.mFlags.mCancelable || aEventStatus)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mFlags.mCancelable || aEventStatus)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!inputEvent.mFlags.mCancelable || aEventStatus))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mFlags.mCancelable || aEventStatus" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6440); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus" ")"); do { MOZ_CrashSequence(__null, 6440); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6441 | ||||
| 6442 | // If there is an editor, set isComposing to true when it has composition. | |||
| 6443 | // Note that EditorBase::IsIMEComposing() may return false even when we | |||
| 6444 | // need to set it to true. | |||
| 6445 | // Otherwise, i.e., editor hasn't been created for the element yet, | |||
| 6446 | // we should set isComposing to false since the element can never has | |||
| 6447 | // composition without editor. | |||
| 6448 | inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition(); | |||
| 6449 | ||||
| 6450 | if (!aEditorBase || aEditorBase->IsTextEditor()) { | |||
| 6451 | if (IsDataAvailableOnTextEditor(aEditorInputType)) { | |||
| 6452 | inputEvent.mData = std::move(aOptions.mData); | |||
| 6453 | MOZ_ASSERT(!inputEvent.mData.IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()" " (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence (__null, 6454); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 6454 | "inputEvent.mData shouldn't be void")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()" " (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence (__null, 6454); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6455 | } | |||
| 6456 | #ifdef DEBUG1 | |||
| 6457 | else { | |||
| 6458 | MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void")do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inputEvent.mData.IsVoid()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mData.IsVoid()" " (" "inputEvent.mData should be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()" ") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence (__null, 6458); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6459 | } | |||
| 6460 | #endif // #ifdef DEBUG | |||
| 6461 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6463 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 6462 | aOptions.mTargetRanges.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6463 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 6463 | "Target ranges for <input> and <textarea> should always be empty")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6463 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6464 | } else { | |||
| 6465 | MOZ_ASSERT(aEditorBase->IsHTMLEditor())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEditorBase->IsHTMLEditor())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aEditorBase->IsHTMLEditor ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aEditorBase->IsHTMLEditor()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()" ")"); do { MOZ_CrashSequence(__null, 6465); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6466 | if (IsDataAvailableOnHTMLEditor(aEditorInputType)) { | |||
| 6467 | inputEvent.mData = std::move(aOptions.mData); | |||
| 6468 | MOZ_ASSERT(!inputEvent.mData.IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()" " (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence (__null, 6469); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 6469 | "inputEvent.mData shouldn't be void")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()" " (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence (__null, 6469); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6470 | } else { | |||
| 6471 | MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void")do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inputEvent.mData.IsVoid()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mData.IsVoid()" " (" "inputEvent.mData should be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()" ") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence (__null, 6471); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6472 | if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) { | |||
| 6473 | inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer); | |||
| 6474 | MOZ_ASSERT(inputEvent.mDataTransfer,do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mDataTransfer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inputEvent.mDataTransfer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer" " (" "inputEvent.mDataTransfer shouldn't be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do { MOZ_CrashSequence(__null, 6475); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
| 6475 | "inputEvent.mDataTransfer shouldn't be nullptr")do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mDataTransfer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inputEvent.mDataTransfer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer" " (" "inputEvent.mDataTransfer shouldn't be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do { MOZ_CrashSequence(__null, 6475); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 6476 | MOZ_ASSERT(inputEvent.mDataTransfer->IsReadOnly(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mDataTransfer->IsReadOnly())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(inputEvent.mDataTransfer->IsReadOnly()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer->IsReadOnly()" " (" "inputEvent.mDataTransfer should be read only" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()" ") (" "inputEvent.mDataTransfer should be read only" ")"); do { MOZ_CrashSequence(__null, 6477); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
| 6477 | "inputEvent.mDataTransfer should be read only")do { static_assert( mozilla::detail::AssertionConditionType< decltype(inputEvent.mDataTransfer->IsReadOnly())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(inputEvent.mDataTransfer->IsReadOnly()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer->IsReadOnly()" " (" "inputEvent.mDataTransfer should be read only" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()" ") (" "inputEvent.mDataTransfer should be read only" ")"); do { MOZ_CrashSequence(__null, 6477); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 6478 | } | |||
| 6479 | #ifdef DEBUG1 | |||
| 6480 | else { | |||
| 6481 | MOZ_ASSERT(!inputEvent.mDataTransfer,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mDataTransfer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mDataTransfer))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mDataTransfer" " (" "inputEvent.mDataTransfer should be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer should be nullptr" ")"); do { MOZ_CrashSequence(__null, 6482); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
| 6482 | "inputEvent.mDataTransfer should be nullptr")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inputEvent.mDataTransfer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inputEvent.mDataTransfer))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mDataTransfer" " (" "inputEvent.mDataTransfer should be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer should be nullptr" ")"); do { MOZ_CrashSequence(__null, 6482); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 6483 | } | |||
| 6484 | #endif // #ifdef DEBUG | |||
| 6485 | } | |||
| 6486 | if (aEventMessage == eEditorBeforeInput && | |||
| 6487 | MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) { | |||
| 6488 | inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges); | |||
| 6489 | } | |||
| 6490 | #ifdef DEBUG1 | |||
| 6491 | else { | |||
| 6492 | MOZ_ASSERT(aOptions.mTargetRanges.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges shouldn't be set for the dispatching event" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6493 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges shouldn't be set for the dispatching event" ")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 6493 | "Target ranges shouldn't be set for the dispatching event")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges shouldn't be set for the dispatching event" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6493 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges shouldn't be set for the dispatching event" ")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6494 | } | |||
| 6495 | #endif // #ifdef DEBUG | |||
| 6496 | } | |||
| 6497 | ||||
| 6498 | inputEvent.mInputType = aEditorInputType; | |||
| 6499 | ||||
| 6500 | // If we cannot dispatch an event right now, we cannot make it cancelable. | |||
| 6501 | if (!nsContentUtils::IsSafeToRunScript()) { | |||
| 6502 | NS_ASSERTION(do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Cancelable beforeinput event dispatcher should run when it's safe" , "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6504); MOZ_PretendNoReturn(); } } while (0) | |||
| 6503 | !inputEvent.mFlags.mCancelable,do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Cancelable beforeinput event dispatcher should run when it's safe" , "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6504); MOZ_PretendNoReturn(); } } while (0) | |||
| 6504 | "Cancelable beforeinput event dispatcher should run when it's safe")do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Cancelable beforeinput event dispatcher should run when it's safe" , "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6504); MOZ_PretendNoReturn(); } } while (0); | |||
| 6505 | inputEvent.mFlags.mCancelable = false; | |||
| 6506 | } | |||
| 6507 | MOZ_LOG(gInputEventLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6508 | ("Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6509 | "aEventTargetElement=%s",do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6510 | ToChar(inputEvent.mMessage),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6511 | YesOrNo(nsContentUtils::IsSafeToRunScript()),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6512 | ToString(inputEvent.mInputType).c_str(), aEditorBase,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0) | |||
| 6513 | ToString(RefPtr{aEventTargetElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gInputEventLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, " "aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo (nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType ).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement}) .c_str()); } } while (0); | |||
| 6514 | return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement, | |||
| 6515 | inputEvent, aEventStatus); | |||
| 6516 | } | |||
| 6517 | ||||
| 6518 | nsresult nsContentUtils::DispatchChromeEvent( | |||
| 6519 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6520 | CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) { | |||
| 6521 | if (!aDoc || !aTarget) { | |||
| 6522 | return NS_ERROR_INVALID_ARG; | |||
| 6523 | } | |||
| 6524 | ||||
| 6525 | if (!aDoc->GetWindow()) { | |||
| 6526 | return NS_ERROR_INVALID_ARG; | |||
| 6527 | } | |||
| 6528 | ||||
| 6529 | EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget(); | |||
| 6530 | if (!piTarget) { | |||
| 6531 | return NS_ERROR_INVALID_ARG; | |||
| 6532 | } | |||
| 6533 | ||||
| 6534 | ErrorResult err; | |||
| 6535 | RefPtr<Event> event = | |||
| 6536 | GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
| 6537 | Composed::eDefault, Trusted::eYes, err); | |||
| 6538 | if (err.Failed()) { | |||
| 6539 | return err.StealNSResult(); | |||
| 6540 | } | |||
| 6541 | ||||
| 6542 | bool defaultActionEnabled = | |||
| 6543 | piTarget->DispatchEvent(*event, CallerType::System, err); | |||
| 6544 | if (aDefaultAction) { | |||
| 6545 | *aDefaultAction = defaultActionEnabled; | |||
| 6546 | } | |||
| 6547 | return err.StealNSResult(); | |||
| 6548 | } | |||
| 6549 | ||||
| 6550 | void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise, | |||
| 6551 | CallerType aCallerType) { | |||
| 6552 | RefPtr<Element> target = &aFrameElement; | |||
| 6553 | bool defaultAction = true; | |||
| 6554 | if (aCanRaise) { | |||
| 6555 | RefPtr<Document> doc = target->OwnerDoc(); | |||
| 6556 | DispatchEventOnlyToChrome(doc, target, u"framefocusrequested"_ns, | |||
| 6557 | CanBubble::eYes, Cancelable::eYes, | |||
| 6558 | &defaultAction); | |||
| 6559 | } | |||
| 6560 | if (!defaultAction) { | |||
| 6561 | return; | |||
| 6562 | } | |||
| 6563 | ||||
| 6564 | RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager(); | |||
| 6565 | if (!fm) { | |||
| 6566 | return; | |||
| 6567 | } | |||
| 6568 | ||||
| 6569 | uint32_t flags = nsIFocusManager::FLAG_NOSCROLL; | |||
| 6570 | if (aCanRaise) { | |||
| 6571 | flags |= nsIFocusManager::FLAG_RAISE; | |||
| 6572 | } | |||
| 6573 | ||||
| 6574 | if (aCallerType == CallerType::NonSystem) { | |||
| 6575 | flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER; | |||
| 6576 | } | |||
| 6577 | ||||
| 6578 | fm->SetFocus(target, flags); | |||
| 6579 | } | |||
| 6580 | ||||
| 6581 | nsresult nsContentUtils::DispatchEventOnlyToChrome( | |||
| 6582 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
| 6583 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
| 6584 | bool* aDefaultAction) { | |||
| 6585 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
| 6586 | aComposed, Trusted::eYes, aDefaultAction, | |||
| 6587 | ChromeOnlyDispatch::eYes); | |||
| 6588 | } | |||
| 6589 | ||||
| 6590 | /* static */ | |||
| 6591 | Element* nsContentUtils::MatchElementId(nsIContent* aContent, | |||
| 6592 | const nsAtom* aId) { | |||
| 6593 | for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) { | |||
| 6594 | if (aId == cur->GetID()) { | |||
| 6595 | return cur->AsElement(); | |||
| 6596 | } | |||
| 6597 | } | |||
| 6598 | ||||
| 6599 | return nullptr; | |||
| 6600 | } | |||
| 6601 | ||||
| 6602 | /* static */ | |||
| 6603 | Element* nsContentUtils::MatchElementId(nsIContent* aContent, | |||
| 6604 | const nsAString& aId) { | |||
| 6605 | MOZ_ASSERT(!aId.IsEmpty(), "Will match random elements")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aId.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aId.IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aId.IsEmpty()" " (" "Will match random elements" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()" ") (" "Will match random elements" ")"); do { MOZ_CrashSequence (__null, 6605); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6606 | ||||
| 6607 | // ID attrs are generally stored as atoms, so just atomize this up front | |||
| 6608 | RefPtr<nsAtom> id(NS_Atomize(aId)); | |||
| 6609 | if (!id) { | |||
| 6610 | // OOM, so just bail | |||
| 6611 | return nullptr; | |||
| 6612 | } | |||
| 6613 | ||||
| 6614 | return MatchElementId(aContent, id); | |||
| 6615 | } | |||
| 6616 | ||||
| 6617 | /* static */ | |||
| 6618 | void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) { | |||
| 6619 | nsCOMPtr<nsIObserverService> observerService = | |||
| 6620 | mozilla::services::GetObserverService(); | |||
| 6621 | if (observerService) { | |||
| 6622 | observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", | |||
| 6623 | false); | |||
| 6624 | } | |||
| 6625 | } | |||
| 6626 | ||||
| 6627 | /* static */ | |||
| 6628 | void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) { | |||
| 6629 | nsCOMPtr<nsIObserverService> observerService = | |||
| 6630 | mozilla::services::GetObserverService(); | |||
| 6631 | if (observerService) { | |||
| 6632 | observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown"); | |||
| 6633 | } | |||
| 6634 | } | |||
| 6635 | ||||
| 6636 | /* static */ | |||
| 6637 | bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, | |||
| 6638 | int32_t aNameSpaceID, nsAtom* aName) { | |||
| 6639 | static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr}; | |||
| 6640 | return aContent->IsElement() && | |||
| 6641 | aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings, | |||
| 6642 | eCaseMatters) == | |||
| 6643 | AttrArray::ATTR_VALUE_NO_MATCH; | |||
| 6644 | } | |||
| 6645 | ||||
| 6646 | void nsContentUtils::NotifyDevToolsOfNodeRemoval(nsINode& aRemovingNode) { | |||
| 6647 | // Having an explicit check here since it's an easy mistake to fall into, | |||
| 6648 | // and there might be existing code with problems. We'd rather be safe | |||
| 6649 | // than fire a chrome only event in all corner cases. We also rely on it for | |||
| 6650 | // nsAutoScriptBlockerSuppressNodeRemoved. | |||
| 6651 | if (!IsSafeToRunScript()) { | |||
| 6652 | // This checks that IsSafeToRunScript is true since we don't want to fire | |||
| 6653 | // events when that is false. We can't rely on EventDispatcher to assert | |||
| 6654 | // this in this situation since most of the time DevTools is not observing | |||
| 6655 | // the mutations, in which case we won't even attempt to dispatch events. | |||
| 6656 | // However this also allows for two exceptions. First off, we don't assert | |||
| 6657 | // if the mutation happens to native anonymous content since we never fire | |||
| 6658 | // mutation events on such content anyway. | |||
| 6659 | // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since | |||
| 6660 | // that is a know case when we'd normally fire a mutation event, but can't | |||
| 6661 | // make that safe and so we suppress it at this time. Ideally this should | |||
| 6662 | // go away eventually. | |||
| 6663 | if (!aRemovingNode.IsInNativeAnonymousSubtree() && | |||
| 6664 | !sDOMNodeRemovedSuppressCount) { | |||
| 6665 | NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire \"devtoolschildremoved\" event, but it's not safe" , "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6666); MOZ_PretendNoReturn(); } while (0) | |||
| 6666 | "Want to fire \"devtoolschildremoved\" event, but it's not safe")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire \"devtoolschildremoved\" event, but it's not safe" , "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6666); MOZ_PretendNoReturn(); } while (0); | |||
| 6667 | WarnScriptWasIgnored(aRemovingNode.OwnerDoc()); | |||
| 6668 | } | |||
| 6669 | return; | |||
| 6670 | } | |||
| 6671 | ||||
| 6672 | if (MOZ_UNLIKELY(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval())(__builtin_expect(!!(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval ()), 0))) { | |||
| 6673 | const RefPtr<Document> doc = aRemovingNode.OwnerDoc(); | |||
| 6674 | DispatchChromeEvent(doc, &aRemovingNode, u"devtoolschildremoved"_ns, | |||
| 6675 | CanBubble::eNo, Cancelable::eNo); | |||
| 6676 | } | |||
| 6677 | } | |||
| 6678 | ||||
| 6679 | void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() { | |||
| 6680 | for (EventListenerManager& mgr : sNodeEventListenerManagers) { | |||
| 6681 | nsINode* n = static_cast<nsINode*>(mgr.GetTarget()); | |||
| 6682 | if (n && n->IsInComposedDoc() && | |||
| 6683 | nsCCUncollectableMarker::InGeneration( | |||
| 6684 | n->OwnerDoc()->GetMarkedCCGeneration())) { | |||
| 6685 | mgr.MarkForCC(); | |||
| 6686 | } | |||
| 6687 | } | |||
| 6688 | } | |||
| 6689 | ||||
| 6690 | /* static */ | |||
| 6691 | void nsContentUtils::AddNodeListenerManager(EventListenerManager* aManager) { | |||
| 6692 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6692); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 6692); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6693 | sNodeEventListenerManagers.pushBack(aManager); | |||
| 6694 | } | |||
| 6695 | ||||
| 6696 | /* static */ | |||
| 6697 | void nsContentUtils::RemoveNodeListenerManager(EventListenerManager* aManager) { | |||
| 6698 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6698); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 6698); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 6699 | // ~EventListenerManager passes here managers which are not in the list. | |||
| 6700 | if (sNodeEventListenerManagers.ElementProbablyInList(aManager)) { | |||
| 6701 | sNodeEventListenerManagers.remove(aManager); | |||
| 6702 | } | |||
| 6703 | } | |||
| 6704 | ||||
| 6705 | void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode, | |||
| 6706 | DOMArena* aDOMArena) { | |||
| 6707 | MOZ_ASSERT_IF(sDOMArenaHashtable, !sDOMArenaHashtable->Contains(aNode))do { if (sDOMArenaHashtable) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(!sDOMArenaHashtable-> Contains(aNode))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!sDOMArenaHashtable->Contains (aNode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!sDOMArenaHashtable->Contains(aNode)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 6707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)" ")"); do { MOZ_CrashSequence(__null, 6707); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 6708 | MOZ_ASSERT(!aNode->HasFlag(NODE_KEEPS_DOMARENA))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aNode->HasFlag(NODE_KEEPS_DOMARENA))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!aNode->HasFlag(NODE_KEEPS_DOMARENA)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aNode->HasFlag(NODE_KEEPS_DOMARENA)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6708); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)" ")" ); do { MOZ_CrashSequence(__null, 6708); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6709 | if (!sDOMArenaHashtable) { | |||
| 6710 | sDOMArenaHashtable = | |||
| 6711 | new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>(); | |||
| 6712 | } | |||
| 6713 | aNode->SetFlags(NODE_KEEPS_DOMARENA); | |||
| 6714 | sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena)); | |||
| 6715 | } | |||
| 6716 | ||||
| 6717 | DOMArena* nsContentUtils::GetEntryFromDOMArenaTable(const nsINode* aNode) { | |||
| 6718 | if (!sDOMArenaHashtable) { | |||
| 6719 | return nullptr; | |||
| 6720 | } | |||
| 6721 | return sDOMArenaHashtable->MaybeGet(aNode).valueOr(nullptr); | |||
| 6722 | } | |||
| 6723 | ||||
| 6724 | already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable( | |||
| 6725 | const nsINode* aNode) { | |||
| 6726 | MOZ_ASSERT(sDOMArenaHashtable->Contains(aNode))do { static_assert( mozilla::detail::AssertionConditionType< decltype(sDOMArenaHashtable->Contains(aNode))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(sDOMArenaHashtable->Contains(aNode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sDOMArenaHashtable->Contains(aNode)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6726); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)" ")" ); do { MOZ_CrashSequence(__null, 6726); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 6727 | RefPtr<DOMArena> arena; | |||
| 6728 | sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena)); | |||
| 6729 | return arena.forget(); | |||
| 6730 | } | |||
| 6731 | ||||
| 6732 | /* static */ | |||
| 6733 | bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix, | |||
| 6734 | int32_t aNamespaceID) { | |||
| 6735 | if (aNamespaceID == kNameSpaceID_Unknown-1) { | |||
| 6736 | return false; | |||
| 6737 | } | |||
| 6738 | ||||
| 6739 | if (!aPrefix) { | |||
| 6740 | // If the prefix is null, then either the QName must be xmlns or the | |||
| 6741 | // namespace must not be XMLNS. | |||
| 6742 | return (aLocalName == nsGkAtoms::xmlns) == | |||
| 6743 | (aNamespaceID == kNameSpaceID_XMLNS1); | |||
| 6744 | } | |||
| 6745 | ||||
| 6746 | // If the prefix is non-null then the namespace must not be null. | |||
| 6747 | if (aNamespaceID == kNameSpaceID_None) { | |||
| 6748 | return false; | |||
| 6749 | } | |||
| 6750 | ||||
| 6751 | // If the namespace is the XMLNS namespace then the prefix must be xmlns, | |||
| 6752 | // but the localname must not be xmlns. | |||
| 6753 | if (aNamespaceID == kNameSpaceID_XMLNS1) { | |||
| 6754 | return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns; | |||
| 6755 | } | |||
| 6756 | ||||
| 6757 | // If the namespace is not the XMLNS namespace then the prefix must not be | |||
| 6758 | // xmlns. | |||
| 6759 | // If the namespace is the XML namespace then the prefix can be anything. | |||
| 6760 | // If the namespace is not the XML namespace then the prefix must not be xml. | |||
| 6761 | return aPrefix != nsGkAtoms::xmlns && | |||
| 6762 | (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml); | |||
| 6763 | } | |||
| 6764 | ||||
| 6765 | already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment( | |||
| 6766 | nsINode* aContextNode, const nsAString& aFragment, | |||
| 6767 | bool aPreventScriptExecution, | |||
| 6768 | Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry, | |||
| 6769 | ErrorResult& aRv) { | |||
| 6770 | if (!aContextNode) { | |||
| 6771 | aRv.Throw(NS_ERROR_INVALID_ARG); | |||
| 6772 | return nullptr; | |||
| 6773 | } | |||
| 6774 | ||||
| 6775 | // If we don't have a document here, we can't get the right security context | |||
| 6776 | // for compiling event handlers... so just bail out. | |||
| 6777 | RefPtr<Document> document = aContextNode->OwnerDoc(); | |||
| 6778 | bool isHTML = document->IsHTMLDocument(); | |||
| 6779 | ||||
| 6780 | if (isHTML) { | |||
| 6781 | RefPtr<DocumentFragment> frag = new (document->NodeInfoManager()) | |||
| 6782 | DocumentFragment(document->NodeInfoManager()); | |||
| 6783 | ||||
| 6784 | Element* element = aContextNode->GetAsElementOrParentElement(); | |||
| 6785 | if (element && !element->IsHTMLElement(nsGkAtoms::html)) { | |||
| 6786 | aRv = ParseFragmentHTML( | |||
| 6787 | aFragment, frag, element->NodeInfo()->NameAtom(), | |||
| 6788 | element->GetNameSpaceID(), | |||
| 6789 | (document->GetCompatibilityMode() == eCompatibility_NavQuirks), | |||
| 6790 | aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization, | |||
| 6791 | std::move(aCustomElementRegistry)); | |||
| 6792 | } else { | |||
| 6793 | aRv = ParseFragmentHTML( | |||
| 6794 | aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3, | |||
| 6795 | (document->GetCompatibilityMode() == eCompatibility_NavQuirks), | |||
| 6796 | aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization, | |||
| 6797 | std::move(aCustomElementRegistry)); | |||
| 6798 | } | |||
| 6799 | ||||
| 6800 | return frag.forget(); | |||
| 6801 | } | |||
| 6802 | ||||
| 6803 | AutoTArray<nsString, 32> tagStack; | |||
| 6804 | nsAutoString uriStr, nameStr; | |||
| 6805 | for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) { | |||
| 6806 | nsString& tagName = *tagStack.AppendElement(); | |||
| 6807 | // It mostly doesn't actually matter what tag name we use here: XML doesn't | |||
| 6808 | // have parsing that depends on the open tag stack, apart from namespace | |||
| 6809 | // declarations. So this whole tagStack bit is just there to get the right | |||
| 6810 | // namespace declarations to the XML parser. That said, the parser _is_ | |||
| 6811 | // going to create elements with the tag names we provide here, so we need | |||
| 6812 | // to make sure they are not names that can trigger custom element | |||
| 6813 | // constructors. Just make up a name that is never going to be a valid | |||
| 6814 | // custom element name. | |||
| 6815 | // | |||
| 6816 | // The principled way to do this would probably be to add a new FromParser | |||
| 6817 | // value and make sure we use it when creating the context elements, then | |||
| 6818 | // make sure we teach all FromParser consumers (and in particular the custom | |||
| 6819 | // element code) about it as needed. But right now the XML parser never | |||
| 6820 | // actually uses FromParser values other than NOT_FROM_PARSER, and changing | |||
| 6821 | // that is pretty complicated. | |||
| 6822 | tagName.AssignLiteral("notacustomelement"); | |||
| 6823 | ||||
| 6824 | // see if we need to add xmlns declarations | |||
| 6825 | uint32_t count = element->GetAttrCount(); | |||
| 6826 | bool setDefaultNamespace = false; | |||
| 6827 | if (count > 0) { | |||
| 6828 | uint32_t index; | |||
| 6829 | ||||
| 6830 | for (index = 0; index < count; index++) { | |||
| 6831 | const BorrowedAttrInfo info = element->GetAttrInfoAt(index); | |||
| 6832 | const nsAttrName* name = info.mName; | |||
| 6833 | if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) { | |||
| 6834 | info.mValue->ToString(uriStr); | |||
| 6835 | ||||
| 6836 | // really want something like nsXMLContentSerializer::SerializeAttr | |||
| 6837 | tagName.AppendLiteral(" xmlns"); // space important | |||
| 6838 | if (name->GetPrefix()) { | |||
| 6839 | tagName.Append(char16_t(':')); | |||
| 6840 | name->LocalName()->ToString(nameStr); | |||
| 6841 | tagName.Append(nameStr); | |||
| 6842 | } else { | |||
| 6843 | setDefaultNamespace = true; | |||
| 6844 | } | |||
| 6845 | tagName.AppendLiteral(R"(=")"); | |||
| 6846 | tagName.Append(uriStr); | |||
| 6847 | tagName.Append('"'); | |||
| 6848 | } | |||
| 6849 | } | |||
| 6850 | } | |||
| 6851 | ||||
| 6852 | if (!setDefaultNamespace) { | |||
| 6853 | mozilla::dom::NodeInfo* info = element->NodeInfo(); | |||
| 6854 | if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) { | |||
| 6855 | // We have no namespace prefix, but have a namespace ID. Push | |||
| 6856 | // default namespace attr in, so that our kids will be in our | |||
| 6857 | // namespace. | |||
| 6858 | info->GetNamespaceURI(uriStr); | |||
| 6859 | tagName.AppendLiteral(R"( xmlns=")"); | |||
| 6860 | tagName.Append(uriStr); | |||
| 6861 | tagName.Append('"'); | |||
| 6862 | } | |||
| 6863 | } | |||
| 6864 | } | |||
| 6865 | ||||
| 6866 | RefPtr<DocumentFragment> frag; | |||
| 6867 | aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution, | |||
| 6868 | kParseFragmentPrivilegedDefaultSanitization, | |||
| 6869 | getter_AddRefs(frag)); | |||
| 6870 | return frag.forget(); | |||
| 6871 | } | |||
| 6872 | ||||
| 6873 | /* static */ | |||
| 6874 | void nsContentUtils::DropFragmentParsers() { | |||
| 6875 | NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release (); (sHTMLFragmentParser) = 0; } } while (0); | |||
| 6876 | NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release (); (sXMLFragmentParser) = 0; } } while (0); | |||
| 6877 | NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release() ; (sXMLFragmentSink) = 0; } } while (0); | |||
| 6878 | } | |||
| 6879 | ||||
| 6880 | /* static */ | |||
| 6881 | void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); } | |||
| 6882 | ||||
| 6883 | // https://wicg.github.io/sanitizer-api/#set-and-filter-html | |||
| 6884 | static void SetAndFilterHTML( | |||
| 6885 | FragmentOrElement* aTarget, Element* aContext, const nsAString& aHTML, | |||
| 6886 | const OwningSanitizerOrSanitizerConfigOrSanitizerPresets& aSanitizerOptions, | |||
| 6887 | const bool aSafe, ErrorResult& aError) { | |||
| 6888 | const RefPtr<Document> doc = aTarget->OwnerDoc(); | |||
| 6889 | ||||
| 6890 | // Step 1. If safe and contextElement’s local name is "script" and | |||
| 6891 | // contextElement’s namespace is the HTML namespace or the SVG namespace, then | |||
| 6892 | // return. | |||
| 6893 | if (aSafe && (aContext->IsHTMLElement(nsGkAtoms::script) || | |||
| 6894 | aContext->IsSVGElement(nsGkAtoms::script))) { | |||
| 6895 | nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, doc, | |||
| 6896 | PropertiesFile::DOM_PROPERTIES, | |||
| 6897 | "SetHTMLScript"); | |||
| 6898 | return; | |||
| 6899 | } | |||
| 6900 | ||||
| 6901 | // Step 2. Let sanitizer be the result of calling get a sanitizer instance | |||
| 6902 | // from options with options and safe. | |||
| 6903 | nsCOMPtr<nsIGlobalObject> global = aTarget->GetRelevantGlobal(); | |||
| 6904 | if (!global) { | |||
| 6905 | aError.ThrowInvalidStateError("Missing owner global."); | |||
| 6906 | return; | |||
| 6907 | } | |||
| 6908 | RefPtr<Sanitizer> sanitizer = | |||
| 6909 | Sanitizer::GetInstance(global, aSanitizerOptions, aSafe, aError); | |||
| 6910 | if (aError.Failed()) { | |||
| 6911 | return; | |||
| 6912 | } | |||
| 6913 | ||||
| 6914 | aTarget->NotifyDevToolsOfRemovalsOfChildren(); | |||
| 6915 | ||||
| 6916 | // Needed when innerHTML is used in combination with contenteditable | |||
| 6917 | mozAutoDocUpdate updateBatch(doc, true); | |||
| 6918 | ||||
| 6919 | // Remove childnodes. | |||
| 6920 | nsAutoMutationBatch mb(aTarget, true, false); | |||
| 6921 | aTarget->RemoveAllChildren(true); | |||
| 6922 | mb.RemovalDone(); | |||
| 6923 | ||||
| 6924 | nsAutoScriptLoaderDisabler sld(doc); | |||
| 6925 | ||||
| 6926 | // Step 3. Let newChildren be the result of the HTML fragment parsing | |||
| 6927 | // algorithm steps given contextElement, html, and true. | |||
| 6928 | // Step 4. Let fragment be a new DocumentFragment whose node document is | |||
| 6929 | // contextElement’s node document. | |||
| 6930 | // Step 5. For each node in newChildren, append node to fragment. | |||
| 6931 | ||||
| 6932 | // We MUST NOT cause any requests during parsing, so we'll | |||
| 6933 | // create an inert Document and parse into a new DocumentFragment. | |||
| 6934 | ||||
| 6935 | RefPtr<Document> inertDoc = nsContentUtils::CreateInertHTMLDocument(doc); | |||
| 6936 | if (!inertDoc) { | |||
| 6937 | aError = NS_ERROR_FAILURE; | |||
| 6938 | return; | |||
| 6939 | } | |||
| 6940 | ||||
| 6941 | RefPtr<DocumentFragment> fragment = new (inertDoc->NodeInfoManager()) | |||
| 6942 | DocumentFragment(inertDoc->NodeInfoManager()); | |||
| 6943 | ||||
| 6944 | nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom(); | |||
| 6945 | int32_t contextNameSpaceID = aContext->GetNameSpaceID(); | |||
| 6946 | int32_t flags = | |||
| 6947 | aSafe ? nsContentUtils::kParseFragmentNoSanitization | |||
| 6948 | : nsContentUtils::kParseFragmentPrivilegedDefaultSanitization; | |||
| 6949 | aError = nsContentUtils::ParseFragmentHTML( | |||
| 6950 | aHTML, fragment, contextLocalName, contextNameSpaceID, | |||
| 6951 | /* aQuirks */ false, /* aPreventScriptExecution */ true, flags, | |||
| 6952 | mozilla::Nothing()); | |||
| 6953 | if (aError.Failed()) { | |||
| 6954 | return; | |||
| 6955 | } | |||
| 6956 | ||||
| 6957 | // Suppress assertion about node removal mutation events that can't have | |||
| 6958 | // listeners anyway, because no one has had the chance to register | |||
| 6959 | // mutation listeners on the fragment that comes from the parser. | |||
| 6960 | nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; | |||
| 6961 | ||||
| 6962 | // Step 6. Run sanitize on fragment using sanitizer and safe. | |||
| 6963 | sanitizer->Sanitize(fragment, aSafe, aError); | |||
| 6964 | if (aError.Failed()) { | |||
| 6965 | return; | |||
| 6966 | } | |||
| 6967 | ||||
| 6968 | // Step 7. Replace all with fragment within target. | |||
| 6969 | aTarget->AppendChild(*fragment, aError); | |||
| 6970 | if (aError.Failed()) { | |||
| 6971 | return; | |||
| 6972 | } | |||
| 6973 | ||||
| 6974 | mb.NodesAdded(); | |||
| 6975 | } | |||
| 6976 | ||||
| 6977 | /* static */ | |||
| 6978 | void nsContentUtils::SetHTML(FragmentOrElement* aTarget, Element* aContext, | |||
| 6979 | const nsAString& aHTML, | |||
| 6980 | const SetHTMLOptions& aOptions, | |||
| 6981 | ErrorResult& aError) { | |||
| 6982 | SetAndFilterHTML(aTarget, aContext, aHTML, aOptions.mSanitizer, | |||
| 6983 | /* aSafe */ true, aError); | |||
| 6984 | } | |||
| 6985 | ||||
| 6986 | /* https://html.spec.whatwg.org/#unsafely-set-html */ | |||
| 6987 | /* https://html.spec.whatwg.org/#dom-shadowroot-sethtmlunsafe */ | |||
| 6988 | /* https://html.spec.whatwg.org/#dom-element-sethtmlunsafe */ | |||
| 6989 | /* static */ | |||
| 6990 | void nsContentUtils::SetHTMLUnsafe( | |||
| 6991 | FragmentOrElement* aTarget, Element* aContext, | |||
| 6992 | const TrustedHTMLOrString& aSource, const SetHTMLUnsafeOptions& aOptions, | |||
| 6993 | bool aIsShadowRoot, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError) { | |||
| 6994 | // Element's setHTMLUnsafe() step 1 / ShadowRoot's setHTMLUnsafe() step 1. | |||
| 6995 | // "Let compliantHTML be the result of invoking the get trusted type compliant | |||
| 6996 | // string algorithm with TrustedHTML, this's relevant global object, html, | |||
| 6997 | // «Element setHTMLUnsafe» or «ShadowRoot setHTMLUnsafe», and «script»." | |||
| 6998 | constexpr nsLiteralString elementSink = u"Element setHTMLUnsafe"_ns; | |||
| 6999 | constexpr nsLiteralString shadowRootSink = u"ShadowRoot setHTMLUnsafe"_ns; | |||
| 7000 | Maybe<nsAutoString> compliantStringHolder; | |||
| 7001 | const nsAString* compliantString = | |||
| 7002 | TrustedTypeUtils::GetTrustedTypesCompliantString( | |||
| 7003 | aSource, aIsShadowRoot ? shadowRootSink : elementSink, | |||
| 7004 | kTrustedTypesOnlySinkGroup, *aContext, aSubjectPrincipal, | |||
| 7005 | compliantStringHolder, aError); | |||
| 7006 | if (aError.Failed()) { | |||
| 7007 | return; | |||
| 7008 | } | |||
| 7009 | ||||
| 7010 | // Fallback to the more optimized code below without a sanitizer. | |||
| 7011 | if (aOptions.mSanitizer.WasPassed()) { | |||
| 7012 | return SetAndFilterHTML(aTarget, aContext, *compliantString, | |||
| 7013 | aOptions.mSanitizer.Value(), /* aSafe */ false, | |||
| 7014 | aError); | |||
| 7015 | } | |||
| 7016 | ||||
| 7017 | RefPtr<DocumentFragment> fragment; | |||
| 7018 | { | |||
| 7019 | MOZ_ASSERT(!sFragmentParsingActive,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sFragmentParsingActive)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sFragmentParsingActive))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!sFragmentParsingActive" " (" "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive" ") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence (__null, 7020); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 7020 | "Re-entrant fragment parsing attempted.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sFragmentParsingActive)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sFragmentParsingActive))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!sFragmentParsingActive" " (" "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive" ") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence (__null, 7020); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7021 | mozilla::AutoRestore<bool> guard(sFragmentParsingActive); | |||
| 7022 | sFragmentParsingActive = true; | |||
| 7023 | if (!sHTMLFragmentParser) { | |||
| 7024 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
| 7025 | // Now sHTMLFragmentParser owns the object | |||
| 7026 | } | |||
| 7027 | ||||
| 7028 | nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom(); | |||
| 7029 | int32_t contextNameSpaceID = aContext->GetNameSpaceID(); | |||
| 7030 | ||||
| 7031 | // https://html.spec.whatwg.org/#html-fragment-parsing-algorithm | |||
| 7032 | // 11. Let root be the result of creating an element given document, | |||
| 7033 | // 'html', the HTML namespace, null, null, false, and context's | |||
| 7034 | // custom element registry. | |||
| 7035 | Maybe<RefPtr<CustomElementRegistry>> customElementRegistry; | |||
| 7036 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 7037 | customElementRegistry.emplace(aContext->GetCustomElementRegistry()); | |||
| 7038 | } | |||
| 7039 | ||||
| 7040 | RefPtr<Document> doc = aTarget->OwnerDoc(); | |||
| 7041 | fragment = doc->CreateDocumentFragment(); | |||
| 7042 | ||||
| 7043 | // XXX: Steps 1-3 are performed together by ParseFragment, which parses | |||
| 7044 | // directly into the DocumentFragment. | |||
| 7045 | nsresult rv = sHTMLFragmentParser->ParseFragment( | |||
| 7046 | *compliantString, fragment, contextLocalName, contextNameSpaceID, | |||
| 7047 | fragment->OwnerDoc()->GetCompatibilityMode() == | |||
| 7048 | eCompatibility_NavQuirks, | |||
| 7049 | true, true, std::move(customElementRegistry)); | |||
| 7050 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 7051 | NS_WARNING("Failed to parse fragment for SetHTMLUnsafe")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse fragment for SetHTMLUnsafe" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7051); | |||
| 7052 | } | |||
| 7053 | } | |||
| 7054 | ||||
| 7055 | // Step 4. "Replace all with fragment within target." | |||
| 7056 | aTarget->ReplaceChildren(fragment, IgnoreErrors()); | |||
| 7057 | } | |||
| 7058 | ||||
| 7059 | // We sanitize if the fragment occurs in a system privileged | |||
| 7060 | // context, an about: page, or if there are explicit sanitization flags. | |||
| 7061 | // Please note that about:blank and about:srcdoc inherit the security | |||
| 7062 | // context from the embedding context and hence are not loaded using | |||
| 7063 | // an about: scheme principal. | |||
| 7064 | bool ShouldSanitize(nsIPrincipal* aPrincipal, int32_t aFlags) { | |||
| 7065 | // We don't need to sanitize for setHTML(), which uses | |||
| 7066 | // kParseFragmentNoSanitization. | |||
| 7067 | if (aFlags == nsContentUtils::kParseFragmentNoSanitization) { | |||
| 7068 | return false; | |||
| 7069 | } | |||
| 7070 | ||||
| 7071 | if (aFlags >= 0) { | |||
| 7072 | return true; | |||
| 7073 | } | |||
| 7074 | ||||
| 7075 | MOZ_ASSERT(aFlags ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7076); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization" ")"); do { MOZ_CrashSequence(__null, 7076); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 7076 | nsContentUtils::kParseFragmentPrivilegedDefaultSanitization)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7076); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization" ")"); do { MOZ_CrashSequence(__null, 7076); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7077 | return aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about"); | |||
| 7078 | } | |||
| 7079 | ||||
| 7080 | // Helper function to compuate Sanitization Flags for ParseFramentHTML/XML | |||
| 7081 | uint32_t ComputeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) { | |||
| 7082 | MOZ_ASSERT(aFlags ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7084); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" ")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 7083 | nsContentUtils::kParseFragmentPrivilegedDefaultSanitization ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7084); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" ")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 7084 | aFlags >= 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7084); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0" ")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7085 | ||||
| 7086 | if (aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about")) { | |||
| 7087 | if (aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization) { | |||
| 7088 | // If this is a chrome-privileged document and no explicit flags | |||
| 7089 | // were passed, then use these sanitization flags. | |||
| 7090 | return nsIParserUtils::SanitizerAllowStyle | | |||
| 7091 | nsIParserUtils::SanitizerAllowComments | | |||
| 7092 | // Don't drop forms in about: to avoid breaking existing users | |||
| 7093 | (aPrincipal->IsSystemPrincipal() | |||
| 7094 | ? nsIParserUtils::SanitizerDropForms | |||
| 7095 | : 0) | | |||
| 7096 | nsIParserUtils::SanitizerLogRemovals; | |||
| 7097 | } | |||
| 7098 | ||||
| 7099 | // If the caller explicitly passes flags, then we use those | |||
| 7100 | // flags but additionally drop forms. | |||
| 7101 | return aFlags | nsIParserUtils::SanitizerDropForms; | |||
| 7102 | } | |||
| 7103 | ||||
| 7104 | if (aFlags >= 0) { | |||
| 7105 | // aFlags by default is -1 and is only ever non equal to -1 if the | |||
| 7106 | // caller of ParseFragmentHTML/ParseFragmentXML is | |||
| 7107 | // ParserUtils::ParseFragment(). Only in that case we should use | |||
| 7108 | // the sanitization flags passed within aFlags. | |||
| 7109 | return aFlags; | |||
| 7110 | } | |||
| 7111 | ||||
| 7112 | MOZ_ASSERT_UNREACHABLE("We should have explicit flags")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "We should have explicit flags" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "We should have explicit flags" ")" ); do { MOZ_CrashSequence(__null, 7112); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7113 | return 0; | |||
| 7114 | } | |||
| 7115 | ||||
| 7116 | /* https://html.spec.whatwg.org/#html-fragment-parsing-algorithm */ | |||
| 7117 | /* static */ | |||
| 7118 | nsresult nsContentUtils::ParseFragmentHTML( | |||
| 7119 | const nsAString& aSourceBuffer, nsIContent* aTargetNode, | |||
| 7120 | nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks, | |||
| 7121 | bool aPreventScriptExecution, int32_t aFlags, | |||
| 7122 | mozilla::Maybe<RefPtr<mozilla::dom::CustomElementRegistry>> | |||
| 7123 | aCustomElementRegistry) { | |||
| 7124 | if (nsContentUtils::sFragmentParsingActive) { | |||
| 7125 | MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence(__null, 7125); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7126 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
| 7127 | } | |||
| 7128 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
| 7129 | nsContentUtils::sFragmentParsingActive = true; | |||
| 7130 | if (!sHTMLFragmentParser) { | |||
| 7131 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
| 7132 | // Now sHTMLFragmentParser owns the object | |||
| 7133 | } | |||
| 7134 | ||||
| 7135 | nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal(); | |||
| 7136 | ||||
| 7137 | #ifdef DEBUG1 | |||
| 7138 | // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless | |||
| 7139 | // the caller of ParseFragmentHTML is ParserUtils::ParseFragment() which is | |||
| 7140 | // the only caller that intends sanitization. For all other callers we need to | |||
| 7141 | // ensure to call AuditParsingOfHTMLXMLFragments. | |||
| 7142 | // | |||
| 7143 | // For SetHTML the flag is kParseFragmentNoSanitization, because that function | |||
| 7144 | // already sanitizes. | |||
| 7145 | if (aFlags == kParseFragmentPrivilegedDefaultSanitization) { | |||
| 7146 | DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal, | |||
| 7147 | aSourceBuffer); | |||
| 7148 | } | |||
| 7149 | #endif | |||
| 7150 | ||||
| 7151 | nsIContent* target = aTargetNode; | |||
| 7152 | ||||
| 7153 | RefPtr<Document> doc = aTargetNode->OwnerDoc(); | |||
| 7154 | RefPtr<DocumentFragment> fragment; | |||
| 7155 | ||||
| 7156 | if (ShouldSanitize(nodePrincipal, aFlags)) { | |||
| 7157 | if (!doc->IsLoadedAsData()) { | |||
| 7158 | doc = nsContentUtils::CreateInertHTMLDocument(doc); | |||
| 7159 | if (!doc) { | |||
| 7160 | return NS_ERROR_FAILURE; | |||
| 7161 | } | |||
| 7162 | } | |||
| 7163 | fragment = | |||
| 7164 | new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager()); | |||
| 7165 | target = fragment; | |||
| 7166 | } | |||
| 7167 | ||||
| 7168 | nsresult rv = sHTMLFragmentParser->ParseFragment( | |||
| 7169 | aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks, | |||
| 7170 | aPreventScriptExecution, false, std::move(aCustomElementRegistry)); | |||
| 7171 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7171); return rv; } } while (false); | |||
| 7172 | ||||
| 7173 | if (fragment) { | |||
| 7174 | uint32_t sanitizationFlags = | |||
| 7175 | ComputeSanitizationFlags(nodePrincipal, aFlags); | |||
| 7176 | // Don't fire mutation events for nodes removed by the sanitizer. | |||
| 7177 | nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; | |||
| 7178 | nsTreeSanitizer sanitizer(sanitizationFlags); | |||
| 7179 | sanitizer.Sanitize(fragment); | |||
| 7180 | ||||
| 7181 | ErrorResult error; | |||
| 7182 | aTargetNode->AppendChild(*fragment, error); | |||
| 7183 | rv = error.StealNSResult(); | |||
| 7184 | } | |||
| 7185 | ||||
| 7186 | return rv; | |||
| 7187 | } | |||
| 7188 | ||||
| 7189 | /* static */ | |||
| 7190 | nsresult nsContentUtils::ParseDocumentHTML( | |||
| 7191 | const nsAString& aSourceBuffer, Document* aTargetDocument, | |||
| 7192 | bool aScriptingEnabledForNoscriptParsing) { | |||
| 7193 | if (nsContentUtils::sFragmentParsingActive) { | |||
| 7194 | MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence(__null, 7194); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7195 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
| 7196 | } | |||
| 7197 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
| 7198 | nsContentUtils::sFragmentParsingActive = true; | |||
| 7199 | if (!sHTMLFragmentParser) { | |||
| 7200 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
| 7201 | // Now sHTMLFragmentParser owns the object | |||
| 7202 | } | |||
| 7203 | nsresult rv = sHTMLFragmentParser->ParseDocument( | |||
| 7204 | aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing); | |||
| 7205 | return rv; | |||
| 7206 | } | |||
| 7207 | ||||
| 7208 | /* static */ | |||
| 7209 | nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer, | |||
| 7210 | Document* aDocument, | |||
| 7211 | nsTArray<nsString>& aTagStack, | |||
| 7212 | bool aPreventScriptExecution, | |||
| 7213 | int32_t aFlags, | |||
| 7214 | DocumentFragment** aReturn) { | |||
| 7215 | if (nsContentUtils::sFragmentParsingActive) { | |||
| 7216 | MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence(__null, 7216); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7217 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
| 7218 | } | |||
| 7219 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
| 7220 | nsContentUtils::sFragmentParsingActive = true; | |||
| 7221 | if (!sXMLFragmentParser) { | |||
| 7222 | RefPtr<nsParser> parser = new nsParser(); | |||
| 7223 | parser.forget(&sXMLFragmentParser); | |||
| 7224 | // sXMLFragmentParser now owns the parser | |||
| 7225 | } | |||
| 7226 | if (!sXMLFragmentSink) { | |||
| 7227 | NS_NewXMLFragmentContentSink(&sXMLFragmentSink); | |||
| 7228 | // sXMLFragmentSink now owns the sink | |||
| 7229 | } | |||
| 7230 | nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink); | |||
| 7231 | MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(contentsink)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(contentsink))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("contentsink" " (" "Sink doesn't QI to nsIContentSink!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink" ") (" "Sink doesn't QI to nsIContentSink!" ")"); do { MOZ_CrashSequence (__null, 7231); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7232 | sXMLFragmentParser->SetContentSink(contentsink); | |||
| 7233 | ||||
| 7234 | RefPtr<Document> doc; | |||
| 7235 | nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal(); | |||
| 7236 | ||||
| 7237 | #ifdef DEBUG1 | |||
| 7238 | // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless | |||
| 7239 | // the caller of ParseFragmentXML is ParserUtils::ParseFragment() which is the | |||
| 7240 | // only caller that intends sanitization. For all other callers we need to | |||
| 7241 | // ensure to call AuditParsingOfHTMLXMLFragments. | |||
| 7242 | if (aFlags == kParseFragmentPrivilegedDefaultSanitization) { | |||
| 7243 | DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal, | |||
| 7244 | aSourceBuffer); | |||
| 7245 | } | |||
| 7246 | #endif | |||
| 7247 | ||||
| 7248 | bool shouldSanitize = ShouldSanitize(nodePrincipal, aFlags); | |||
| 7249 | if (shouldSanitize && !aDocument->IsLoadedAsData()) { | |||
| 7250 | doc = nsContentUtils::CreateInertXMLDocument(aDocument); | |||
| 7251 | } else { | |||
| 7252 | doc = aDocument; | |||
| 7253 | } | |||
| 7254 | ||||
| 7255 | sXMLFragmentSink->SetTargetDocument(doc); | |||
| 7256 | sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); | |||
| 7257 | ||||
| 7258 | nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); | |||
| 7259 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 7260 | // Drop the fragment parser and sink that might be in an inconsistent state | |||
| 7261 | NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release (); (sXMLFragmentParser) = 0; } } while (0); | |||
| 7262 | NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release() ; (sXMLFragmentSink) = 0; } } while (0); | |||
| 7263 | return rv; | |||
| 7264 | } | |||
| 7265 | ||||
| 7266 | rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); | |||
| 7267 | ||||
| 7268 | sXMLFragmentParser->Reset(); | |||
| 7269 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7269); return rv; } } while (false); | |||
| 7270 | ||||
| 7271 | if (shouldSanitize) { | |||
| 7272 | uint32_t sanitizationFlags = | |||
| 7273 | ComputeSanitizationFlags(nodePrincipal, aFlags); | |||
| 7274 | // Don't fire mutation events for nodes removed by the sanitizer. | |||
| 7275 | nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; | |||
| 7276 | nsTreeSanitizer sanitizer(sanitizationFlags); | |||
| 7277 | sanitizer.Sanitize(*aReturn); | |||
| 7278 | } | |||
| 7279 | ||||
| 7280 | return rv; | |||
| 7281 | } | |||
| 7282 | ||||
| 7283 | /* static */ | |||
| 7284 | nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer, | |||
| 7285 | nsAString& aResultBuffer, | |||
| 7286 | uint32_t aFlags, | |||
| 7287 | uint32_t aWrapCol) { | |||
| 7288 | RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr); | |||
| 7289 | if (!document) { | |||
| 7290 | return NS_ERROR_FAILURE; | |||
| 7291 | } | |||
| 7292 | ||||
| 7293 | nsresult rv = nsContentUtils::ParseDocumentHTML( | |||
| 7294 | aSourceBuffer, document, | |||
| 7295 | !(aFlags & nsIDocumentEncoder::OutputNoScriptContent)); | |||
| 7296 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7296); return rv; } } while (false); | |||
| 7297 | ||||
| 7298 | nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain"); | |||
| 7299 | ||||
| 7300 | rv = encoder->Init(document, u"text/plain"_ns, aFlags); | |||
| 7301 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7301); return rv; } } while (false); | |||
| 7302 | ||||
| 7303 | encoder->SetWrapColumn(aWrapCol); | |||
| 7304 | ||||
| 7305 | return encoder->EncodeToString(aResultBuffer); | |||
| 7306 | } | |||
| 7307 | ||||
| 7308 | static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate, | |||
| 7309 | DocumentFlavor aFlavor) { | |||
| 7310 | if (aTemplate) { | |||
| 7311 | bool hasHad = true; | |||
| 7312 | nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad); | |||
| 7313 | NS_ENSURE_TRUE(sgo || !hasHad, nullptr)do { if ((__builtin_expect(!!(!(sgo || !hasHad)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sgo || !hasHad" ") failed" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7313); return nullptr; } } while (false); | |||
| 7314 | ||||
| 7315 | nsCOMPtr<Document> doc; | |||
| 7316 | nsresult rv = NS_NewDOMDocument( | |||
| 7317 | getter_AddRefs(doc), u""_ns, u""_ns, nullptr, | |||
| 7318 | aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(), | |||
| 7319 | aTemplate->NodePrincipal(), LoadedAsData::AsData, sgo, aFlavor); | |||
| 7320 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 7321 | return nullptr; | |||
| 7322 | } | |||
| 7323 | return doc.forget(); | |||
| 7324 | } | |||
| 7325 | nsCOMPtr<nsIURI> uri; | |||
| 7326 | NS_NewURI(getter_AddRefs(uri), "about:blank"_ns); | |||
| 7327 | if (!uri) { | |||
| 7328 | return nullptr; | |||
| 7329 | } | |||
| 7330 | ||||
| 7331 | RefPtr<NullPrincipal> nullPrincipal = | |||
| 7332 | NullPrincipal::CreateWithoutOriginAttributes(); | |||
| 7333 | if (!nullPrincipal) { | |||
| 7334 | return nullptr; | |||
| 7335 | } | |||
| 7336 | ||||
| 7337 | nsCOMPtr<Document> doc; | |||
| 7338 | nsresult rv = | |||
| 7339 | NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri, | |||
| 7340 | nullPrincipal, LoadedAsData::AsData, nullptr, aFlavor); | |||
| 7341 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 7342 | return nullptr; | |||
| 7343 | } | |||
| 7344 | return doc.forget(); | |||
| 7345 | } | |||
| 7346 | ||||
| 7347 | /* static */ | |||
| 7348 | already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument( | |||
| 7349 | const Document* aTemplate) { | |||
| 7350 | return CreateInertDocument(aTemplate, DocumentFlavor::XML); | |||
| 7351 | } | |||
| 7352 | ||||
| 7353 | /* static */ | |||
| 7354 | already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument( | |||
| 7355 | const Document* aTemplate) { | |||
| 7356 | return CreateInertDocument(aTemplate, DocumentFlavor::HTML); | |||
| 7357 | } | |||
| 7358 | ||||
| 7359 | /* static */ | |||
| 7360 | nsresult nsContentUtils::SetNodeTextContent( | |||
| 7361 | nsIContent* aContent, const nsAString& aValue, bool aTryReuse, | |||
| 7362 | MutationEffectOnScript aMutationEffectOnScript) { | |||
| 7363 | // Optimize the common case of there being no observers | |||
| 7364 | if (MOZ_UNLIKELY((__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc ()), 0)) | |||
| 7365 | aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())(__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc ()), 0))) { | |||
| 7366 | if (aTryReuse) { | |||
| 7367 | bool skipFirstText = true; | |||
| 7368 | for (nsCOMPtr<nsINode> child = aContent->GetFirstChild(); | |||
| 7369 | child && child->GetParentNode() == aContent; | |||
| 7370 | child = child->GetNextSibling()) { | |||
| 7371 | if (skipFirstText && child->IsText()) { | |||
| 7372 | skipFirstText = false; | |||
| 7373 | continue; | |||
| 7374 | } | |||
| 7375 | nsContentUtils::NotifyDevToolsOfNodeRemoval(*child); | |||
| 7376 | } | |||
| 7377 | } else { | |||
| 7378 | aContent->NotifyDevToolsOfRemovalsOfChildren(); | |||
| 7379 | } | |||
| 7380 | } | |||
| 7381 | ||||
| 7382 | // Might as well stick a batch around this since we're performing several | |||
| 7383 | // mutations. | |||
| 7384 | mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true); | |||
| 7385 | nsAutoMutationBatch mb; | |||
| 7386 | ||||
| 7387 | if (aTryReuse && !aValue.IsEmpty()) { | |||
| 7388 | // Let's remove nodes until we find a eTEXT. | |||
| 7389 | while (aContent->HasChildren()) { | |||
| 7390 | nsIContent* child = aContent->GetFirstChild(); | |||
| 7391 | if (child->IsText()) { | |||
| 7392 | break; | |||
| 7393 | } | |||
| 7394 | aContent->RemoveChildNode(child, true, nullptr, nullptr, | |||
| 7395 | aMutationEffectOnScript); | |||
| 7396 | } | |||
| 7397 | ||||
| 7398 | // If we have a node, it must be a eTEXT and we reuse it. | |||
| 7399 | if (aContent->HasChildren()) { | |||
| 7400 | nsIContent* child = aContent->GetFirstChild(); | |||
| 7401 | nsresult rv = child->AsText()->SetText(aValue, true); | |||
| 7402 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7402); return rv; } } while (false); | |||
| 7403 | ||||
| 7404 | // All the following nodes, if they exist, must be deleted. | |||
| 7405 | while (nsIContent* lastChild = aContent->GetLastChild()) { | |||
| 7406 | if (lastChild == child) { | |||
| 7407 | break; | |||
| 7408 | } | |||
| 7409 | aContent->RemoveChildNode(lastChild, true, nullptr, nullptr, | |||
| 7410 | aMutationEffectOnScript); | |||
| 7411 | } | |||
| 7412 | } | |||
| 7413 | ||||
| 7414 | if (aContent->HasChildren()) { | |||
| 7415 | return NS_OK; | |||
| 7416 | } | |||
| 7417 | } else { | |||
| 7418 | mb.Init(aContent, true, false); | |||
| 7419 | aContent->RemoveAllChildren(true); | |||
| 7420 | } | |||
| 7421 | mb.RemovalDone(); | |||
| 7422 | ||||
| 7423 | if (aValue.IsEmpty()) { | |||
| 7424 | return NS_OK; | |||
| 7425 | } | |||
| 7426 | ||||
| 7427 | RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager()) | |||
| 7428 | nsTextNode(aContent->NodeInfo()->NodeInfoManager()); | |||
| 7429 | ||||
| 7430 | textContent->SetText(aValue, true); | |||
| 7431 | ||||
| 7432 | ErrorResult rv; | |||
| 7433 | aContent->AppendChildTo(textContent, true, rv, aMutationEffectOnScript); | |||
| 7434 | mb.NodesAdded(); | |||
| 7435 | return rv.StealNSResult(); | |||
| 7436 | } | |||
| 7437 | ||||
| 7438 | template <typename CharT> | |||
| 7439 | static bool AppendNodeTextContentsRecurse(const nsINode* aNode, | |||
| 7440 | nsTSubstring<CharT>& aResult, | |||
| 7441 | const fallible_t& aFallible) { | |||
| 7442 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
| 7443 | child = child->GetNextSibling()) { | |||
| 7444 | if (child->IsElement()) { | |||
| 7445 | if (!AppendNodeTextContentsRecurse(child, aResult, aFallible)) { | |||
| 7446 | return false; | |||
| 7447 | } | |||
| 7448 | } else if (Text* text = child->GetAsText()) { | |||
| 7449 | if (!text->AppendTextTo(aResult, aFallible)) { | |||
| 7450 | return false; | |||
| 7451 | } | |||
| 7452 | } | |||
| 7453 | } | |||
| 7454 | return true; | |||
| 7455 | } | |||
| 7456 | ||||
| 7457 | template <typename CharT> | |||
| 7458 | static bool AppendNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 7459 | nsTSubstring<CharT>& aResult, | |||
| 7460 | const fallible_t& aFallible) { | |||
| 7461 | if (const Text* text = aNode->GetAsText()) { | |||
| 7462 | return text->AppendTextTo(aResult, aFallible); | |||
| 7463 | } | |||
| 7464 | if (aDeep) { | |||
| 7465 | return AppendNodeTextContentsRecurse(aNode, aResult, aFallible); | |||
| 7466 | } | |||
| 7467 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
| 7468 | child = child->GetNextSibling()) { | |||
| 7469 | if (Text* text = child->GetAsText()) { | |||
| 7470 | bool ok = text->AppendTextTo(aResult, fallible); | |||
| 7471 | if (!ok) { | |||
| 7472 | return false; | |||
| 7473 | } | |||
| 7474 | } | |||
| 7475 | } | |||
| 7476 | return true; | |||
| 7477 | } | |||
| 7478 | ||||
| 7479 | /* static */ | |||
| 7480 | bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 7481 | nsAString& aResult, | |||
| 7482 | const fallible_t& aFallible) { | |||
| 7483 | return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible); | |||
| 7484 | } | |||
| 7485 | ||||
| 7486 | bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 7487 | nsACString& aResult, | |||
| 7488 | const fallible_t& aFallible) { | |||
| 7489 | return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible); | |||
| 7490 | } | |||
| 7491 | ||||
| 7492 | bool nsContentUtils::HasNonEmptyTextContent( | |||
| 7493 | nsINode* aNode, TextContentDiscoverMode aDiscoverMode) { | |||
| 7494 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
| 7495 | child = child->GetNextSibling()) { | |||
| 7496 | if (child->IsText() && child->TextLength() > 0) { | |||
| 7497 | return true; | |||
| 7498 | } | |||
| 7499 | ||||
| 7500 | if (aDiscoverMode == eRecurseIntoChildren && | |||
| 7501 | HasNonEmptyTextContent(child, aDiscoverMode)) { | |||
| 7502 | return true; | |||
| 7503 | } | |||
| 7504 | } | |||
| 7505 | ||||
| 7506 | return false; | |||
| 7507 | } | |||
| 7508 | ||||
| 7509 | /* static */ | |||
| 7510 | bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode, | |||
| 7511 | const nsINode* aOtherNode) { | |||
| 7512 | MOZ_ASSERT(aNode, "Must have a node to work with")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aNode))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("aNode" " (" "Must have a node to work with" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7512 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "Must have a node to work with" ")"); do { MOZ_CrashSequence(__null, 7512); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7513 | MOZ_ASSERT(aOtherNode, "Must have a content to work with")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOtherNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOtherNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aOtherNode" " (" "Must have a content to work with" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7513 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode" ") (" "Must have a content to work with" ")"); do { MOZ_CrashSequence (__null, 7513); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7514 | ||||
| 7515 | const bool anon = aNode->IsInNativeAnonymousSubtree(); | |||
| 7516 | if (anon != aOtherNode->IsInNativeAnonymousSubtree()) { | |||
| 7517 | return false; | |||
| 7518 | } | |||
| 7519 | ||||
| 7520 | if (anon) { | |||
| 7521 | return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() == | |||
| 7522 | aNode->GetClosestNativeAnonymousSubtreeRoot(); | |||
| 7523 | } | |||
| 7524 | ||||
| 7525 | // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't | |||
| 7526 | // use to either. Maybe that's fine. | |||
| 7527 | return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow(); | |||
| 7528 | } | |||
| 7529 | ||||
| 7530 | /* static */ | |||
| 7531 | bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement, | |||
| 7532 | const Element* aStop) { | |||
| 7533 | const Element* element = aElement; | |||
| 7534 | while (element && element != aStop) { | |||
| 7535 | if (element->IsInteractiveHTMLContent()) { | |||
| 7536 | return true; | |||
| 7537 | } | |||
| 7538 | element = element->GetFlattenedTreeParentElement(); | |||
| 7539 | } | |||
| 7540 | return false; | |||
| 7541 | } | |||
| 7542 | ||||
| 7543 | /* static */ | |||
| 7544 | void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) { | |||
| 7545 | IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling); | |||
| 7546 | } | |||
| 7547 | ||||
| 7548 | /* static */ | |||
| 7549 | bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) { | |||
| 7550 | nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI); | |||
| 7551 | NS_ENSURE_TRUE(baseURI, false)do { if ((__builtin_expect(!!(!(baseURI)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "baseURI" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7551); return false; } } while (false); | |||
| 7552 | return baseURI->SchemeIs(aScheme); | |||
| 7553 | } | |||
| 7554 | ||||
| 7555 | bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) { | |||
| 7556 | return aPrincipal && aPrincipal->GetIsExpandedPrincipal(); | |||
| 7557 | } | |||
| 7558 | ||||
| 7559 | bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) { | |||
| 7560 | return (aPrincipal && aPrincipal->IsSystemPrincipal()) || | |||
| 7561 | IsExpandedPrincipal(aPrincipal); | |||
| 7562 | } | |||
| 7563 | ||||
| 7564 | nsIPrincipal* nsContentUtils::GetSystemPrincipal() { | |||
| 7565 | MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInitialized()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7565); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence (__null, 7565); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7566 | return sSystemPrincipal; | |||
| 7567 | } | |||
| 7568 | ||||
| 7569 | bool nsContentUtils::CombineResourcePrincipals( | |||
| 7570 | nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) { | |||
| 7571 | if (!aExtraPrincipal) { | |||
| 7572 | return false; | |||
| 7573 | } | |||
| 7574 | if (!*aResourcePrincipal) { | |||
| 7575 | *aResourcePrincipal = aExtraPrincipal; | |||
| 7576 | return true; | |||
| 7577 | } | |||
| 7578 | if (*aResourcePrincipal == aExtraPrincipal) { | |||
| 7579 | return false; | |||
| 7580 | } | |||
| 7581 | bool subsumes; | |||
| 7582 | if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal )->Subsumes(aExtraPrincipal, &subsumes))), 1))) | |||
| 7583 | (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal )->Subsumes(aExtraPrincipal, &subsumes))), 1))) && | |||
| 7584 | subsumes) { | |||
| 7585 | return false; | |||
| 7586 | } | |||
| 7587 | *aResourcePrincipal = sSystemPrincipal; | |||
| 7588 | return true; | |||
| 7589 | } | |||
| 7590 | ||||
| 7591 | /* static */ | |||
| 7592 | void nsContentUtils::TriggerLinkClick( | |||
| 7593 | nsIContent* aContent, nsIURI* aLinkURI, const nsString& aTargetSpec, | |||
| 7594 | UserNavigationInvolvement aUserInvolvement) { | |||
| 7595 | MOZ_ASSERT(aLinkURI, "No link URI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLinkURI)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLinkURI))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLinkURI" " (" "No link URI" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7595 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI" ")"); do { MOZ_CrashSequence(__null, 7595); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7596 | ||||
| 7597 | if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) { | |||
| 7598 | return; | |||
| 7599 | } | |||
| 7600 | ||||
| 7601 | RefPtr<nsDocShell> docShell = | |||
| 7602 | nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell()); | |||
| 7603 | if (!docShell) { | |||
| 7604 | return; | |||
| 7605 | } | |||
| 7606 | ||||
| 7607 | // Check that this page is allowed to load this URI. | |||
| 7608 | nsresult proceed = NS_OK; | |||
| 7609 | ||||
| 7610 | if (sSecurityManager) { | |||
| 7611 | uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD); | |||
| 7612 | proceed = sSecurityManager->CheckLoadURIWithPrincipal( | |||
| 7613 | aContent->NodePrincipal(), aLinkURI, flag, | |||
| 7614 | aContent->OwnerDoc()->InnerWindowID()); | |||
| 7615 | } | |||
| 7616 | ||||
| 7617 | // Only pass off the click event if the script security manager says it's ok. | |||
| 7618 | // We need to rest aTargetSpec for forced downloads. | |||
| 7619 | if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) { | |||
| 7620 | // A link/area element with a download attribute is allowed to set | |||
| 7621 | // a pseudo Content-Disposition header. | |||
| 7622 | // For security reasons we only allow websites to declare same-origin | |||
| 7623 | // resources as downloadable. If this check fails we will just do the normal | |||
| 7624 | // thing (i.e. navigate to the resource). | |||
| 7625 | nsAutoString fileName; | |||
| 7626 | if ((!aContent->IsHTMLElement(nsGkAtoms::a) && | |||
| 7627 | !aContent->IsHTMLElement(nsGkAtoms::area) && | |||
| 7628 | !aContent->IsSVGElement(nsGkAtoms::a)) || | |||
| 7629 | !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) || | |||
| 7630 | NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal ()->CheckMayLoad(aLinkURI, true))), 0)))) { | |||
| 7631 | fileName.SetIsVoid(true); // No actionable download attribute was found. | |||
| 7632 | } | |||
| 7633 | ||||
| 7634 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal(); | |||
| 7635 | nsCOMPtr<nsIPolicyContainer> policyContainer = | |||
| 7636 | aContent->GetPolicyContainer(); | |||
| 7637 | ||||
| 7638 | // Sanitize fileNames containing null characters by replacing them with | |||
| 7639 | // underscores. | |||
| 7640 | if (!fileName.IsVoid()) { | |||
| 7641 | fileName.ReplaceChar(char16_t(0), '_'); | |||
| 7642 | } | |||
| 7643 | ||||
| 7644 | docShell->OnLinkClick( | |||
| 7645 | aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName, | |||
| 7646 | nullptr, nullptr, UserActivation::IsHandlingUserInput(), | |||
| 7647 | aUserInvolvement, triggeringPrincipal, policyContainer); | |||
| 7648 | } | |||
| 7649 | } | |||
| 7650 | ||||
| 7651 | /* static */ | |||
| 7652 | void nsContentUtils::TriggerLinkMouseOver(nsIContent* aContent, | |||
| 7653 | nsIURI* aLinkURI, | |||
| 7654 | const nsString& aTargetSpec) { | |||
| 7655 | MOZ_ASSERT(aLinkURI, "No link URI")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLinkURI)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLinkURI))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLinkURI" " (" "No link URI" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7655 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI" ")"); do { MOZ_CrashSequence(__null, 7655); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7656 | ||||
| 7657 | if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) { | |||
| 7658 | return; | |||
| 7659 | } | |||
| 7660 | ||||
| 7661 | RefPtr<nsDocShell> docShell = | |||
| 7662 | nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell()); | |||
| 7663 | if (!docShell) { | |||
| 7664 | return; | |||
| 7665 | } | |||
| 7666 | ||||
| 7667 | docShell->OnOverLink(aContent, aLinkURI, aTargetSpec); | |||
| 7668 | ||||
| 7669 | if (nsPresContext* pc = aContent->OwnerDoc()->GetPresContext()) { | |||
| 7670 | pc->EventStateManager()->SetLinkOverFrame(aContent->GetPrimaryFrame()); | |||
| 7671 | } | |||
| 7672 | } | |||
| 7673 | ||||
| 7674 | /* static */ | |||
| 7675 | void nsContentUtils::GetLinkLocation(Element* aElement, | |||
| 7676 | nsString& aLocationString) { | |||
| 7677 | nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI(); | |||
| 7678 | if (hrefURI) { | |||
| 7679 | nsAutoCString specUTF8; | |||
| 7680 | nsresult rv = hrefURI->GetSpec(specUTF8); | |||
| 7681 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString); | |||
| 7682 | } | |||
| 7683 | } | |||
| 7684 | ||||
| 7685 | /* static */ | |||
| 7686 | nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) { | |||
| 7687 | if (!aWidget) return nullptr; | |||
| 7688 | ||||
| 7689 | return aWidget->GetTopLevelWidget(); | |||
| 7690 | } | |||
| 7691 | ||||
| 7692 | /* static */ | |||
| 7693 | const nsDependentString nsContentUtils::GetLocalizedEllipsis() { | |||
| 7694 | static char16_t sBuf[4] = {0, 0, 0, 0}; | |||
| 7695 | if (!sBuf[0]) { | |||
| 7696 | if (!nsContentUtils::ShouldResistFingerprinting("No context", | |||
| 7697 | RFPTarget::JSLocale)) { | |||
| 7698 | nsAutoString tmp; | |||
| 7699 | intl::LocaleService::GetInstance()->GetEllipsis(tmp); | |||
| 7700 | uint32_t len = | |||
| 7701 | std::min(uint32_t(tmp.Length()), uint32_t(std::size(sBuf) - 1)); | |||
| 7702 | CopyUnicodeTo(tmp, 0, sBuf, len); | |||
| 7703 | } | |||
| 7704 | if (!sBuf[0]) { | |||
| 7705 | sBuf[0] = char16_t(0x2026); | |||
| 7706 | } | |||
| 7707 | } | |||
| 7708 | return nsDependentString(sBuf); | |||
| 7709 | } | |||
| 7710 | ||||
| 7711 | /* static */ | |||
| 7712 | void nsContentUtils::AddScriptBlocker() { | |||
| 7713 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7713); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 7713); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7714 | if (!sScriptBlockerCount) { | |||
| 7715 | MOZ_ASSERT(sRunnersCountAtFirstBlocker == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype(sRunnersCountAtFirstBlocker == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sRunnersCountAtFirstBlocker == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sRunnersCountAtFirstBlocker == 0" " (" "Should not already have a count" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7716 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0" ") (" "Should not already have a count" ")"); do { MOZ_CrashSequence (__null, 7716); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 7716 | "Should not already have a count")do { static_assert( mozilla::detail::AssertionConditionType< decltype(sRunnersCountAtFirstBlocker == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sRunnersCountAtFirstBlocker == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sRunnersCountAtFirstBlocker == 0" " (" "Should not already have a count" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7716 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0" ") (" "Should not already have a count" ")"); do { MOZ_CrashSequence (__null, 7716); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7717 | sRunnersCountAtFirstBlocker = | |||
| 7718 | sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0; | |||
| 7719 | } | |||
| 7720 | ++sScriptBlockerCount; | |||
| 7721 | } | |||
| 7722 | ||||
| 7723 | #ifdef DEBUG1 | |||
| 7724 | static bool sRemovingScriptBlockers = false; | |||
| 7725 | #endif | |||
| 7726 | ||||
| 7727 | /* static */ | |||
| 7728 | void nsContentUtils::RemoveScriptBlocker() { | |||
| 7729 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7729); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 7729); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7730 | MOZ_ASSERT(!sRemovingScriptBlockers)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sRemovingScriptBlockers)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sRemovingScriptBlockers))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sRemovingScriptBlockers" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7730); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!sRemovingScriptBlockers" ")"); do { MOZ_CrashSequence (__null, 7730); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7731 | NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers")do { if (!(sScriptBlockerCount != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Negative script blockers", "sScriptBlockerCount != 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7731); MOZ_PretendNoReturn(); } } while (0); | |||
| 7732 | --sScriptBlockerCount; | |||
| 7733 | if (sScriptBlockerCount) { | |||
| 7734 | return; | |||
| 7735 | } | |||
| 7736 | ||||
| 7737 | if (!sBlockedScriptRunners) { | |||
| 7738 | return; | |||
| 7739 | } | |||
| 7740 | ||||
| 7741 | uint32_t firstBlocker = sRunnersCountAtFirstBlocker; | |||
| 7742 | uint32_t lastBlocker = sBlockedScriptRunners->Length(); | |||
| 7743 | uint32_t originalFirstBlocker = firstBlocker; | |||
| 7744 | uint32_t blockersCount = lastBlocker - firstBlocker; | |||
| 7745 | sRunnersCountAtFirstBlocker = 0; | |||
| 7746 | NS_ASSERTION(firstBlocker <= lastBlocker, "bad sRunnersCountAtFirstBlocker")do { if (!(firstBlocker <= lastBlocker)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "bad sRunnersCountAtFirstBlocker", "firstBlocker <= lastBlocker" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7746); MOZ_PretendNoReturn (); } } while (0); | |||
| 7747 | ||||
| 7748 | while (firstBlocker < lastBlocker) { | |||
| 7749 | nsCOMPtr<nsIRunnable> runnable; | |||
| 7750 | runnable.swap((*sBlockedScriptRunners)[firstBlocker]); | |||
| 7751 | ++firstBlocker; | |||
| 7752 | ||||
| 7753 | // Calling the runnable can reenter us | |||
| 7754 | { | |||
| 7755 | AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker ; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker .emplace(runnable); }; | |||
| 7756 | runnable->Run(); | |||
| 7757 | } | |||
| 7758 | // So can dropping the reference to the runnable | |||
| 7759 | runnable = nullptr; | |||
| 7760 | ||||
| 7761 | NS_ASSERTION(sRunnersCountAtFirstBlocker == 0, "Bad count")do { if (!(sRunnersCountAtFirstBlocker == 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Bad count", "sRunnersCountAtFirstBlocker == 0" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7761); MOZ_PretendNoReturn (); } } while (0); | |||
| 7762 | NS_ASSERTION(!sScriptBlockerCount, "This is really bad")do { if (!(!sScriptBlockerCount)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "This is really bad", "!sScriptBlockerCount", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7762); MOZ_PretendNoReturn(); } } while (0); | |||
| 7763 | } | |||
| 7764 | #ifdef DEBUG1 | |||
| 7765 | AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers); | |||
| 7766 | sRemovingScriptBlockers = true; | |||
| 7767 | #endif | |||
| 7768 | sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount); | |||
| 7769 | } | |||
| 7770 | ||||
| 7771 | /* static */ | |||
| 7772 | already_AddRefed<nsPIDOMWindowOuter> | |||
| 7773 | nsContentUtils::GetMostRecentNonPBWindow() { | |||
| 7774 | nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1"); | |||
| 7775 | ||||
| 7776 | nsCOMPtr<mozIDOMWindowProxy> window; | |||
| 7777 | wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window)); | |||
| 7778 | nsCOMPtr<nsPIDOMWindowOuter> pwindow; | |||
| 7779 | pwindow = do_QueryInterface(window); | |||
| 7780 | ||||
| 7781 | return pwindow.forget(); | |||
| 7782 | } | |||
| 7783 | ||||
| 7784 | /* static */ | |||
| 7785 | already_AddRefed<nsPIDOMWindowOuter> nsContentUtils::GetMostRecentWindowBy( | |||
| 7786 | WindowMediatorFilter aFilter) { | |||
| 7787 | nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1"); | |||
| 7788 | ||||
| 7789 | nsCOMPtr<mozIDOMWindowProxy> window; | |||
| 7790 | wm->GetMostRecentWindowBy(u"navigator:browser", static_cast<uint8_t>(aFilter), | |||
| 7791 | getter_AddRefs(window)); | |||
| 7792 | nsCOMPtr<nsPIDOMWindowOuter> pwindow; | |||
| 7793 | pwindow = do_QueryInterface(window); | |||
| 7794 | ||||
| 7795 | return pwindow.forget(); | |||
| 7796 | } | |||
| 7797 | ||||
| 7798 | /* static */ | |||
| 7799 | void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) { | |||
| 7800 | nsAutoString msg; | |||
| 7801 | bool privateBrowsing = false; | |||
| 7802 | bool chromeContext = false; | |||
| 7803 | ||||
| 7804 | if (aDocument) { | |||
| 7805 | nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI(); | |||
| 7806 | if (uri) { | |||
| 7807 | msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault())); | |||
| 7808 | msg.AppendLiteral(" : "); | |||
| 7809 | } | |||
| 7810 | privateBrowsing = | |||
| 7811 | aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); | |||
| 7812 | chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal(); | |||
| 7813 | } | |||
| 7814 | ||||
| 7815 | msg.AppendLiteral( | |||
| 7816 | "Unable to run script because scripts are blocked internally."); | |||
| 7817 | LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext); | |||
| 7818 | } | |||
| 7819 | ||||
| 7820 | /* static */ | |||
| 7821 | void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) { | |||
| 7822 | nsCOMPtr<nsIRunnable> runnable = aRunnable; | |||
| 7823 | if (!runnable) { | |||
| 7824 | return; | |||
| 7825 | } | |||
| 7826 | ||||
| 7827 | if (sScriptBlockerCount) { | |||
| 7828 | PROFILER_MARKER("nsContentUtils::AddScriptRunner", OTHER, {}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("nsContentUtils::AddScriptRunner", ::geckoprofiler::category ::OTHER, {}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer (runnable.get())); } } while (false); } while (false) | |||
| 7829 | Flow::FromPointer(runnable.get()))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl ("nsContentUtils::AddScriptRunner", ::geckoprofiler::category ::OTHER, {}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer (runnable.get())); } } while (false); } while (false); | |||
| 7830 | sBlockedScriptRunners->AppendElement(runnable.forget()); | |||
| 7831 | return; | |||
| 7832 | } | |||
| 7833 | ||||
| 7834 | AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker ; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker .emplace(runnable); }; | |||
| 7835 | runnable->Run(); | |||
| 7836 | } | |||
| 7837 | ||||
| 7838 | /* static */ | |||
| 7839 | void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) { | |||
| 7840 | nsCOMPtr<nsIRunnable> runnable = aRunnable; | |||
| 7841 | AddScriptRunner(runnable.forget()); | |||
| 7842 | } | |||
| 7843 | ||||
| 7844 | /* static */ bool nsContentUtils::IsSafeToRunScript() { | |||
| 7845 | MOZ_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "This static variable only makes sense on the main thread!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7846 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "This static variable only makes sense on the main thread!" ")"); do { MOZ_CrashSequence(__null, 7846); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 7846 | "This static variable only makes sense on the main thread!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "This static variable only makes sense on the main thread!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7846 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "This static variable only makes sense on the main thread!" ")"); do { MOZ_CrashSequence(__null, 7846); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 7847 | return sScriptBlockerCount == 0; | |||
| 7848 | } | |||
| 7849 | ||||
| 7850 | /* static */ | |||
| 7851 | void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) { | |||
| 7852 | MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7852 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence (__null, 7852); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7853 | CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable)); | |||
| 7854 | } | |||
| 7855 | ||||
| 7856 | /* static */ | |||
| 7857 | void nsContentUtils::AddPendingIDBTransaction( | |||
| 7858 | already_AddRefed<nsIRunnable> aTransaction) { | |||
| 7859 | MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7859 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence (__null, 7859); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7860 | CycleCollectedJSContext::Get()->AddPendingIDBTransaction( | |||
| 7861 | std::move(aTransaction)); | |||
| 7862 | } | |||
| 7863 | ||||
| 7864 | /* static */ | |||
| 7865 | bool nsContentUtils::IsInStableOrMetaStableState() { | |||
| 7866 | MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7866 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence (__null, 7866); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 7867 | return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState(); | |||
| 7868 | } | |||
| 7869 | ||||
| 7870 | /* static */ | |||
| 7871 | void nsContentUtils::HidePopupsInDocument(Document* aDocument) { | |||
| 7872 | RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance(); | |||
| 7873 | if (!pm || !aDocument) { | |||
| 7874 | return; | |||
| 7875 | } | |||
| 7876 | nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell(); | |||
| 7877 | if (docShellToHide) { | |||
| 7878 | pm->HidePopupsInDocShell(docShellToHide); | |||
| 7879 | } | |||
| 7880 | } | |||
| 7881 | ||||
| 7882 | /* static */ | |||
| 7883 | already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession( | |||
| 7884 | nsIWidget* aWidget) { | |||
| 7885 | nsCOMPtr<nsIDragSession> dragSession; | |||
| 7886 | nsCOMPtr<nsIDragService> dragService = | |||
| 7887 | do_GetService("@mozilla.org/widget/dragservice;1"); | |||
| 7888 | if (dragService) { | |||
| 7889 | dragSession = dragService->GetCurrentSession(aWidget); | |||
| 7890 | } | |||
| 7891 | return dragSession.forget(); | |||
| 7892 | } | |||
| 7893 | ||||
| 7894 | /* static */ | |||
| 7895 | already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession( | |||
| 7896 | nsPresContext* aPC) { | |||
| 7897 | NS_ENSURE_TRUE(aPC, nullptr)do { if ((__builtin_expect(!!(!(aPC)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "aPC" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7897); return nullptr; } } while (false); | |||
| 7898 | auto* widget = aPC->GetRootWidget(); | |||
| 7899 | if (!widget) { | |||
| 7900 | return nullptr; | |||
| 7901 | } | |||
| 7902 | return GetDragSession(widget); | |||
| 7903 | } | |||
| 7904 | ||||
| 7905 | /* static */ | |||
| 7906 | nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) { | |||
| 7907 | if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) { | |||
| 7908 | return NS_OK; | |||
| 7909 | } | |||
| 7910 | ||||
| 7911 | // For dragstart events, the data transfer object is | |||
| 7912 | // created before the event fires, so it should already be set. For other | |||
| 7913 | // drag events, get the object from the drag session. | |||
| 7914 | NS_ASSERTION(aDragEvent->mMessage != eDragStart,do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer" , "aDragEvent->mMessage != eDragStart", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7915); MOZ_PretendNoReturn(); } } while (0) | |||
| 7915 | "draggesture event created without a dataTransfer")do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer" , "aDragEvent->mMessage != eDragStart", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 7915); MOZ_PretendNoReturn(); } } while (0); | |||
| 7916 | ||||
| 7917 | nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget); | |||
| 7918 | NS_ENSURE_TRUE(dragSession, NS_OK)do { if ((__builtin_expect(!!(!(dragSession)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "dragSession" ") failed" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7918); return NS_OK; } } while (false); // no drag in progress | |||
| 7919 | ||||
| 7920 | RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer(); | |||
| 7921 | if (!initialDataTransfer) { | |||
| 7922 | // A dataTransfer won't exist when a drag was started by some other | |||
| 7923 | // means, for instance calling the drag service directly, or a drag | |||
| 7924 | // from another application. In either case, a new dataTransfer should | |||
| 7925 | // be created that reflects the data. | |||
| 7926 | initialDataTransfer = new DataTransfer( | |||
| 7927 | aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing()); | |||
| 7928 | ||||
| 7929 | // now set it in the drag session so we don't need to create it again | |||
| 7930 | dragSession->SetDataTransfer(initialDataTransfer); | |||
| 7931 | } | |||
| 7932 | ||||
| 7933 | bool isCrossDomainSubFrameDrop = false; | |||
| 7934 | if (aDragEvent->mMessage == eDrop) { | |||
| 7935 | isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent); | |||
| 7936 | } | |||
| 7937 | ||||
| 7938 | // each event should use a clone of the original dataTransfer. | |||
| 7939 | initialDataTransfer->Clone( | |||
| 7940 | aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled, | |||
| 7941 | isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer)); | |||
| 7942 | if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7942)) { | |||
| 7943 | return NS_ERROR_OUT_OF_MEMORY; | |||
| 7944 | } | |||
| 7945 | ||||
| 7946 | // for the dragenter and dragover events, initialize the drop effect | |||
| 7947 | // from the drop action, which platform specific widget code sets before | |||
| 7948 | // the event is fired based on the keyboard state. | |||
| 7949 | if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) { | |||
| 7950 | uint32_t action; | |||
| 7951 | dragSession->GetDragAction(&action); | |||
| 7952 | uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt(); | |||
| 7953 | aDragEvent->mDataTransfer->SetDropEffectInt( | |||
| 7954 | FilterDropEffect(action, effectAllowed)); | |||
| 7955 | } else if (aDragEvent->mMessage == eDrop || | |||
| 7956 | aDragEvent->mMessage == eDragEnd) { | |||
| 7957 | // For the drop and dragend events, set the drop effect based on the | |||
| 7958 | // last value that the dropEffect had. This will have been set in | |||
| 7959 | // EventStateManager::PostHandleEvent for the last dragenter or | |||
| 7960 | // dragover event. | |||
| 7961 | aDragEvent->mDataTransfer->SetDropEffectInt( | |||
| 7962 | initialDataTransfer->DropEffectInt()); | |||
| 7963 | } | |||
| 7964 | ||||
| 7965 | return NS_OK; | |||
| 7966 | } | |||
| 7967 | ||||
| 7968 | /* static */ | |||
| 7969 | uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction, | |||
| 7970 | uint32_t aEffectAllowed) { | |||
| 7971 | // It is possible for the drag action to include more than one action, but | |||
| 7972 | // the widget code which sets the action from the keyboard state should only | |||
| 7973 | // be including one. If multiple actions were set, we just consider them in | |||
| 7974 | // the following order: | |||
| 7975 | // copy, link, move | |||
| 7976 | if (aAction & nsIDragService::DRAGDROP_ACTION_COPY) | |||
| 7977 | aAction = nsIDragService::DRAGDROP_ACTION_COPY; | |||
| 7978 | else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK) | |||
| 7979 | aAction = nsIDragService::DRAGDROP_ACTION_LINK; | |||
| 7980 | else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE) | |||
| 7981 | aAction = nsIDragService::DRAGDROP_ACTION_MOVE; | |||
| 7982 | ||||
| 7983 | // Filter the action based on the effectAllowed. If the effectAllowed | |||
| 7984 | // doesn't include the action, then that action cannot be done, so adjust | |||
| 7985 | // the action to something that is allowed. For a copy, adjust to move or | |||
| 7986 | // link. For a move, adjust to copy or link. For a link, adjust to move or | |||
| 7987 | // link. Otherwise, use none. | |||
| 7988 | if (aAction & aEffectAllowed || | |||
| 7989 | aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) | |||
| 7990 | return aAction; | |||
| 7991 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE) | |||
| 7992 | return nsIDragService::DRAGDROP_ACTION_MOVE; | |||
| 7993 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY) | |||
| 7994 | return nsIDragService::DRAGDROP_ACTION_COPY; | |||
| 7995 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK) | |||
| 7996 | return nsIDragService::DRAGDROP_ACTION_LINK; | |||
| 7997 | return nsIDragService::DRAGDROP_ACTION_NONE; | |||
| 7998 | } | |||
| 7999 | ||||
| 8000 | /* static */ | |||
| 8001 | bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession, | |||
| 8002 | WidgetDragEvent* aDropEvent) { | |||
| 8003 | nsCOMPtr<nsIContent> target = | |||
| 8004 | nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget); | |||
| 8005 | if (!target) { | |||
| 8006 | return true; | |||
| 8007 | } | |||
| 8008 | ||||
| 8009 | // Always allow dropping onto chrome shells. | |||
| 8010 | BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext(); | |||
| 8011 | if (targetBC->IsChrome()) { | |||
| 8012 | return false; | |||
| 8013 | } | |||
| 8014 | ||||
| 8015 | WindowContext* targetWC = target->OwnerDoc()->GetWindowContext(); | |||
| 8016 | ||||
| 8017 | // If there is no source browsing context, then this is a drag from another | |||
| 8018 | // application, which should be allowed. | |||
| 8019 | RefPtr<WindowContext> sourceWC; | |||
| 8020 | aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC)); | |||
| 8021 | if (sourceWC) { | |||
| 8022 | // Get each successive parent of the source document and compare it to | |||
| 8023 | // the drop document. If they match, then this is a drag from a child frame. | |||
| 8024 | for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC; | |||
| 8025 | sourceWC = sourceWC->GetParentWindowContext()) { | |||
| 8026 | // If the source and the target match, then the drag started in a | |||
| 8027 | // descendant frame. If the source is discarded, err on the side of | |||
| 8028 | // caution and treat it as a subframe drag. | |||
| 8029 | if (sourceWC == targetWC || sourceWC->IsDiscarded()) { | |||
| 8030 | return true; | |||
| 8031 | } | |||
| 8032 | } | |||
| 8033 | } | |||
| 8034 | ||||
| 8035 | return false; | |||
| 8036 | } | |||
| 8037 | ||||
| 8038 | /* static */ | |||
| 8039 | bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) { | |||
| 8040 | bool isFile; | |||
| 8041 | nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service(); | |||
| 8042 | ||||
| 8043 | // Important: we do NOT test the entire URI chain here! | |||
| 8044 | return util && | |||
| 8045 | NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags ( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))) , 1))) | |||
| 8046 | aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags ( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))) , 1))) && | |||
| 8047 | isFile; | |||
| 8048 | } | |||
| 8049 | ||||
| 8050 | /* static */ | |||
| 8051 | JSContext* nsContentUtils::GetCurrentJSContext() { | |||
| 8052 | MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInitialized()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8052); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence (__null, 8052); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8053 | if (!IsJSAPIActive()) { | |||
| 8054 | return nullptr; | |||
| 8055 | } | |||
| 8056 | return danger::GetJSContext(); | |||
| 8057 | } | |||
| 8058 | ||||
| 8059 | template <typename StringType, typename CharType> | |||
| 8060 | void _ASCIIToLowerInSitu(StringType& aStr) { | |||
| 8061 | CharType* iter = aStr.BeginWriting(); | |||
| 8062 | CharType* end = aStr.EndWriting(); | |||
| 8063 | MOZ_ASSERT(iter && end)do { static_assert( mozilla::detail::AssertionConditionType< decltype(iter && end)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(iter && end))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("iter && end" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8063); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence (__null, 8063); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8064 | ||||
| 8065 | while (iter != end) { | |||
| 8066 | CharType c = *iter; | |||
| 8067 | if (c >= 'A' && c <= 'Z') { | |||
| 8068 | *iter = c + ('a' - 'A'); | |||
| 8069 | } | |||
| 8070 | ++iter; | |||
| 8071 | } | |||
| 8072 | } | |||
| 8073 | ||||
| 8074 | /* static */ | |||
| 8075 | void nsContentUtils::ASCIIToLower(nsAString& aStr) { | |||
| 8076 | return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr); | |||
| 8077 | } | |||
| 8078 | ||||
| 8079 | /* static */ | |||
| 8080 | void nsContentUtils::ASCIIToLower(nsACString& aStr) { | |||
| 8081 | return _ASCIIToLowerInSitu<nsACString, char>(aStr); | |||
| 8082 | } | |||
| 8083 | ||||
| 8084 | template <typename StringType, typename CharType> | |||
| 8085 | void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) { | |||
| 8086 | uint32_t len = aSource.Length(); | |||
| 8087 | aDest.SetLength(len); | |||
| 8088 | MOZ_ASSERT(aDest.Length() == len)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDest.Length() == len)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDest.Length() == len))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("aDest.Length() == len" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8088); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence (__null, 8088); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8089 | ||||
| 8090 | CharType* dest = aDest.BeginWriting(); | |||
| 8091 | MOZ_ASSERT(dest)do { static_assert( mozilla::detail::AssertionConditionType< decltype(dest)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(dest))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("dest", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")"); do { MOZ_CrashSequence(__null, 8091); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 8092 | ||||
| 8093 | const CharType* iter = aSource.BeginReading(); | |||
| 8094 | const CharType* end = aSource.EndReading(); | |||
| 8095 | while (iter != end) { | |||
| 8096 | CharType c = *iter; | |||
| 8097 | *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; | |||
| 8098 | ++iter; | |||
| 8099 | ++dest; | |||
| 8100 | } | |||
| 8101 | } | |||
| 8102 | ||||
| 8103 | /* static */ | |||
| 8104 | void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) { | |||
| 8105 | return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest); | |||
| 8106 | } | |||
| 8107 | ||||
| 8108 | /* static */ | |||
| 8109 | void nsContentUtils::ASCIIToLower(const nsACString& aSource, | |||
| 8110 | nsACString& aDest) { | |||
| 8111 | return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest); | |||
| 8112 | } | |||
| 8113 | ||||
| 8114 | template <typename StringType, typename CharType> | |||
| 8115 | void _ASCIIToUpperInSitu(StringType& aStr) { | |||
| 8116 | CharType* iter = aStr.BeginWriting(); | |||
| 8117 | CharType* end = aStr.EndWriting(); | |||
| 8118 | MOZ_ASSERT(iter && end)do { static_assert( mozilla::detail::AssertionConditionType< decltype(iter && end)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(iter && end))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("iter && end" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8118); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence (__null, 8118); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8119 | ||||
| 8120 | while (iter != end) { | |||
| 8121 | CharType c = *iter; | |||
| 8122 | if (c >= 'a' && c <= 'z') { | |||
| 8123 | *iter = c + ('A' - 'a'); | |||
| 8124 | } | |||
| 8125 | ++iter; | |||
| 8126 | } | |||
| 8127 | } | |||
| 8128 | ||||
| 8129 | /* static */ | |||
| 8130 | void nsContentUtils::ASCIIToUpper(nsAString& aStr) { | |||
| 8131 | return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr); | |||
| 8132 | } | |||
| 8133 | ||||
| 8134 | /* static */ | |||
| 8135 | void nsContentUtils::ASCIIToUpper(nsACString& aStr) { | |||
| 8136 | return _ASCIIToUpperInSitu<nsACString, char>(aStr); | |||
| 8137 | } | |||
| 8138 | ||||
| 8139 | template <typename StringType, typename CharType> | |||
| 8140 | void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) { | |||
| 8141 | uint32_t len = aSource.Length(); | |||
| 8142 | aDest.SetLength(len); | |||
| 8143 | MOZ_ASSERT(aDest.Length() == len)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDest.Length() == len)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDest.Length() == len))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("aDest.Length() == len" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8143); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence (__null, 8143); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8144 | ||||
| 8145 | CharType* dest = aDest.BeginWriting(); | |||
| 8146 | MOZ_ASSERT(dest)do { static_assert( mozilla::detail::AssertionConditionType< decltype(dest)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(dest))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("dest", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")"); do { MOZ_CrashSequence(__null, 8146); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 8147 | ||||
| 8148 | const CharType* iter = aSource.BeginReading(); | |||
| 8149 | const CharType* end = aSource.EndReading(); | |||
| 8150 | while (iter != end) { | |||
| 8151 | CharType c = *iter; | |||
| 8152 | *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c; | |||
| 8153 | ++iter; | |||
| 8154 | ++dest; | |||
| 8155 | } | |||
| 8156 | } | |||
| 8157 | ||||
| 8158 | /* static */ | |||
| 8159 | void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) { | |||
| 8160 | return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest); | |||
| 8161 | } | |||
| 8162 | ||||
| 8163 | /* static */ | |||
| 8164 | void nsContentUtils::ASCIIToUpper(const nsACString& aSource, | |||
| 8165 | nsACString& aDest) { | |||
| 8166 | return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest); | |||
| 8167 | } | |||
| 8168 | ||||
| 8169 | /* static */ | |||
| 8170 | bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) { | |||
| 8171 | if (aAtom1 == aAtom2) { | |||
| 8172 | return true; | |||
| 8173 | } | |||
| 8174 | ||||
| 8175 | // If both are ascii lowercase already, we know that the slow comparison | |||
| 8176 | // below is going to return false. | |||
| 8177 | if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) { | |||
| 8178 | return false; | |||
| 8179 | } | |||
| 8180 | ||||
| 8181 | return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1), | |||
| 8182 | nsDependentAtomString(aAtom2)); | |||
| 8183 | } | |||
| 8184 | ||||
| 8185 | /* static */ | |||
| 8186 | bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, | |||
| 8187 | const nsAString& aStr2) { | |||
| 8188 | uint32_t len = aStr1.Length(); | |||
| 8189 | if (len != aStr2.Length()) { | |||
| 8190 | return false; | |||
| 8191 | } | |||
| 8192 | ||||
| 8193 | const char16_t* str1 = aStr1.BeginReading(); | |||
| 8194 | const char16_t* str2 = aStr2.BeginReading(); | |||
| 8195 | const char16_t* end = str1 + len; | |||
| 8196 | ||||
| 8197 | while (str1 < end) { | |||
| 8198 | char16_t c1 = *str1++; | |||
| 8199 | char16_t c2 = *str2++; | |||
| 8200 | ||||
| 8201 | // First check if any bits other than the 0x0020 differs | |||
| 8202 | if ((c1 ^ c2) & 0xffdf) { | |||
| 8203 | return false; | |||
| 8204 | } | |||
| 8205 | ||||
| 8206 | // We know they can only differ in the 0x0020 bit. | |||
| 8207 | // Likely the two chars are the same, so check that first | |||
| 8208 | if (c1 != c2) { | |||
| 8209 | // They do differ, but since it's only in the 0x0020 bit, check if it's | |||
| 8210 | // the same ascii char, but just differing in case | |||
| 8211 | char16_t c1Upper = c1 & 0xffdf; | |||
| 8212 | if (!('A' <= c1Upper && c1Upper <= 'Z')) { | |||
| 8213 | return false; | |||
| 8214 | } | |||
| 8215 | } | |||
| 8216 | } | |||
| 8217 | ||||
| 8218 | return true; | |||
| 8219 | } | |||
| 8220 | ||||
| 8221 | /* static */ | |||
| 8222 | bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) { | |||
| 8223 | const char16_t* iter = aStr.BeginReading(); | |||
| 8224 | const char16_t* end = aStr.EndReading(); | |||
| 8225 | while (iter != end) { | |||
| 8226 | char16_t c = *iter; | |||
| 8227 | if (c >= 'A' && c <= 'Z') { | |||
| 8228 | return true; | |||
| 8229 | } | |||
| 8230 | ++iter; | |||
| 8231 | } | |||
| 8232 | ||||
| 8233 | return false; | |||
| 8234 | } | |||
| 8235 | ||||
| 8236 | /* static */ | |||
| 8237 | nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() { | |||
| 8238 | if (!sSameOriginChecker) { | |||
| 8239 | sSameOriginChecker = new SameOriginCheckerImpl(); | |||
| 8240 | NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef(); | |||
| 8241 | } | |||
| 8242 | return sSameOriginChecker; | |||
| 8243 | } | |||
| 8244 | ||||
| 8245 | /* static */ | |||
| 8246 | nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel, | |||
| 8247 | nsIChannel* aNewChannel) { | |||
| 8248 | if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE; | |||
| 8249 | ||||
| 8250 | nsCOMPtr<nsIPrincipal> oldPrincipal; | |||
| 8251 | nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( | |||
| 8252 | aOldChannel, getter_AddRefs(oldPrincipal)); | |||
| 8253 | ||||
| 8254 | nsCOMPtr<nsIURI> newURI; | |||
| 8255 | aNewChannel->GetURI(getter_AddRefs(newURI)); | |||
| 8256 | nsCOMPtr<nsIURI> newOriginalURI; | |||
| 8257 | aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI)); | |||
| 8258 | ||||
| 8259 | NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI)do { if ((__builtin_expect(!!(!(oldPrincipal && newURI && newOriginalURI)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "oldPrincipal && newURI && newOriginalURI" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8259); return NS_ERROR_UNEXPECTED; } } while (false); | |||
| 8260 | ||||
| 8261 | nsresult rv = oldPrincipal->CheckMayLoad(newURI, false); | |||
| 8262 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) { | |||
| 8263 | rv = oldPrincipal->CheckMayLoad(newOriginalURI, false); | |||
| 8264 | } | |||
| 8265 | ||||
| 8266 | return rv; | |||
| 8267 | } | |||
| 8268 | ||||
| 8269 | NS_IMPL_ISUPPORTS(SameOriginCheckerImpl, nsIChannelEventSink,MozExternalRefCountType SameOriginCheckerImpl::AddRef(void) { static_assert(!std::is_destructible_v<SameOriginCheckerImpl >, "Reference-counted class " "SameOriginCheckerImpl" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8270 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SameOriginCheckerImpl" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 8270); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SameOriginCheckerImpl" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("SameOriginCheckerImpl" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType SameOriginCheckerImpl::Release(void) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8270 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8270 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SameOriginCheckerImpl" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 8270); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SameOriginCheckerImpl" " not thread-safe"); const char* const nametmp = "SameOriginCheckerImpl"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)) ; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult SameOriginCheckerImpl::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsIChannelEventSink >, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink *>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast< char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsIInterfaceRequestor >, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor *>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast< char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIChannelEventSink*>((SameOriginCheckerImpl *)0x1000))) - reinterpret_cast<char*>((SameOriginCheckerImpl *)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table ) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } | |||
| 8270 | nsIInterfaceRequestor)MozExternalRefCountType SameOriginCheckerImpl::AddRef(void) { static_assert(!std::is_destructible_v<SameOriginCheckerImpl >, "Reference-counted class " "SameOriginCheckerImpl" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8270 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SameOriginCheckerImpl" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 8270); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SameOriginCheckerImpl" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("SameOriginCheckerImpl" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType SameOriginCheckerImpl::Release(void) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8270 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8270 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SameOriginCheckerImpl" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 8270); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SameOriginCheckerImpl" " not thread-safe"); const char* const nametmp = "SameOriginCheckerImpl"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)) ; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult SameOriginCheckerImpl::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8270); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsIChannelEventSink >, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink *>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast< char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsIInterfaceRequestor >, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor *>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast< char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail ::kImplementedIID<SameOriginCheckerImpl, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIChannelEventSink*>((SameOriginCheckerImpl *)0x1000))) - reinterpret_cast<char*>((SameOriginCheckerImpl *)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table ) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } | |||
| 8271 | ||||
| 8272 | NS_IMETHODIMPnsresult | |||
| 8273 | SameOriginCheckerImpl::AsyncOnChannelRedirect( | |||
| 8274 | nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags, | |||
| 8275 | nsIAsyncVerifyRedirectCallback* cb) { | |||
| 8276 | MOZ_ASSERT(aNewChannel, "Redirecting to null channel?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNewChannel)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aNewChannel))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNewChannel" " (" "Redirecting to null channel?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel" ") (" "Redirecting to null channel?" ")"); do { MOZ_CrashSequence (__null, 8276); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8277 | ||||
| 8278 | nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel); | |||
| 8279 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
| 8280 | cb->OnRedirectVerifyCallback(NS_OK); | |||
| 8281 | } | |||
| 8282 | ||||
| 8283 | return rv; | |||
| 8284 | } | |||
| 8285 | ||||
| 8286 | NS_IMETHODIMPnsresult | |||
| 8287 | SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) { | |||
| 8288 | return QueryInterface(aIID, aResult); | |||
| 8289 | } | |||
| 8290 | ||||
| 8291 | /* static */ | |||
| 8292 | nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI, | |||
| 8293 | nsACString& aOrigin) { | |||
| 8294 | nsresult rv; | |||
| 8295 | MOZ_ASSERT(aURI, "missing uri")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "missing uri" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "missing uri" ")"); do { MOZ_CrashSequence(__null, 8295); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 8296 | ||||
| 8297 | // For Blob URI, the path is the URL of the owning page. | |||
| 8298 | if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) { | |||
| 8299 | nsAutoCString path; | |||
| 8300 | rv = aURI->GetPathQueryRef(path); | |||
| 8301 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8301); return rv; } } while (false); | |||
| 8302 | ||||
| 8303 | nsCOMPtr<nsIURI> uri; | |||
| 8304 | rv = NS_NewURI(getter_AddRefs(uri), path); | |||
| 8305 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 8306 | aOrigin.AssignLiteral("null"); | |||
| 8307 | return NS_OK; | |||
| 8308 | } | |||
| 8309 | ||||
| 8310 | if ( | |||
| 8311 | // Schemes in spec. https://url.spec.whatwg.org/#origin | |||
| 8312 | !net::SchemeIsHttpOrHttps(uri) && !uri->SchemeIs("file") && | |||
| 8313 | !uri->SchemeIs("resource") && | |||
| 8314 | // Our own schemes. | |||
| 8315 | !uri->SchemeIs("moz-extension")) { | |||
| 8316 | aOrigin.AssignLiteral("null"); | |||
| 8317 | return NS_OK; | |||
| 8318 | } | |||
| 8319 | ||||
| 8320 | return GetWebExposedOriginSerialization(uri, aOrigin); | |||
| 8321 | } | |||
| 8322 | ||||
| 8323 | nsAutoCString scheme; | |||
| 8324 | aURI->GetScheme(scheme); | |||
| 8325 | ||||
| 8326 | // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then | |||
| 8327 | // return "null" as the origin serialization. | |||
| 8328 | // We make an exception for "ftp" since we don't have a protocol handler | |||
| 8329 | // for this scheme | |||
| 8330 | uint32_t flags = 0; | |||
| 8331 | nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv); | |||
| 8332 | if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && | |||
| 8333 | NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags (scheme.get(), &flags))), 1)))) { | |||
| 8334 | if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) { | |||
| 8335 | aOrigin.AssignLiteral("null"); | |||
| 8336 | return NS_OK; | |||
| 8337 | } | |||
| 8338 | } | |||
| 8339 | ||||
| 8340 | aOrigin.Truncate(); | |||
| 8341 | ||||
| 8342 | nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI); | |||
| 8343 | NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(uri)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "uri" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8343); return NS_ERROR_UNEXPECTED; } } while (false); | |||
| 8344 | ||||
| 8345 | nsAutoCString host; | |||
| 8346 | rv = uri->GetAsciiHost(host); | |||
| 8347 | ||||
| 8348 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) { | |||
| 8349 | nsAutoCString userPass; | |||
| 8350 | uri->GetUserPass(userPass); | |||
| 8351 | ||||
| 8352 | nsAutoCString prePath; | |||
| 8353 | if (!userPass.IsEmpty()) { | |||
| 8354 | rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri); | |||
| 8355 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8355); return rv; } } while (false); | |||
| 8356 | } | |||
| 8357 | ||||
| 8358 | rv = uri->GetPrePath(prePath); | |||
| 8359 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8359); return rv; } } while (false); | |||
| 8360 | ||||
| 8361 | aOrigin = std::move(prePath); | |||
| 8362 | } else { | |||
| 8363 | aOrigin.AssignLiteral("null"); | |||
| 8364 | } | |||
| 8365 | ||||
| 8366 | return NS_OK; | |||
| 8367 | } | |||
| 8368 | ||||
| 8369 | /* static */ | |||
| 8370 | nsresult nsContentUtils::GetWebExposedOriginSerialization( | |||
| 8371 | nsIPrincipal* aPrincipal, nsAString& aOrigin) { | |||
| 8372 | MOZ_ASSERT(aPrincipal, "missing principal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPrincipal" " (" "missing principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8372 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ") (" "missing principal" ")"); do { MOZ_CrashSequence(__null, 8372 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 8373 | ||||
| 8374 | aOrigin.Truncate(); | |||
| 8375 | nsAutoCString webExposedOriginSerialization; | |||
| 8376 | ||||
| 8377 | nsresult rv = aPrincipal->GetWebExposedOriginSerialization( | |||
| 8378 | webExposedOriginSerialization); | |||
| 8379 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 8380 | webExposedOriginSerialization.AssignLiteral("null"); | |||
| 8381 | } | |||
| 8382 | ||||
| 8383 | CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin); | |||
| 8384 | return NS_OK; | |||
| 8385 | } | |||
| 8386 | ||||
| 8387 | /* static */ | |||
| 8388 | nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI, | |||
| 8389 | nsAString& aOrigin) { | |||
| 8390 | MOZ_ASSERT(aURI, "missing uri")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aURI)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aURI" " (" "missing uri" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "missing uri" ")"); do { MOZ_CrashSequence(__null, 8390); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
| 8391 | nsresult rv; | |||
| 8392 | ||||
| 8393 | #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) | |||
| 8394 | // Check if either URI has a special origin. | |||
| 8395 | nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = | |||
| 8396 | do_QueryInterface(aURI); | |||
| 8397 | if (uriWithSpecialOrigin) { | |||
| 8398 | nsCOMPtr<nsIURI> origin; | |||
| 8399 | rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin)); | |||
| 8400 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8400); return rv; } } while (false); | |||
| 8401 | ||||
| 8402 | return GetWebExposedOriginSerialization(origin, aOrigin); | |||
| 8403 | } | |||
| 8404 | #endif | |||
| 8405 | ||||
| 8406 | nsAutoCString webExposedOriginSerialization; | |||
| 8407 | rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization); | |||
| 8408 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8408); return rv; } } while (false); | |||
| 8409 | ||||
| 8410 | CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin); | |||
| 8411 | return NS_OK; | |||
| 8412 | } | |||
| 8413 | ||||
| 8414 | /* static */ | |||
| 8415 | bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, | |||
| 8416 | nsIChannel* aChannel, | |||
| 8417 | bool aAllowIfInheritsPrincipal) { | |||
| 8418 | nsCOMPtr<nsIURI> channelURI; | |||
| 8419 | nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
| 8420 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8420); return false; } } while (false); | |||
| 8421 | ||||
| 8422 | return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad (channelURI, aAllowIfInheritsPrincipal))), 1))) | |||
| 8423 | aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad (channelURI, aAllowIfInheritsPrincipal))), 1))); | |||
| 8424 | } | |||
| 8425 | ||||
| 8426 | /* static */ | |||
| 8427 | bool nsContentUtils::CanAccessNativeAnon() { | |||
| 8428 | return LegacyIsCallerChromeOrNativeCode(); | |||
| 8429 | } | |||
| 8430 | ||||
| 8431 | /* static */ | |||
| 8432 | nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted, | |||
| 8433 | Event* aSourceEvent, | |||
| 8434 | PresShell* aPresShell, bool aCtrl, | |||
| 8435 | bool aAlt, bool aShift, bool aMeta, | |||
| 8436 | uint16_t aInputSource, | |||
| 8437 | int16_t aButton) { | |||
| 8438 | NS_ENSURE_STATE(aTarget)do { if ((__builtin_expect(!!(!(aTarget)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTarget" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8438); return NS_ERROR_UNEXPECTED; } } while (false); | |||
| 8439 | Document* doc = aTarget->OwnerDoc(); | |||
| 8440 | nsPresContext* presContext = doc->GetPresContext(); | |||
| 8441 | ||||
| 8442 | RefPtr<XULCommandEvent> xulCommand = | |||
| 8443 | new XULCommandEvent(doc, presContext, nullptr); | |||
| 8444 | xulCommand->InitCommandEvent(u"command"_ns, true, true, | |||
| 8445 | nsGlobalWindowInner::Cast(doc->GetInnerWindow()), | |||
| 8446 | 0, aCtrl, aAlt, aShift, aMeta, aButton, | |||
| 8447 | aSourceEvent, aInputSource, IgnoreErrors()); | |||
| 8448 | ||||
| 8449 | if (aPresShell) { | |||
| 8450 | nsEventStatus status = nsEventStatus_eIgnore; | |||
| 8451 | return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status); | |||
| 8452 | } | |||
| 8453 | ||||
| 8454 | ErrorResult rv; | |||
| 8455 | aTarget->DispatchEvent(*xulCommand, rv); | |||
| 8456 | return rv.StealNSResult(); | |||
| 8457 | } | |||
| 8458 | ||||
| 8459 | // static | |||
| 8460 | nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native, | |||
| 8461 | nsWrapperCache* cache, const nsIID* aIID, | |||
| 8462 | JS::MutableHandle<JS::Value> vp, | |||
| 8463 | bool aAllowWrapping) { | |||
| 8464 | MOZ_ASSERT(cx == GetCurrentJSContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(cx == GetCurrentJSContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(cx == GetCurrentJSContext()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cx == GetCurrentJSContext()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8464); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()" ")"); do { MOZ_CrashSequence (__null, 8464); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 8465 | ||||
| 8466 | if (!native) { | |||
| 8467 | vp.setNull(); | |||
| 8468 | ||||
| 8469 | return NS_OK; | |||
| 8470 | } | |||
| 8471 | ||||
| 8472 | JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp); | |||
| 8473 | if (wrapper) { | |||
| 8474 | return NS_OK; | |||
| 8475 | } | |||
| 8476 | ||||
| 8477 | NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(sXPConnect)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sXPConnect" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8477 ); return NS_ERROR_UNEXPECTED; } } while (false); | |||
| 8478 | ||||
| 8479 | if (!NS_IsMainThread()) { | |||
| 8480 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8480); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence (__null, 8480); __attribute__((nomerge)) ::abort(); } while ( false); } while (false); | |||
| 8481 | } | |||
| 8482 | ||||
| 8483 | JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx)); | |||
| 8484 | nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID, | |||
| 8485 | aAllowWrapping, vp); | |||
| 8486 | return rv; | |||
| 8487 | } | |||
| 8488 | ||||
| 8489 | void nsContentUtils::StripNullChars(const nsAString& aInStr, | |||
| 8490 | nsAString& aOutStr) { | |||
| 8491 | // In common cases where we don't have nulls in the | |||
| 8492 | // string we can simple simply bypass the checking code. | |||
| 8493 | int32_t firstNullPos = aInStr.FindChar('\0'); | |||
| 8494 | if (firstNullPos == kNotFound) { | |||
| 8495 | aOutStr.Assign(aInStr); | |||
| 8496 | return; | |||
| 8497 | } | |||
| 8498 | ||||
| 8499 | aOutStr.SetCapacity(aInStr.Length() - 1); | |||
| 8500 | nsAString::const_iterator start, end; | |||
| 8501 | aInStr.BeginReading(start); | |||
| 8502 | aInStr.EndReading(end); | |||
| 8503 | while (start != end) { | |||
| 8504 | if (*start != '\0') aOutStr.Append(*start); | |||
| 8505 | ++start; | |||
| 8506 | } | |||
| 8507 | } | |||
| 8508 | ||||
| 8509 | struct ClassMatchingInfo { | |||
| 8510 | AtomArray mClasses; | |||
| 8511 | nsCaseTreatment mCaseTreatment; | |||
| 8512 | }; | |||
| 8513 | ||||
| 8514 | // static | |||
| 8515 | bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID, | |||
| 8516 | nsAtom* aAtom, void* aData) { | |||
| 8517 | // We can't match if there are no class names | |||
| 8518 | const nsAttrValue* classAttr = aElement->GetClasses(); | |||
| 8519 | if (!classAttr) { | |||
| 8520 | return false; | |||
| 8521 | } | |||
| 8522 | ||||
| 8523 | // need to match *all* of the classes | |||
| 8524 | ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData); | |||
| 8525 | if (info->mClasses.IsEmpty()) { | |||
| 8526 | // If we actually had no classes, don't match. | |||
| 8527 | return false; | |||
| 8528 | } | |||
| 8529 | ||||
| 8530 | for (nsAtom* cls : info->mClasses) { | |||
| 8531 | if (!classAttr->Contains(cls, info->mCaseTreatment)) { | |||
| 8532 | return false; | |||
| 8533 | } | |||
| 8534 | } | |||
| 8535 | return true; | |||
| 8536 | } | |||
| 8537 | ||||
| 8538 | // static | |||
| 8539 | void nsContentUtils::DestroyClassNameArray(void* aData) { | |||
| 8540 | ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData); | |||
| 8541 | delete info; | |||
| 8542 | } | |||
| 8543 | ||||
| 8544 | // static | |||
| 8545 | void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode, | |||
| 8546 | const nsString* aClasses) { | |||
| 8547 | nsAttrValue attrValue; | |||
| 8548 | attrValue.ParseAtomArray(*aClasses); | |||
| 8549 | // nsAttrValue::Equals is sensitive to order, so we'll send an array | |||
| 8550 | auto* info = new ClassMatchingInfo; | |||
| 8551 | if (attrValue.Type() == nsAttrValue::eAtomArray) { | |||
| 8552 | info->mClasses.AppendElements(attrValue.GetAtomArrayValue()->Array()); | |||
| 8553 | } else if (attrValue.Type() == nsAttrValue::eAtom) { | |||
| 8554 | info->mClasses.AppendElement(attrValue.GetAtomValue()); | |||
| 8555 | } | |||
| 8556 | ||||
| 8557 | info->mCaseTreatment = | |||
| 8558 | aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks | |||
| 8559 | ? eIgnoreCase | |||
| 8560 | : eCaseMatters; | |||
| 8561 | return info; | |||
| 8562 | } | |||
| 8563 | ||||
| 8564 | void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) { | |||
| 8565 | if (!aWindow) { | |||
| 8566 | return; | |||
| 8567 | } | |||
| 8568 | ||||
| 8569 | // Note that because FlushPendingNotifications flushes parents, this | |||
| 8570 | // is O(N^2) in docshell tree depth. However, the docshell tree is | |||
| 8571 | // usually pretty shallow. | |||
| 8572 | ||||
| 8573 | if (RefPtr<Document> doc = aWindow->GetDoc()) { | |||
| 8574 | doc->FlushPendingNotifications(FlushType::Layout); | |||
| 8575 | } | |||
| 8576 | ||||
| 8577 | if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) { | |||
| 8578 | int32_t i = 0, i_end; | |||
| 8579 | docShell->GetInProcessChildCount(&i_end); | |||
| 8580 | for (; i < i_end; ++i) { | |||
| 8581 | nsCOMPtr<nsIDocShellTreeItem> item; | |||
| 8582 | if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK && | |||
| 8583 | item) { | |||
| 8584 | if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) { | |||
| 8585 | FlushLayoutForTree(win); | |||
| 8586 | } | |||
| 8587 | } | |||
| 8588 | } | |||
| 8589 | } | |||
| 8590 | } | |||
| 8591 | ||||
| 8592 | void nsContentUtils::RemoveNewlines(nsAString& aString) { aString.StripCRLF(); } | |||
| 8593 | ||||
| 8594 | void nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString) { | |||
| 8595 | if (!PlatformToDOMLineBreaks(aString, fallible)) { | |||
| 8596 | aString.AllocFailed(aString.Length()); | |||
| 8597 | } | |||
| 8598 | } | |||
| 8599 | ||||
| 8600 | bool nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString, | |||
| 8601 | const fallible_t& aFallible) { | |||
| 8602 | if (aString.FindChar(char16_t('\r')) != -1) { | |||
| 8603 | // Windows linebreaks: Map CRLF to LF: | |||
| 8604 | if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) { | |||
| 8605 | return false; | |||
| 8606 | } | |||
| 8607 | ||||
| 8608 | // Mac linebreaks: Map any remaining CR to LF: | |||
| 8609 | if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) { | |||
| 8610 | return false; | |||
| 8611 | } | |||
| 8612 | } | |||
| 8613 | ||||
| 8614 | return true; | |||
| 8615 | } | |||
| 8616 | ||||
| 8617 | already_AddRefed<ContentList> nsContentUtils::GetElementsByClassName( | |||
| 8618 | nsINode* aRootNode, const nsAString& aClasses) { | |||
| 8619 | MOZ_ASSERT(aRootNode, "Must have root node")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aRootNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aRootNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRootNode" " (" "Must have root node" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8619 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") (" "Must have root node" ")"); do { MOZ_CrashSequence(__null, 8619); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 8620 | ||||
| 8621 | return GetFuncStringContentList<CacheableFuncStringHTMLCollection>( | |||
| 8622 | aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo, | |||
| 8623 | aClasses); | |||
| 8624 | } | |||
| 8625 | ||||
| 8626 | PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) { | |||
| 8627 | const Document* doc = aDocument; | |||
| 8628 | Document* displayDoc = doc->GetDisplayDocument(); | |||
| 8629 | if (displayDoc) { | |||
| 8630 | doc = displayDoc; | |||
| 8631 | } | |||
| 8632 | ||||
| 8633 | PresShell* presShell = doc->GetPresShell(); | |||
| 8634 | if (presShell) { | |||
| 8635 | return presShell; | |||
| 8636 | } | |||
| 8637 | ||||
| 8638 | nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell(); | |||
| 8639 | while (docShellTreeItem) { | |||
| 8640 | // We may be in a display:none subdocument, or we may not have a presshell | |||
| 8641 | // created yet. | |||
| 8642 | // Walk the docshell tree to find the nearest container that has a | |||
| 8643 | // presshell, and return that. | |||
| 8644 | nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem); | |||
| 8645 | if (PresShell* presShell = docShell->GetPresShell()) { | |||
| 8646 | return presShell; | |||
| 8647 | } | |||
| 8648 | nsCOMPtr<nsIDocShellTreeItem> parent; | |||
| 8649 | docShellTreeItem->GetInProcessParent(getter_AddRefs(parent)); | |||
| 8650 | docShellTreeItem = parent; | |||
| 8651 | } | |||
| 8652 | ||||
| 8653 | return nullptr; | |||
| 8654 | } | |||
| 8655 | ||||
| 8656 | /* static */ | |||
| 8657 | nsPresContext* nsContentUtils::FindPresContextForDocument( | |||
| 8658 | const Document* aDocument) { | |||
| 8659 | if (PresShell* presShell = FindPresShellForDocument(aDocument)) { | |||
| 8660 | return presShell->GetPresContext(); | |||
| 8661 | } | |||
| 8662 | return nullptr; | |||
| 8663 | } | |||
| 8664 | ||||
| 8665 | nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) { | |||
| 8666 | PresShell* presShell = FindPresShellForDocument(aDocument); | |||
| 8667 | return presShell ? presShell->GetNearestWidget() : nullptr; | |||
| 8668 | } | |||
| 8669 | ||||
| 8670 | nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) { | |||
| 8671 | nsIFrame* frame = aContent->GetPrimaryFrame(); | |||
| 8672 | if (!frame) { | |||
| 8673 | return nullptr; | |||
| 8674 | } | |||
| 8675 | return frame->GetNearestWidget(); | |||
| 8676 | } | |||
| 8677 | ||||
| 8678 | WindowRenderer* nsContentUtils::WindowRendererForContent( | |||
| 8679 | const nsIContent* aContent) { | |||
| 8680 | nsIWidget* widget = nsContentUtils::WidgetForContent(aContent); | |||
| 8681 | if (widget) { | |||
| 8682 | return widget->GetWindowRenderer(); | |||
| 8683 | } | |||
| 8684 | ||||
| 8685 | return nullptr; | |||
| 8686 | } | |||
| 8687 | ||||
| 8688 | WindowRenderer* nsContentUtils::WindowRendererForDocument( | |||
| 8689 | const Document* aDoc) { | |||
| 8690 | if (nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc)) { | |||
| 8691 | return widget->GetWindowRenderer(); | |||
| 8692 | } | |||
| 8693 | return nullptr; | |||
| 8694 | } | |||
| 8695 | ||||
| 8696 | bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) { | |||
| 8697 | if (!aPrincipal) { | |||
| 8698 | return false; | |||
| 8699 | } | |||
| 8700 | ||||
| 8701 | if (aPrincipal->IsSystemPrincipal()) { | |||
| 8702 | return true; | |||
| 8703 | } | |||
| 8704 | ||||
| 8705 | return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns); | |||
| 8706 | } | |||
| 8707 | ||||
| 8708 | bool nsContentUtils::IsPDFJSEnabled() { return !StaticPrefs::pdfjs_disabled(); } | |||
| 8709 | ||||
| 8710 | bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) { | |||
| 8711 | if (!aPrincipal || !aPrincipal->SchemeIs("resource")) { | |||
| 8712 | return false; | |||
| 8713 | } | |||
| 8714 | nsAutoCString spec; | |||
| 8715 | nsresult rv = aPrincipal->GetAsciiSpec(spec); | |||
| 8716 | NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8716); return false; } } while (false); | |||
| 8717 | return spec.EqualsLiteral("resource://pdf.js/web/viewer.html"); | |||
| 8718 | } | |||
| 8719 | ||||
| 8720 | bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) { | |||
| 8721 | nsIPrincipal* principal = SubjectPrincipal(aCx); | |||
| 8722 | return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal)); | |||
| 8723 | } | |||
| 8724 | ||||
| 8725 | bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx, | |||
| 8726 | JSObject* aGlobal) { | |||
| 8727 | nsIPrincipal* principal = SubjectPrincipal(aCx); | |||
| 8728 | return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, | |||
| 8729 | aGlobal) || | |||
| 8730 | (principal && principal->GetIsAddonOrExpandedAddonPrincipal()); | |||
| 8731 | } | |||
| 8732 | ||||
| 8733 | already_AddRefed<nsIDocumentLoaderFactory> | |||
| 8734 | nsContentUtils::FindInternalDocumentViewer(const nsACString& aType, | |||
| 8735 | DocumentViewerType* aLoaderType) { | |||
| 8736 | if (aLoaderType) { | |||
| 8737 | *aLoaderType = TYPE_UNSUPPORTED; | |||
| 8738 | } | |||
| 8739 | ||||
| 8740 | // one helper factory, please | |||
| 8741 | nsCOMPtr<nsICategoryManager> catMan( | |||
| 8742 | do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1")); | |||
| 8743 | if (!catMan) return nullptr; | |||
| 8744 | ||||
| 8745 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory; | |||
| 8746 | ||||
| 8747 | nsCString contractID; | |||
| 8748 | nsresult rv = | |||
| 8749 | catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID); | |||
| 8750 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
| 8751 | docFactory = do_GetService(contractID.get()); | |||
| 8752 | if (docFactory && aLoaderType) { | |||
| 8753 | if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1")) | |||
| 8754 | *aLoaderType = TYPE_CONTENT; | |||
| 8755 | else | |||
| 8756 | *aLoaderType = TYPE_UNKNOWN; | |||
| 8757 | } | |||
| 8758 | return docFactory.forget(); | |||
| 8759 | } | |||
| 8760 | ||||
| 8761 | // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's | |||
| 8762 | // another type which we may dynamically support, such as `text/*` types or | |||
| 8763 | // video document types. These types are all backed by the nsContentDLF. | |||
| 8764 | if (IsPlainTextType(aType) || | |||
| 8765 | DecoderTraits::IsSupportedInVideoDocument(aType)) { | |||
| 8766 | docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"); | |||
| 8767 | if (docFactory && aLoaderType) { | |||
| 8768 | *aLoaderType = TYPE_CONTENT; | |||
| 8769 | } | |||
| 8770 | return docFactory.forget(); | |||
| 8771 | } | |||
| 8772 | ||||
| 8773 | return nullptr; | |||
| 8774 | } | |||
| 8775 | ||||
| 8776 | static void ReportPatternCompileFailure(nsAString& aPattern, | |||
| 8777 | const JS::RegExpFlags& aFlags, | |||
| 8778 | const Document* aDocument, | |||
| 8779 | JS::MutableHandle<JS::Value> error, | |||
| 8780 | JSContext* cx) { | |||
| 8781 | AutoTArray<nsString, 3> strings; | |||
| 8782 | ||||
| 8783 | strings.AppendElement(aPattern); | |||
| 8784 | ||||
| 8785 | std::stringstream flag_ss; | |||
| 8786 | flag_ss << aFlags; | |||
| 8787 | nsString* flagstr = strings.AppendElement(); | |||
| 8788 | AppendUTF8toUTF16(flag_ss.str(), *flagstr); | |||
| 8789 | ||||
| 8790 | JS::AutoSaveExceptionState savedExc(cx); | |||
| 8791 | JS::Rooted<JSObject*> exnObj(cx, &error.toObject()); | |||
| 8792 | JS::Rooted<JS::Value> messageVal(cx); | |||
| 8793 | if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) { | |||
| 8794 | return; | |||
| 8795 | } | |||
| 8796 | JS::Rooted<JSString*> messageStr(cx, messageVal.toString()); | |||
| 8797 | MOZ_ASSERT(messageStr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(messageStr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(messageStr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("messageStr", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr" ")"); do { MOZ_CrashSequence(__null, 8797); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 8798 | if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) { | |||
| 8799 | return; | |||
| 8800 | } | |||
| 8801 | ||||
| 8802 | nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns, | |||
| 8803 | aDocument, PropertiesFile::DOM_PROPERTIES, | |||
| 8804 | "PatternAttributeCompileFailurev2", strings); | |||
| 8805 | savedExc.drop(); | |||
| 8806 | } | |||
| 8807 | ||||
| 8808 | // static | |||
| 8809 | Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue, | |||
| 8810 | nsString&& aPattern, | |||
| 8811 | const Document* aDocument, | |||
| 8812 | bool aHasMultiple, | |||
| 8813 | JS::RegExpFlags aFlags) { | |||
| 8814 | NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)")do { if (!(aDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "aDocument should be a valid pointer (not null)" , "aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8814); MOZ_PretendNoReturn(); } } while (0); | |||
| 8815 | ||||
| 8816 | // The fact that we're using a JS regexp under the hood should not be visible | |||
| 8817 | // to things like window onerror handlers, so we don't initialize our JSAPI | |||
| 8818 | // with the document's window (which may not exist anyway). | |||
| 8819 | AutoJSAPI jsapi; | |||
| 8820 | jsapi.Init(); | |||
| 8821 | JSContext* cx = jsapi.cx(); | |||
| 8822 | AutoDisableJSInterruptCallback disabler(cx); | |||
| 8823 | ||||
| 8824 | // We can use the junk scope here, because we're just using it for regexp | |||
| 8825 | // evaluation, not actual script execution, and we disable statics so that the | |||
| 8826 | // evaluation does not interact with the execution global. | |||
| 8827 | JSAutoRealm ar(cx, xpc::PrivilegedJunkScope()); | |||
| 8828 | ||||
| 8829 | // Check if the pattern by itself is valid first, and not that it only becomes | |||
| 8830 | // valid once we add ^(?: and )$. | |||
| 8831 | JS::Rooted<JS::Value> error(cx); | |||
| 8832 | if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(), | |||
| 8833 | aFlags, &error)) { | |||
| 8834 | return Nothing(); | |||
| 8835 | } | |||
| 8836 | ||||
| 8837 | if (!error.isUndefined()) { | |||
| 8838 | ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx); | |||
| 8839 | return Some(true); | |||
| 8840 | } | |||
| 8841 | ||||
| 8842 | // The pattern has to match the entire value. | |||
| 8843 | aPattern.InsertLiteral(u"^(?:", 0); | |||
| 8844 | aPattern.AppendLiteral(")$"); | |||
| 8845 | ||||
| 8846 | JS::Rooted<JSObject*> re( | |||
| 8847 | cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(), | |||
| 8848 | aFlags)); | |||
| 8849 | if (!re) { | |||
| 8850 | return Nothing(); | |||
| 8851 | } | |||
| 8852 | ||||
| 8853 | JS::Rooted<JS::Value> rval(cx, JS::NullValue()); | |||
| 8854 | if (!aHasMultiple) { | |||
| 8855 | size_t idx = 0; | |||
| 8856 | if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(), | |||
| 8857 | aValue.Length(), &idx, true, &rval)) { | |||
| 8858 | return Nothing(); | |||
| 8859 | } | |||
| 8860 | return Some(!rval.isNull()); | |||
| 8861 | } | |||
| 8862 | ||||
| 8863 | HTMLSplitOnSpacesTokenizer tokenizer(aValue, ','); | |||
| 8864 | while (tokenizer.hasMoreTokens()) { | |||
| 8865 | const nsAString& value = tokenizer.nextToken(); | |||
| 8866 | size_t idx = 0; | |||
| 8867 | if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(), | |||
| 8868 | value.Length(), &idx, true, &rval)) { | |||
| 8869 | return Nothing(); | |||
| 8870 | } | |||
| 8871 | if (rval.isNull()) { | |||
| 8872 | return Some(false); | |||
| 8873 | } | |||
| 8874 | } | |||
| 8875 | return Some(true); | |||
| 8876 | } | |||
| 8877 | ||||
| 8878 | // static | |||
| 8879 | nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI, | |||
| 8880 | bool* aResult) { | |||
| 8881 | // Note: about:blank URIs do NOT inherit the security context from the | |||
| 8882 | // current document, which is what this function tests for... | |||
| 8883 | return NS_URIChainHasFlags( | |||
| 8884 | aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult); | |||
| 8885 | } | |||
| 8886 | ||||
| 8887 | // static | |||
| 8888 | bool nsContentUtils::ChannelShouldInheritPrincipal( | |||
| 8889 | nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank, | |||
| 8890 | bool aForceInherit) { | |||
| 8891 | MOZ_ASSERT(aLoadingPrincipal,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal" " (" "Can not check inheritance without a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Can not check inheritance without a principal" ")"); do { MOZ_CrashSequence(__null, 8892); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
| 8892 | "Can not check inheritance without a principal")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal" " (" "Can not check inheritance without a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Can not check inheritance without a principal" ")"); do { MOZ_CrashSequence(__null, 8892); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 8893 | ||||
| 8894 | // Only tell the channel to inherit if it can't provide its own security | |||
| 8895 | // context. | |||
| 8896 | // | |||
| 8897 | // XXX: If this is ever changed, check all callers for what owners | |||
| 8898 | // they're passing in. In particular, see the code and | |||
| 8899 | // comments in nsDocShell::LoadURI where we fall back on | |||
| 8900 | // inheriting the owner if called from chrome. That would be | |||
| 8901 | // very wrong if this code changed anything but channels that | |||
| 8902 | // can't provide their own security context! | |||
| 8903 | // | |||
| 8904 | // If aForceInherit is true, we will inherit, even for a channel that | |||
| 8905 | // can provide its own security context. This is used for srcdoc loads. | |||
| 8906 | bool inherit = aForceInherit; | |||
| 8907 | if (!inherit) { | |||
| 8908 | bool uriInherits; | |||
| 8909 | // We expect URIInheritsSecurityContext to return success for an | |||
| 8910 | // about:blank URI, so don't call NS_IsAboutBlank() if this call fails. | |||
| 8911 | // This condition needs to match the one in nsDocShell::InternalLoad where | |||
| 8912 | // we're checking for things that will use the owner. | |||
| 8913 | inherit = | |||
| 8914 | (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext (aURI, &uriInherits))), 1))) && | |||
| 8915 | (uriInherits || (aInheritForAboutBlank && | |||
| 8916 | NS_IsAboutBlankAllowQueryAndFragment(aURI)))) || | |||
| 8917 | // | |||
| 8918 | // file: uri special-casing | |||
| 8919 | // | |||
| 8920 | // If this is a file: load opened from another file: then it may need | |||
| 8921 | // to inherit the owner from the referrer so they can script each other. | |||
| 8922 | // If we don't set the owner explicitly then each file: gets an owner | |||
| 8923 | // based on its own codebase later. | |||
| 8924 | // | |||
| 8925 | (URIIsLocalFile(aURI) && | |||
| 8926 | NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal ->CheckMayLoad(aURI, false))), 1))) && | |||
| 8927 | // One more check here. CheckMayLoad will always return true for the | |||
| 8928 | // system principal, but we do NOT want to inherit in that case. | |||
| 8929 | !aLoadingPrincipal->IsSystemPrincipal()); | |||
| 8930 | } | |||
| 8931 | return inherit; | |||
| 8932 | } | |||
| 8933 | ||||
| 8934 | /* static */ | |||
| 8935 | bool nsContentUtils::IsCutCopyAllowed(Document* aDocument, | |||
| 8936 | nsIPrincipal& aSubjectPrincipal) { | |||
| 8937 | if (StaticPrefs::dom_allow_cut_copy() && aDocument && | |||
| 8938 | aDocument->HasValidTransientUserGestureActivation()) { | |||
| 8939 | return true; | |||
| 8940 | } | |||
| 8941 | ||||
| 8942 | return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite); | |||
| 8943 | } | |||
| 8944 | ||||
| 8945 | /* static */ | |||
| 8946 | bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) { | |||
| 8947 | if (!aDoc1 || !aDoc2) { | |||
| 8948 | return false; | |||
| 8949 | } | |||
| 8950 | bool principalsEqual = false; | |||
| 8951 | aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual); | |||
| 8952 | return principalsEqual; | |||
| 8953 | } | |||
| 8954 | ||||
| 8955 | /* static */ | |||
| 8956 | const Document* nsContentUtils::GetInProcessSubtreeRootDocument( | |||
| 8957 | const Document* aDoc) { | |||
| 8958 | if (!aDoc) { | |||
| 8959 | return nullptr; | |||
| 8960 | } | |||
| 8961 | const Document* doc = aDoc; | |||
| 8962 | while (doc->GetInProcessParentDocument()) { | |||
| 8963 | doc = doc->GetInProcessParentDocument(); | |||
| 8964 | } | |||
| 8965 | return doc; | |||
| 8966 | } | |||
| 8967 | ||||
| 8968 | // static | |||
| 8969 | bool nsContentUtils::IsPointInSelection( | |||
| 8970 | const mozilla::dom::Selection& aSelection, const nsINode& aNode, | |||
| 8971 | const uint32_t aOffset, const bool aAllowCrossShadowBoundary) { | |||
| 8972 | const bool selectionIsCollapsed = | |||
| 8973 | !aAllowCrossShadowBoundary | |||
| 8974 | ? aSelection.IsCollapsed() | |||
| 8975 | : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed(); | |||
| 8976 | if (selectionIsCollapsed) { | |||
| 8977 | return false; | |||
| 8978 | } | |||
| 8979 | ||||
| 8980 | const uint32_t rangeCount = aSelection.RangeCount(); | |||
| 8981 | for (const uint32_t i : IntegerRange(rangeCount)) { | |||
| 8982 | MOZ_ASSERT(aSelection.RangeCount() == rangeCount)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSelection.RangeCount() == rangeCount)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(aSelection.RangeCount() == rangeCount))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSelection.RangeCount() == rangeCount" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8982); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount" ")" ); do { MOZ_CrashSequence(__null, 8982); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 8983 | RefPtr<const nsRange> range = aSelection.GetRangeAt(i); | |||
| 8984 | if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 8984)) { | |||
| 8985 | // Don't bail yet, iterate through them all | |||
| 8986 | continue; | |||
| 8987 | } | |||
| 8988 | ||||
| 8989 | // Done when we find a range that we are in | |||
| 8990 | if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(), | |||
| 8991 | aAllowCrossShadowBoundary)) { | |||
| 8992 | return true; | |||
| 8993 | } | |||
| 8994 | } | |||
| 8995 | ||||
| 8996 | return false; | |||
| 8997 | } | |||
| 8998 | ||||
| 8999 | // static | |||
| 9000 | void nsContentUtils::GetSelectionInTextControl(Selection* aSelection, | |||
| 9001 | Element* aRoot, | |||
| 9002 | uint32_t& aOutStartOffset, | |||
| 9003 | uint32_t& aOutEndOffset) { | |||
| 9004 | MOZ_ASSERT(aSelection && aRoot)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSelection && aRoot)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSelection && aRoot) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSelection && aRoot" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9004); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aSelection && aRoot" ")"); do { MOZ_CrashSequence (__null, 9004); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 9005 | ||||
| 9006 | // We don't care which end of this selection is anchor and which is focus. In | |||
| 9007 | // fact, we explicitly want to know which is the _start_ and which is the | |||
| 9008 | // _end_, not anchor vs focus. | |||
| 9009 | const nsRange* range = aSelection->GetAnchorFocusRange(); | |||
| 9010 | if (!range) { | |||
| 9011 | // Nothing selected | |||
| 9012 | aOutStartOffset = aOutEndOffset = 0; | |||
| 9013 | return; | |||
| 9014 | } | |||
| 9015 | ||||
| 9016 | // All the node pointers here are raw pointers for performance. We shouldn't | |||
| 9017 | // be doing anything in this function that invalidates the node tree. | |||
| 9018 | nsINode* startContainer = range->GetStartContainer(); | |||
| 9019 | uint32_t startOffset = range->StartOffset(); | |||
| 9020 | nsINode* endContainer = range->GetEndContainer(); | |||
| 9021 | uint32_t endOffset = range->EndOffset(); | |||
| 9022 | ||||
| 9023 | // We have at most two children, consisting of an optional text node followed | |||
| 9024 | // by an optional <br>. | |||
| 9025 | NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children")do { if (!(aRoot->GetChildCount() <= 2)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Unexpected children", "aRoot->GetChildCount() <= 2" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9025); MOZ_PretendNoReturn (); } } while (0); | |||
| 9026 | nsIContent* firstChild = aRoot->GetFirstChild(); | |||
| 9027 | #ifdef DEBUG1 | |||
| 9028 | nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild(); | |||
| 9029 | NS_ASSERTION(startContainer == aRoot || startContainer == firstChild ||do { if (!(startContainer == aRoot || startContainer == firstChild || startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9031); MOZ_PretendNoReturn (); } } while (0) | |||
| 9030 | startContainer == lastChild,do { if (!(startContainer == aRoot || startContainer == firstChild || startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9031); MOZ_PretendNoReturn (); } } while (0) | |||
| 9031 | "Unexpected startContainer")do { if (!(startContainer == aRoot || startContainer == firstChild || startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9031); MOZ_PretendNoReturn (); } } while (0); | |||
| 9032 | NS_ASSERTION(endContainer == aRoot || endContainer == firstChild ||do { if (!(endContainer == aRoot || endContainer == firstChild || endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9034); MOZ_PretendNoReturn (); } } while (0) | |||
| 9033 | endContainer == lastChild,do { if (!(endContainer == aRoot || endContainer == firstChild || endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9034); MOZ_PretendNoReturn (); } } while (0) | |||
| 9034 | "Unexpected endContainer")do { if (!(endContainer == aRoot || endContainer == firstChild || endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9034); MOZ_PretendNoReturn (); } } while (0); | |||
| 9035 | // firstChild is either text or a <br> (hence an element). | |||
| 9036 | MOZ_ASSERT_IF(firstChild, firstChild->IsText() || firstChild->IsElement())do { if (firstChild) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(firstChild->IsText() || firstChild->IsElement ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(firstChild->IsText() || firstChild->IsElement( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("firstChild->IsText() || firstChild->IsElement()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()" ")"); do { MOZ_CrashSequence(__null, 9036); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 9037 | #endif | |||
| 9038 | if (!firstChild || firstChild->IsElement()) { | |||
| 9039 | // No text node, so everything is 0 | |||
| 9040 | startOffset = endOffset = 0; | |||
| 9041 | } else { | |||
| 9042 | // First child is text. If the start/end is already in the text node, | |||
| 9043 | // or the start of the root node, no change needed. If it's in the root | |||
| 9044 | // node but not the start, or in the trailing <br>, we need to set the | |||
| 9045 | // offset to the end. | |||
| 9046 | if ((startContainer == aRoot && startOffset != 0) || | |||
| 9047 | (startContainer != aRoot && startContainer != firstChild)) { | |||
| 9048 | startOffset = firstChild->Length(); | |||
| 9049 | } | |||
| 9050 | if ((endContainer == aRoot && endOffset != 0) || | |||
| 9051 | (endContainer != aRoot && endContainer != firstChild)) { | |||
| 9052 | endOffset = firstChild->Length(); | |||
| 9053 | } | |||
| 9054 | } | |||
| 9055 | ||||
| 9056 | MOZ_ASSERT(startOffset <= endOffset)do { static_assert( mozilla::detail::AssertionConditionType< decltype(startOffset <= endOffset)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(startOffset <= endOffset) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("startOffset <= endOffset" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9056); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "startOffset <= endOffset" ")"); do { MOZ_CrashSequence (__null, 9056); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 9057 | aOutStartOffset = startOffset; | |||
| 9058 | aOutEndOffset = endOffset; | |||
| 9059 | } | |||
| 9060 | ||||
| 9061 | // static | |||
| 9062 | HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) { | |||
| 9063 | if (!aPresContext) { | |||
| 9064 | return nullptr; | |||
| 9065 | } | |||
| 9066 | return GetHTMLEditor(aPresContext->GetDocShell()); | |||
| 9067 | } | |||
| 9068 | ||||
| 9069 | // static | |||
| 9070 | HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) { | |||
| 9071 | bool isEditable; | |||
| 9072 | if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable (&isEditable))), 0))) || | |||
| 9073 | !isEditable) { | |||
| 9074 | return nullptr; | |||
| 9075 | } | |||
| 9076 | return aDocShell->GetHTMLEditor(); | |||
| 9077 | } | |||
| 9078 | ||||
| 9079 | // static | |||
| 9080 | EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) { | |||
| 9081 | if (!aPresContext) { | |||
| 9082 | return nullptr; | |||
| 9083 | } | |||
| 9084 | ||||
| 9085 | return GetActiveEditor(aPresContext->Document()->GetWindow()); | |||
| 9086 | } | |||
| 9087 | ||||
| 9088 | // static | |||
| 9089 | EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) { | |||
| 9090 | if (!aWindow || !aWindow->GetExtantDoc()) { | |||
| 9091 | return nullptr; | |||
| 9092 | } | |||
| 9093 | ||||
| 9094 | // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor | |||
| 9095 | // handles all events. I.e., it's focused editor in this case. | |||
| 9096 | if (aWindow->GetExtantDoc()->IsInDesignMode()) { | |||
| 9097 | return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell())); | |||
| 9098 | } | |||
| 9099 | ||||
| 9100 | // If focused element is associated with TextEditor, it must be <input> | |||
| 9101 | // element or <textarea> element. Let's return it even if it's in a | |||
| 9102 | // contenteditable element. | |||
| 9103 | nsCOMPtr<nsPIDOMWindowOuter> focusedWindow; | |||
| 9104 | if (Element* focusedElement = nsFocusManager::GetFocusedDescendant( | |||
| 9105 | aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow, | |||
| 9106 | getter_AddRefs(focusedWindow))) { | |||
| 9107 | if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) { | |||
| 9108 | return textEditor; | |||
| 9109 | } | |||
| 9110 | } | |||
| 9111 | ||||
| 9112 | // Otherwise, HTMLEditor may handle inputs even non-editable element has | |||
| 9113 | // focus or nobody has focus. | |||
| 9114 | return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell())); | |||
| 9115 | } | |||
| 9116 | ||||
| 9117 | // static | |||
| 9118 | TextEditor* nsContentUtils::GetExtantTextEditorFromAnonymousNode( | |||
| 9119 | const nsIContent* aAnonymousContent) { | |||
| 9120 | if (!aAnonymousContent) { | |||
| 9121 | return nullptr; | |||
| 9122 | } | |||
| 9123 | nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent(); | |||
| 9124 | if (!parent || parent == aAnonymousContent) { | |||
| 9125 | return nullptr; | |||
| 9126 | } | |||
| 9127 | if (const HTMLInputElement* const inputElement = | |||
| 9128 | HTMLInputElement::FromNodeOrNull(parent)) { | |||
| 9129 | return inputElement->GetExtantTextEditor(); | |||
| 9130 | } | |||
| 9131 | if (const HTMLTextAreaElement* const textareaElement = | |||
| 9132 | HTMLTextAreaElement::FromNodeOrNull(parent)) { | |||
| 9133 | return textareaElement->GetExtantTextEditor(); | |||
| 9134 | } | |||
| 9135 | return nullptr; | |||
| 9136 | } | |||
| 9137 | ||||
| 9138 | // static | |||
| 9139 | bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) { | |||
| 9140 | while (aNode) { | |||
| 9141 | if (aNode->IsEditable()) { | |||
| 9142 | return true; | |||
| 9143 | } | |||
| 9144 | aNode = aNode->GetParent(); | |||
| 9145 | } | |||
| 9146 | return false; | |||
| 9147 | } | |||
| 9148 | ||||
| 9149 | // static | |||
| 9150 | bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader, | |||
| 9151 | const nsACString& aValue) { | |||
| 9152 | if (IsForbiddenSystemRequestHeader(aHeader)) { | |||
| 9153 | return true; | |||
| 9154 | } | |||
| 9155 | ||||
| 9156 | if ((nsContentUtils::IsOverrideMethodHeader(aHeader) && | |||
| 9157 | nsContentUtils::ContainsForbiddenMethod(aValue))) { | |||
| 9158 | return true; | |||
| 9159 | } | |||
| 9160 | ||||
| 9161 | if (StringBeginsWith(aHeader, "proxy-"_ns, | |||
| 9162 | nsCaseInsensitiveCStringComparator) || | |||
| 9163 | StringBeginsWith(aHeader, "sec-"_ns, | |||
| 9164 | nsCaseInsensitiveCStringComparator)) { | |||
| 9165 | return true; | |||
| 9166 | } | |||
| 9167 | ||||
| 9168 | return false; | |||
| 9169 | } | |||
| 9170 | ||||
| 9171 | // static | |||
| 9172 | bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) { | |||
| 9173 | static const char* kInvalidHeaders[] = {"accept-charset", | |||
| 9174 | "accept-encoding", | |||
| 9175 | "access-control-request-headers", | |||
| 9176 | "access-control-request-method", | |||
| 9177 | "connection", | |||
| 9178 | "content-length", | |||
| 9179 | "cookie", | |||
| 9180 | "cookie2", | |||
| 9181 | "date", | |||
| 9182 | "dnt", | |||
| 9183 | "expect", | |||
| 9184 | "host", | |||
| 9185 | "keep-alive", | |||
| 9186 | "origin", | |||
| 9187 | "referer", | |||
| 9188 | "set-cookie", | |||
| 9189 | "te", | |||
| 9190 | "trailer", | |||
| 9191 | "transfer-encoding", | |||
| 9192 | "upgrade", | |||
| 9193 | "via"}; | |||
| 9194 | for (auto& kInvalidHeader : kInvalidHeaders) { | |||
| 9195 | if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) { | |||
| 9196 | return true; | |||
| 9197 | } | |||
| 9198 | } | |||
| 9199 | return false; | |||
| 9200 | } | |||
| 9201 | ||||
| 9202 | // static | |||
| 9203 | bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) { | |||
| 9204 | return (aHeader.LowerCaseEqualsASCII("set-cookie") || | |||
| 9205 | aHeader.LowerCaseEqualsASCII("set-cookie2")); | |||
| 9206 | } | |||
| 9207 | ||||
| 9208 | // static | |||
| 9209 | bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) { | |||
| 9210 | return headerName.EqualsIgnoreCase("x-http-method-override") || | |||
| 9211 | headerName.EqualsIgnoreCase("x-http-method") || | |||
| 9212 | headerName.EqualsIgnoreCase("x-method-override"); | |||
| 9213 | } | |||
| 9214 | ||||
| 9215 | // static | |||
| 9216 | bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) { | |||
| 9217 | bool hasInsecureMethod = false; | |||
| 9218 | nsCCharSeparatedTokenizer tokenizer(headerValue, ','); | |||
| 9219 | ||||
| 9220 | while (tokenizer.hasMoreTokens()) { | |||
| 9221 | const nsDependentCSubstring& value = tokenizer.nextToken(); | |||
| 9222 | ||||
| 9223 | if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") || | |||
| 9224 | value.EqualsIgnoreCase("track")) { | |||
| 9225 | hasInsecureMethod = true; | |||
| 9226 | break; | |||
| 9227 | } | |||
| 9228 | } | |||
| 9229 | ||||
| 9230 | return hasInsecureMethod; | |||
| 9231 | } | |||
| 9232 | ||||
| 9233 | Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest( | |||
| 9234 | const nsACString& aHeaderValue, bool aAllowWhitespace) { | |||
| 9235 | // See https://fetch.spec.whatwg.org/#simple-range-header-value | |||
| 9236 | mozilla::Tokenizer p(aHeaderValue); | |||
| 9237 | Maybe<uint64_t> rangeStart; | |||
| 9238 | Maybe<uint64_t> rangeEnd; | |||
| 9239 | ||||
| 9240 | // Step 2 and 3 | |||
| 9241 | if (!p.CheckWord("bytes")) { | |||
| 9242 | return Nothing(); | |||
| 9243 | } | |||
| 9244 | ||||
| 9245 | // Step 4 | |||
| 9246 | if (aAllowWhitespace) { | |||
| 9247 | p.SkipWhites(); | |||
| 9248 | } | |||
| 9249 | ||||
| 9250 | // Step 5 and 6 | |||
| 9251 | if (!p.CheckChar('=')) { | |||
| 9252 | return Nothing(); | |||
| 9253 | } | |||
| 9254 | ||||
| 9255 | // Step 7 | |||
| 9256 | if (aAllowWhitespace) { | |||
| 9257 | p.SkipWhites(); | |||
| 9258 | } | |||
| 9259 | ||||
| 9260 | // Step 8 and 9 | |||
| 9261 | uint64_t res; | |||
| 9262 | if (p.ReadInteger(&res)) { | |||
| 9263 | rangeStart = Some(res); | |||
| 9264 | } | |||
| 9265 | ||||
| 9266 | // Step 10 | |||
| 9267 | if (aAllowWhitespace) { | |||
| 9268 | p.SkipWhites(); | |||
| 9269 | } | |||
| 9270 | ||||
| 9271 | // Step 11 | |||
| 9272 | if (!p.CheckChar('-')) { | |||
| 9273 | return Nothing(); | |||
| 9274 | } | |||
| 9275 | ||||
| 9276 | // Step 13 | |||
| 9277 | if (aAllowWhitespace) { | |||
| 9278 | p.SkipWhites(); | |||
| 9279 | } | |||
| 9280 | ||||
| 9281 | // Step 14 and 15 | |||
| 9282 | if (p.ReadInteger(&res)) { | |||
| 9283 | rangeEnd = Some(res); | |||
| 9284 | } | |||
| 9285 | ||||
| 9286 | // Step 16 | |||
| 9287 | if (!p.CheckEOF()) { | |||
| 9288 | return Nothing(); | |||
| 9289 | } | |||
| 9290 | ||||
| 9291 | // Step 17 | |||
| 9292 | if (!rangeStart && !rangeEnd) { | |||
| 9293 | return Nothing(); | |||
| 9294 | } | |||
| 9295 | ||||
| 9296 | // Step 18 | |||
| 9297 | if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) { | |||
| 9298 | return Nothing(); | |||
| 9299 | } | |||
| 9300 | ||||
| 9301 | return Some(ParsedRange(rangeStart, rangeEnd)); | |||
| 9302 | } | |||
| 9303 | ||||
| 9304 | // static | |||
| 9305 | bool nsContentUtils::IsCorsUnsafeRequestHeaderValue( | |||
| 9306 | const nsACString& aHeaderValue) { | |||
| 9307 | const char* cur = aHeaderValue.BeginReading(); | |||
| 9308 | const char* end = aHeaderValue.EndReading(); | |||
| 9309 | ||||
| 9310 | while (cur != end) { | |||
| 9311 | // Implementation of | |||
| 9312 | // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less | |||
| 9313 | // than a space but not a horizontal tab | |||
| 9314 | if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' || | |||
| 9315 | *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' || | |||
| 9316 | *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' || | |||
| 9317 | *cur == ']' || *cur == '{' || *cur == '}' || | |||
| 9318 | *cur == 0x7F) { // 0x75 is DEL | |||
| 9319 | return true; | |||
| 9320 | } | |||
| 9321 | cur++; | |||
| 9322 | } | |||
| 9323 | return false; | |||
| 9324 | } | |||
| 9325 | ||||
| 9326 | // static | |||
| 9327 | bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) { | |||
| 9328 | if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) { | |||
| 9329 | return false; | |||
| 9330 | } | |||
| 9331 | return true; | |||
| 9332 | } | |||
| 9333 | ||||
| 9334 | // static | |||
| 9335 | bool nsContentUtils::IsAllowedNonCorsContentType( | |||
| 9336 | const nsACString& aHeaderValue) { | |||
| 9337 | nsAutoCString contentType; | |||
| 9338 | nsAutoCString unused; | |||
| 9339 | ||||
| 9340 | if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) { | |||
| 9341 | return false; | |||
| 9342 | } | |||
| 9343 | ||||
| 9344 | nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused); | |||
| 9345 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 9346 | return false; | |||
| 9347 | } | |||
| 9348 | ||||
| 9349 | return contentType.LowerCaseEqualsLiteral("text/plain") || | |||
| 9350 | contentType.LowerCaseEqualsLiteral( | |||
| 9351 | "application/x-www-form-urlencoded") || | |||
| 9352 | contentType.LowerCaseEqualsLiteral("multipart/form-data"); | |||
| 9353 | } | |||
| 9354 | ||||
| 9355 | // static | |||
| 9356 | bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) { | |||
| 9357 | const char* cur = aHeaderValue.BeginReading(); | |||
| 9358 | const char* end = aHeaderValue.EndReading(); | |||
| 9359 | ||||
| 9360 | while (cur != end) { | |||
| 9361 | if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') || | |||
| 9362 | (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' || | |||
| 9363 | *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' || | |||
| 9364 | *cur == '=') { | |||
| 9365 | cur++; | |||
| 9366 | continue; | |||
| 9367 | } | |||
| 9368 | return false; | |||
| 9369 | } | |||
| 9370 | return true; | |||
| 9371 | } | |||
| 9372 | ||||
| 9373 | bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) { | |||
| 9374 | Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false); | |||
| 9375 | if (!parsedRange) { | |||
| 9376 | return false; | |||
| 9377 | } | |||
| 9378 | ||||
| 9379 | if (!parsedRange->Start()) { | |||
| 9380 | return false; | |||
| 9381 | } | |||
| 9382 | ||||
| 9383 | return true; | |||
| 9384 | } | |||
| 9385 | ||||
| 9386 | // static | |||
| 9387 | bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName, | |||
| 9388 | const nsACString& aValue) { | |||
| 9389 | // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header | |||
| 9390 | if (aValue.Length() > 128) { | |||
| 9391 | return false; | |||
| 9392 | } | |||
| 9393 | return (aName.LowerCaseEqualsLiteral("accept") && | |||
| 9394 | nsContentUtils::IsAllowedNonCorsAccept(aValue)) || | |||
| 9395 | (aName.LowerCaseEqualsLiteral("accept-language") && | |||
| 9396 | nsContentUtils::IsAllowedNonCorsLanguage(aValue)) || | |||
| 9397 | (aName.LowerCaseEqualsLiteral("content-language") && | |||
| 9398 | nsContentUtils::IsAllowedNonCorsLanguage(aValue)) || | |||
| 9399 | (aName.LowerCaseEqualsLiteral("content-type") && | |||
| 9400 | nsContentUtils::IsAllowedNonCorsContentType(aValue)) || | |||
| 9401 | (aName.LowerCaseEqualsLiteral("range") && | |||
| 9402 | nsContentUtils::IsAllowedNonCorsRange(aValue)) || | |||
| 9403 | (StaticPrefs::network_http_idempotencyKey_enabled() && | |||
| 9404 | aName.LowerCaseEqualsLiteral("idempotency-key")); | |||
| 9405 | } | |||
| 9406 | ||||
| 9407 | mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() { | |||
| 9408 | return gResistFingerprintingLog; | |||
| 9409 | } | |||
| 9410 | mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; } | |||
| 9411 | ||||
| 9412 | bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 9413 | nsAString& aResult, | |||
| 9414 | const fallible_t& aFallible) { | |||
| 9415 | aResult.Truncate(); | |||
| 9416 | return AppendNodeTextContent(aNode, aDeep, aResult, aFallible); | |||
| 9417 | } | |||
| 9418 | ||||
| 9419 | bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 9420 | nsACString& aResult, | |||
| 9421 | const fallible_t& aFallible) { | |||
| 9422 | aResult.Truncate(); | |||
| 9423 | return AppendNodeTextContent(aNode, aDeep, aResult, aFallible); | |||
| 9424 | } | |||
| 9425 | ||||
| 9426 | void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 9427 | nsAString& aResult) { | |||
| 9428 | if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) { | |||
| 9429 | NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size | |||
| 9430 | } | |||
| 9431 | } | |||
| 9432 | ||||
| 9433 | void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
| 9434 | nsACString& aResult) { | |||
| 9435 | if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) { | |||
| 9436 | NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size | |||
| 9437 | } | |||
| 9438 | } | |||
| 9439 | ||||
| 9440 | void nsContentUtils::DestroyMatchString(void* aData) { | |||
| 9441 | if (aData) { | |||
| 9442 | nsString* matchString = static_cast<nsString*>(aData); | |||
| 9443 | delete matchString; | |||
| 9444 | } | |||
| 9445 | } | |||
| 9446 | ||||
| 9447 | // Table ordered from most to least likely JS MIME types. | |||
| 9448 | static constexpr std::string_view kJavascriptMIMETypes[] = { | |||
| 9449 | "text/javascript", | |||
| 9450 | "text/ecmascript", | |||
| 9451 | "application/javascript", | |||
| 9452 | "application/ecmascript", | |||
| 9453 | "application/x-javascript", | |||
| 9454 | "application/x-ecmascript", | |||
| 9455 | "text/javascript1.0", | |||
| 9456 | "text/javascript1.1", | |||
| 9457 | "text/javascript1.2", | |||
| 9458 | "text/javascript1.3", | |||
| 9459 | "text/javascript1.4", | |||
| 9460 | "text/javascript1.5", | |||
| 9461 | "text/jscript", | |||
| 9462 | "text/livescript", | |||
| 9463 | "text/x-ecmascript", | |||
| 9464 | "text/x-javascript"}; | |||
| 9465 | ||||
| 9466 | bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) { | |||
| 9467 | for (std::string_view type : kJavascriptMIMETypes) { | |||
| 9468 | if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) { | |||
| 9469 | return true; | |||
| 9470 | } | |||
| 9471 | } | |||
| 9472 | return false; | |||
| 9473 | } | |||
| 9474 | ||||
| 9475 | bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) { | |||
| 9476 | for (std::string_view type : kJavascriptMIMETypes) { | |||
| 9477 | if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) { | |||
| 9478 | return true; | |||
| 9479 | } | |||
| 9480 | } | |||
| 9481 | return false; | |||
| 9482 | } | |||
| 9483 | ||||
| 9484 | // https://mimesniff.spec.whatwg.org/#json-mime-type | |||
| 9485 | bool nsContentUtils::IsJsonMimeType(const nsAString& aMimeType) { | |||
| 9486 | // Table ordered from most to least likely JSON MIME types. | |||
| 9487 | static constexpr std::string_view jsonTypes[] = {"application/json", | |||
| 9488 | "text/json"}; | |||
| 9489 | ||||
| 9490 | for (std::string_view type : jsonTypes) { | |||
| 9491 | if (aMimeType.LowerCaseEqualsASCII(type.data(), type.length())) { | |||
| 9492 | return true; | |||
| 9493 | } | |||
| 9494 | } | |||
| 9495 | ||||
| 9496 | // Below checks if the 'subtype' ends in "+json". | |||
| 9497 | RefPtr<MimeType> parsed = MimeType::Parse(aMimeType); | |||
| 9498 | if (!parsed) { | |||
| 9499 | return false; | |||
| 9500 | } | |||
| 9501 | ||||
| 9502 | nsAutoString subtype; | |||
| 9503 | parsed->GetSubtype(subtype); | |||
| 9504 | return StringEndsWith(subtype, u"+json"_ns); | |||
| 9505 | } | |||
| 9506 | ||||
| 9507 | // https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.7.3 | |||
| 9508 | bool nsContentUtils::HasCssMimeTypeEssence(const nsAString& aMimeType) { | |||
| 9509 | nsString contentType, contentCharset; | |||
| 9510 | if (MimeType::Parse(aMimeType, contentType, contentCharset)) { | |||
| 9511 | return contentType.LowerCaseEqualsLiteral("text/css"); | |||
| 9512 | } | |||
| 9513 | return false; | |||
| 9514 | } | |||
| 9515 | ||||
| 9516 | // https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.6 | |||
| 9517 | bool nsContentUtils::HasWasmMimeTypeEssence(const nsAString& aMimeType) { | |||
| 9518 | nsString contentType, contentCharset; | |||
| 9519 | if (MimeType::Parse(aMimeType, contentType, contentCharset)) { | |||
| 9520 | return contentType.LowerCaseEqualsLiteral("application/wasm"); | |||
| 9521 | } | |||
| 9522 | return false; | |||
| 9523 | } | |||
| 9524 | ||||
| 9525 | bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) { | |||
| 9526 | // | |||
| 9527 | // SECURITY CHECK: disable prefetching and preloading from mailnews! | |||
| 9528 | // | |||
| 9529 | // walk up the docshell tree to see if any containing | |||
| 9530 | // docshell are of type MAIL. | |||
| 9531 | // | |||
| 9532 | ||||
| 9533 | if (!aDocShell) { | |||
| 9534 | return false; | |||
| 9535 | } | |||
| 9536 | ||||
| 9537 | nsCOMPtr<nsIDocShell> docshell = aDocShell; | |||
| 9538 | nsCOMPtr<nsIDocShellTreeItem> parentItem; | |||
| 9539 | ||||
| 9540 | do { | |||
| 9541 | auto appType = docshell->GetAppType(); | |||
| 9542 | if (appType == nsIDocShell::APP_TYPE_MAIL) { | |||
| 9543 | return false; // do not prefetch, preload, preconnect from mailnews | |||
| 9544 | } | |||
| 9545 | ||||
| 9546 | docshell->GetInProcessParent(getter_AddRefs(parentItem)); | |||
| 9547 | if (parentItem) { | |||
| 9548 | docshell = do_QueryInterface(parentItem); | |||
| 9549 | if (!docshell) { | |||
| 9550 | NS_ERROR("cannot get a docshell from a treeItem!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "cannot get a docshell from a treeItem!" , "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9550); MOZ_PretendNoReturn(); } while (0); | |||
| 9551 | return false; | |||
| 9552 | } | |||
| 9553 | } | |||
| 9554 | } while (parentItem); | |||
| 9555 | ||||
| 9556 | return true; | |||
| 9557 | } | |||
| 9558 | ||||
| 9559 | uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) { | |||
| 9560 | // can't do anything if there's no nsIRequest! | |||
| 9561 | if (!aRequest) { | |||
| 9562 | return 0; | |||
| 9563 | } | |||
| 9564 | ||||
| 9565 | if (nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest)) { | |||
| 9566 | nsCOMPtr loadInfo = channel->LoadInfo(); | |||
| 9567 | if (auto id = loadInfo->GetInnerWindowID()) { | |||
| 9568 | return id; | |||
| 9569 | } | |||
| 9570 | if (auto id = loadInfo->GetTriggeringWindowId()) { | |||
| 9571 | return id; | |||
| 9572 | } | |||
| 9573 | } | |||
| 9574 | ||||
| 9575 | nsCOMPtr<nsILoadGroup> loadGroup; | |||
| 9576 | nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup)); | |||
| 9577 | ||||
| 9578 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) { | |||
| 9579 | return 0; | |||
| 9580 | } | |||
| 9581 | ||||
| 9582 | return GetInnerWindowID(loadGroup); | |||
| 9583 | } | |||
| 9584 | ||||
| 9585 | uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) { | |||
| 9586 | if (!aLoadGroup) { | |||
| 9587 | return 0; | |||
| 9588 | } | |||
| 9589 | ||||
| 9590 | nsCOMPtr<nsIInterfaceRequestor> callbacks; | |||
| 9591 | nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); | |||
| 9592 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) { | |||
| 9593 | return 0; | |||
| 9594 | } | |||
| 9595 | ||||
| 9596 | nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); | |||
| 9597 | if (!loadContext) { | |||
| 9598 | return 0; | |||
| 9599 | } | |||
| 9600 | ||||
| 9601 | nsCOMPtr<mozIDOMWindowProxy> window; | |||
| 9602 | rv = loadContext->GetAssociatedWindow(getter_AddRefs(window)); | |||
| 9603 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) { | |||
| 9604 | return 0; | |||
| 9605 | } | |||
| 9606 | ||||
| 9607 | auto* pwindow = nsPIDOMWindowOuter::From(window); | |||
| 9608 | if (!pwindow) { | |||
| 9609 | return 0; | |||
| 9610 | } | |||
| 9611 | ||||
| 9612 | nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow(); | |||
| 9613 | return inner ? inner->WindowID() : 0; | |||
| 9614 | } | |||
| 9615 | ||||
| 9616 | // static | |||
| 9617 | void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) { | |||
| 9618 | if (aHost.FindChar(':') != -1) { // Escape IPv6 address | |||
| 9619 | MOZ_ASSERT(!aHost.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aHost.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aHost.IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aHost.IsEmpty()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9619); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!aHost.IsEmpty()" ")"); do { MOZ_CrashSequence (__null, 9619); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 9620 | if (aHost.Length() >= 2 && aHost[0] != '[' && | |||
| 9621 | aHost[aHost.Length() - 1] != ']') { | |||
| 9622 | aHost.Insert('[', 0); | |||
| 9623 | aHost.Append(']'); | |||
| 9624 | } | |||
| 9625 | } | |||
| 9626 | } | |||
| 9627 | ||||
| 9628 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, | |||
| 9629 | nsACString& aHost) { | |||
| 9630 | aHost.Truncate(); | |||
| 9631 | nsresult rv = aURI->GetHost(aHost); | |||
| 9632 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host | |||
| 9633 | return rv; | |||
| 9634 | } | |||
| 9635 | ||||
| 9636 | MaybeFixIPv6Host(aHost); | |||
| 9637 | ||||
| 9638 | return NS_OK; | |||
| 9639 | } | |||
| 9640 | ||||
| 9641 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, | |||
| 9642 | nsAString& aHost) { | |||
| 9643 | nsAutoCString hostname; | |||
| 9644 | nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname); | |||
| 9645 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 9646 | return rv; | |||
| 9647 | } | |||
| 9648 | CopyUTF8toUTF16(hostname, aHost); | |||
| 9649 | return NS_OK; | |||
| 9650 | } | |||
| 9651 | ||||
| 9652 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal, | |||
| 9653 | nsACString& aHost) { | |||
| 9654 | nsresult rv = aPrincipal->GetAsciiHost(aHost); | |||
| 9655 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host | |||
| 9656 | return rv; | |||
| 9657 | } | |||
| 9658 | ||||
| 9659 | MaybeFixIPv6Host(aHost); | |||
| 9660 | return NS_OK; | |||
| 9661 | } | |||
| 9662 | ||||
| 9663 | nsresult nsContentUtils::GetAsciiHostOrIPv6WithBrackets(nsIURI* aURI, | |||
| 9664 | nsACString& aHost) { | |||
| 9665 | aHost.Truncate(); | |||
| 9666 | nsresult rv = aURI->GetAsciiHost(aHost); | |||
| 9667 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 9668 | return rv; | |||
| 9669 | } | |||
| 9670 | ||||
| 9671 | MaybeFixIPv6Host(aHost); | |||
| 9672 | return NS_OK; | |||
| 9673 | } | |||
| 9674 | ||||
| 9675 | CallState nsContentUtils::CallOnAllRemoteChildren( | |||
| 9676 | MessageBroadcaster* aManager, | |||
| 9677 | const std::function<CallState(BrowserParent*)>& aCallback) { | |||
| 9678 | uint32_t browserChildCount = aManager->ChildCount(); | |||
| 9679 | for (uint32_t j = 0; j < browserChildCount; ++j) { | |||
| 9680 | RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j); | |||
| 9681 | if (!childMM) { | |||
| 9682 | continue; | |||
| 9683 | } | |||
| 9684 | ||||
| 9685 | RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM); | |||
| 9686 | if (nonLeafMM) { | |||
| 9687 | if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) { | |||
| 9688 | return CallState::Stop; | |||
| 9689 | } | |||
| 9690 | continue; | |||
| 9691 | } | |||
| 9692 | ||||
| 9693 | mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback(); | |||
| 9694 | if (cb) { | |||
| 9695 | nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb); | |||
| 9696 | BrowserParent* remote = BrowserParent::GetFrom(fl); | |||
| 9697 | if (remote && aCallback) { | |||
| 9698 | if (aCallback(remote) == CallState::Stop) { | |||
| 9699 | return CallState::Stop; | |||
| 9700 | } | |||
| 9701 | } | |||
| 9702 | } | |||
| 9703 | } | |||
| 9704 | ||||
| 9705 | return CallState::Continue; | |||
| 9706 | } | |||
| 9707 | ||||
| 9708 | void nsContentUtils::CallOnAllRemoteChildren( | |||
| 9709 | nsPIDOMWindowOuter* aWindow, | |||
| 9710 | const std::function<CallState(BrowserParent*)>& aCallback) { | |||
| 9711 | nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow); | |||
| 9712 | if (window->IsChromeWindow()) { | |||
| 9713 | RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager(); | |||
| 9714 | if (windowMM) { | |||
| 9715 | CallOnAllRemoteChildren(windowMM, aCallback); | |||
| 9716 | } | |||
| 9717 | } | |||
| 9718 | } | |||
| 9719 | ||||
| 9720 | bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor( | |||
| 9721 | const IPCTransferableDataItem& aItem) { | |||
| 9722 | // Unknown types are converted to kCustomTypesMime. | |||
| 9723 | if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) { | |||
| 9724 | return true; | |||
| 9725 | } | |||
| 9726 | ||||
| 9727 | for (const char* format : DataTransfer::kKnownFormats) { | |||
| 9728 | if (aItem.flavor().EqualsASCII(format)) { | |||
| 9729 | return true; | |||
| 9730 | } | |||
| 9731 | } | |||
| 9732 | ||||
| 9733 | // Clipboard custom type. Only recognise "web foo/bar" as a known flavor | |||
| 9734 | // when the web custom format feature is enabled; otherwise DnD or other | |||
| 9735 | // callers must not be able to slip web custom flavors through this helper. | |||
| 9736 | const nsCString& flavor = aItem.flavor(); | |||
| 9737 | if (StaticPrefs::dom_clipboard_customFormatSupport_enabled() && | |||
| 9738 | StringBeginsWith(flavor, nsLiteralCString(kWebCustomFormatPrefix"web "))) { | |||
| 9739 | if (RefPtr<CMimeType> parsedType = CMimeType::Parse(Substring( | |||
| 9740 | flavor, strlen(kWebCustomFormatPrefix"web "), flavor.Length()))) { | |||
| 9741 | return true; | |||
| 9742 | } | |||
| 9743 | } | |||
| 9744 | ||||
| 9745 | return false; | |||
| 9746 | } | |||
| 9747 | ||||
| 9748 | nsresult nsContentUtils::IPCTransferableDataToTransferable( | |||
| 9749 | const IPCTransferableData& aTransferableData, bool aAddDataFlavor, | |||
| 9750 | nsITransferable* aTransferable, const bool aFilterUnknownFlavors) { | |||
| 9751 | nsresult rv; | |||
| 9752 | const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items(); | |||
| 9753 | for (const auto& item : items) { | |||
| 9754 | if (aFilterUnknownFlavors) { | |||
| 9755 | if (item.flavor().EqualsLiteral(kFilePromiseDirectoryMime"application/x-moz-file-promise-dir")) { | |||
| 9756 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758) | |||
| 9757 | "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758) | |||
| 9758 | "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758); | |||
| 9759 | continue; | |||
| 9760 | } | |||
| 9761 | ||||
| 9762 | if ((item.flavor().EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise") || | |||
| 9763 | item.flavor().EqualsLiteral(kFilePromiseURLMime"application/x-moz-file-promise-url") || | |||
| 9764 | item.flavor().EqualsLiteral(kFilePromiseDestFilename"application/x-moz-file-promise-dest-filename")) | |||
| 9765 | #ifdef XP_WIN | |||
| 9766 | && !StaticPrefs::clipboard_imageAsFile_enabled() | |||
| 9767 | #endif | |||
| 9768 | ) { | |||
| 9769 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771) | |||
| 9770 | "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771) | |||
| 9771 | "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771); | |||
| 9772 | continue; | |||
| 9773 | } | |||
| 9774 | ||||
| 9775 | if (!IPCTransferableDataItemHasKnownFlavor(item)) { | |||
| 9776 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778) | |||
| 9777 | "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778) | |||
| 9778 | "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778); | |||
| 9779 | continue; | |||
| 9780 | } | |||
| 9781 | } | |||
| 9782 | ||||
| 9783 | if (aAddDataFlavor) { | |||
| 9784 | aTransferable->AddDataFlavor(item.flavor().get()); | |||
| 9785 | } | |||
| 9786 | ||||
| 9787 | nsCOMPtr<nsISupports> transferData; | |||
| 9788 | switch (item.data().type()) { | |||
| 9789 | case IPCTransferableDataType::TIPCTransferableDataString: { | |||
| 9790 | const auto& data = item.data().get_IPCTransferableDataString(); | |||
| 9791 | nsCOMPtr<nsISupportsString> dataWrapper = | |||
| 9792 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); | |||
| 9793 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9793); return rv; } } while (false); | |||
| 9794 | rv = dataWrapper->SetData(nsDependentSubstring( | |||
| 9795 | reinterpret_cast<const char16_t*>(data.data().Data()), | |||
| 9796 | data.data().Size() / sizeof(char16_t))); | |||
| 9797 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9797); return rv; } } while (false); | |||
| 9798 | transferData = dataWrapper; | |||
| 9799 | break; | |||
| 9800 | } | |||
| 9801 | case IPCTransferableDataType::TIPCTransferableDataCString: { | |||
| 9802 | const auto& data = item.data().get_IPCTransferableDataCString(); | |||
| 9803 | nsCOMPtr<nsISupportsCString> dataWrapper = | |||
| 9804 | do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv); | |||
| 9805 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9805); return rv; } } while (false); | |||
| 9806 | rv = dataWrapper->SetData(nsDependentCSubstring( | |||
| 9807 | reinterpret_cast<const char*>(data.data().Data()), | |||
| 9808 | data.data().Size())); | |||
| 9809 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9809); return rv; } } while (false); | |||
| 9810 | transferData = dataWrapper; | |||
| 9811 | break; | |||
| 9812 | } | |||
| 9813 | case IPCTransferableDataType::TIPCTransferableDataInputStream: { | |||
| 9814 | const auto& data = item.data().get_IPCTransferableDataInputStream(); | |||
| 9815 | nsCOMPtr<nsIInputStream> stream; | |||
| 9816 | rv = NS_NewByteInputStream(getter_AddRefs(stream), | |||
| 9817 | AsChars(data.data().AsSpan()), | |||
| 9818 | NS_ASSIGNMENT_COPY); | |||
| 9819 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9819); return rv; } } while (false); | |||
| 9820 | transferData = stream.forget(); | |||
| 9821 | break; | |||
| 9822 | } | |||
| 9823 | case IPCTransferableDataType::TIPCTransferableDataImageContainer: { | |||
| 9824 | const auto& data = item.data().get_IPCTransferableDataImageContainer(); | |||
| 9825 | nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image()); | |||
| 9826 | if (!container) { | |||
| 9827 | return NS_ERROR_FAILURE; | |||
| 9828 | } | |||
| 9829 | transferData = container; | |||
| 9830 | break; | |||
| 9831 | } | |||
| 9832 | case IPCTransferableDataType::TIPCTransferableDataBlob: { | |||
| 9833 | const auto& data = item.data().get_IPCTransferableDataBlob(); | |||
| 9834 | transferData = IPCBlobUtils::Deserialize(data.blob()); | |||
| 9835 | break; | |||
| 9836 | } | |||
| 9837 | case IPCTransferableDataType::T__None: | |||
| 9838 | MOZ_ASSERT_UNREACHABLE()do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9838 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " ")"); do { MOZ_CrashSequence(__null, 9838); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 9839 | return NS_ERROR_FAILURE; | |||
| 9840 | } | |||
| 9841 | ||||
| 9842 | rv = aTransferable->SetTransferData(item.flavor().get(), transferData); | |||
| 9843 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9843); return rv; } } while (false); | |||
| 9844 | } | |||
| 9845 | return NS_OK; | |||
| 9846 | } | |||
| 9847 | ||||
| 9848 | nsresult nsContentUtils::IPCTransferableToTransferable( | |||
| 9849 | const IPCTransferable& aIPCTransferable, bool aAddDataFlavor, | |||
| 9850 | nsITransferable* aTransferable, const bool aFilterUnknownFlavors) { | |||
| 9851 | // Note that we need to set privacy status of transferable before adding any | |||
| 9852 | // data into it. | |||
| 9853 | aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData()); | |||
| 9854 | ||||
| 9855 | nsresult rv = | |||
| 9856 | IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor, | |||
| 9857 | aTransferable, aFilterUnknownFlavors); | |||
| 9858 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9858); return rv; } } while (false); | |||
| 9859 | ||||
| 9860 | if (aIPCTransferable.cookieJarSettings().isSome()) { | |||
| 9861 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings; | |||
| 9862 | net::CookieJarSettings::Deserialize( | |||
| 9863 | aIPCTransferable.cookieJarSettings().ref(), | |||
| 9864 | getter_AddRefs(cookieJarSettings)); | |||
| 9865 | aTransferable->SetCookieJarSettings(cookieJarSettings); | |||
| 9866 | } | |||
| 9867 | aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo()); | |||
| 9868 | aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal()); | |||
| 9869 | aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType()); | |||
| 9870 | ||||
| 9871 | return NS_OK; | |||
| 9872 | } | |||
| 9873 | ||||
| 9874 | nsresult nsContentUtils::IPCTransferableDataItemToVariant( | |||
| 9875 | const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) { | |||
| 9876 | MOZ_ASSERT(aVariant)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aVariant)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aVariant))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aVariant", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")" ); do { MOZ_CrashSequence(__null, 9876); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 9877 | ||||
| 9878 | switch (aItem.data().type()) { | |||
| 9879 | case IPCTransferableDataType::TIPCTransferableDataString: { | |||
| 9880 | const auto& data = aItem.data().get_IPCTransferableDataString(); | |||
| 9881 | return aVariant->SetAsAString(nsDependentSubstring( | |||
| 9882 | reinterpret_cast<const char16_t*>(data.data().Data()), | |||
| 9883 | data.data().Size() / sizeof(char16_t))); | |||
| 9884 | } | |||
| 9885 | case IPCTransferableDataType::TIPCTransferableDataCString: { | |||
| 9886 | const auto& data = aItem.data().get_IPCTransferableDataCString(); | |||
| 9887 | return aVariant->SetAsACString(nsDependentCSubstring( | |||
| 9888 | reinterpret_cast<const char*>(data.data().Data()), | |||
| 9889 | data.data().Size())); | |||
| 9890 | } | |||
| 9891 | case IPCTransferableDataType::TIPCTransferableDataInputStream: { | |||
| 9892 | const auto& data = aItem.data().get_IPCTransferableDataInputStream(); | |||
| 9893 | nsCOMPtr<nsIInputStream> stream; | |||
| 9894 | nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), | |||
| 9895 | AsChars(data.data().AsSpan()), | |||
| 9896 | NS_ASSIGNMENT_COPY); | |||
| 9897 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 9897); return rv; } } while (false); | |||
| 9898 | return aVariant->SetAsISupports(stream); | |||
| 9899 | } | |||
| 9900 | case IPCTransferableDataType::TIPCTransferableDataImageContainer: { | |||
| 9901 | const auto& data = aItem.data().get_IPCTransferableDataImageContainer(); | |||
| 9902 | nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image()); | |||
| 9903 | if (!container) { | |||
| 9904 | return NS_ERROR_FAILURE; | |||
| 9905 | } | |||
| 9906 | return aVariant->SetAsISupports(container); | |||
| 9907 | } | |||
| 9908 | case IPCTransferableDataType::TIPCTransferableDataBlob: { | |||
| 9909 | const auto& data = aItem.data().get_IPCTransferableDataBlob(); | |||
| 9910 | RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob()); | |||
| 9911 | return aVariant->SetAsISupports(blobImpl); | |||
| 9912 | } | |||
| 9913 | case IPCTransferableDataType::T__None: | |||
| 9914 | break; | |||
| 9915 | } | |||
| 9916 | ||||
| 9917 | MOZ_ASSERT_UNREACHABLE()do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9917 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " ")"); do { MOZ_CrashSequence(__null, 9917); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 9918 | return NS_ERROR_UNEXPECTED; | |||
| 9919 | } | |||
| 9920 | ||||
| 9921 | void nsContentUtils::TransferablesToIPCTransferableDatas( | |||
| 9922 | nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC, | |||
| 9923 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
| 9924 | aIPC.Clear(); | |||
| 9925 | if (aTransferables) { | |||
| 9926 | uint32_t transferableCount = 0; | |||
| 9927 | aTransferables->GetLength(&transferableCount); | |||
| 9928 | for (uint32_t i = 0; i < transferableCount; ++i) { | |||
| 9929 | IPCTransferableData* dt = aIPC.AppendElement(); | |||
| 9930 | nsCOMPtr<nsITransferable> transferable = | |||
| 9931 | do_QueryElementAt(aTransferables, i); | |||
| 9932 | TransferableToIPCTransferableData(transferable, dt, aInSyncMessage, | |||
| 9933 | aParent); | |||
| 9934 | } | |||
| 9935 | } | |||
| 9936 | } | |||
| 9937 | ||||
| 9938 | nsresult nsContentUtils::CalculateBufferSizeForImage( | |||
| 9939 | const uint32_t& aStride, const IntSize& aImageSize, | |||
| 9940 | const SurfaceFormat& aFormat, size_t* aMaxBufferSize, | |||
| 9941 | size_t* aUsedBufferSize) { | |||
| 9942 | if (aImageSize.width <= 0 || aImageSize.height <= 0) { | |||
| 9943 | return NS_ERROR_FAILURE; | |||
| 9944 | } | |||
| 9945 | ||||
| 9946 | CheckedInt32 rowBytes = | |||
| 9947 | CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat); | |||
| 9948 | CheckedInt32 stride(aStride); | |||
| 9949 | if (!rowBytes.isValid() || !stride.isValid() || | |||
| 9950 | stride.value() < rowBytes.value()) { | |||
| 9951 | return NS_ERROR_FAILURE; | |||
| 9952 | } | |||
| 9953 | ||||
| 9954 | CheckedInt32 requiredBytes = stride * CheckedInt32(aImageSize.height); | |||
| 9955 | CheckedInt32 usedBytes = requiredBytes - stride + rowBytes; | |||
| 9956 | if (!requiredBytes.isValid() || !usedBytes.isValid()) { | |||
| 9957 | return NS_ERROR_FAILURE; | |||
| 9958 | } | |||
| 9959 | ||||
| 9960 | *aMaxBufferSize = requiredBytes.value(); | |||
| 9961 | *aUsedBufferSize = usedBytes.value(); | |||
| 9962 | return NS_OK; | |||
| 9963 | } | |||
| 9964 | ||||
| 9965 | static already_AddRefed<DataSourceSurface> BigBufferToDataSurface( | |||
| 9966 | const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize, | |||
| 9967 | SurfaceFormat aFormat) { | |||
| 9968 | if (!aData.Size() || !aImageSize.width || !aImageSize.height) { | |||
| 9969 | return nullptr; | |||
| 9970 | } | |||
| 9971 | ||||
| 9972 | // Validate shared memory buffer size | |||
| 9973 | size_t imageBufLen = 0; | |||
| 9974 | size_t maxBufLen = 0; | |||
| 9975 | if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage ( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen ))), 0))) | |||
| 9976 | aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage ( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen ))), 0)))) { | |||
| 9977 | return nullptr; | |||
| 9978 | } | |||
| 9979 | if (imageBufLen > aData.Size()) { | |||
| 9980 | return nullptr; | |||
| 9981 | } | |||
| 9982 | return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(), | |||
| 9983 | aStride); | |||
| 9984 | } | |||
| 9985 | ||||
| 9986 | bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) { | |||
| 9987 | return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") || | |||
| 9988 | aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") || | |||
| 9989 | aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") || | |||
| 9990 | aFlavor.EqualsLiteral(kPNGImageMime"image/png") || | |||
| 9991 | aFlavor.EqualsLiteral(kGIFImageMime"image/gif"); | |||
| 9992 | } | |||
| 9993 | ||||
| 9994 | // FIXME: This can probably be removed once bug 1783240 lands, as `nsString` | |||
| 9995 | // will be implicitly serialized in shmem when sent over IPDL directly. | |||
| 9996 | static IPCTransferableDataString AsIPCTransferableDataString( | |||
| 9997 | Span<const char16_t> aInput) { | |||
| 9998 | return IPCTransferableDataString{BigBuffer(AsBytes(aInput))}; | |||
| 9999 | } | |||
| 10000 | ||||
| 10001 | // FIXME: This can probably be removed once bug 1783240 lands, as `nsCString` | |||
| 10002 | // will be implicitly serialized in shmem when sent over IPDL directly. | |||
| 10003 | static IPCTransferableDataCString AsIPCTransferableDataCString( | |||
| 10004 | Span<const char> aInput) { | |||
| 10005 | return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))}; | |||
| 10006 | } | |||
| 10007 | ||||
| 10008 | void nsContentUtils::TransferableToIPCTransferableData( | |||
| 10009 | nsITransferable* aTransferable, IPCTransferableData* aTransferableData, | |||
| 10010 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
| 10011 | MOZ_ASSERT_IF(XRE_IsParentProcess(), aParent)do { if (XRE_IsParentProcess()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(aParent)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")" ); do { MOZ_CrashSequence(__null, 10011); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
| 10012 | ||||
| 10013 | if (aTransferable) { | |||
| 10014 | nsTArray<nsCString> flavorList; | |||
| 10015 | aTransferable->FlavorsTransferableCanExport(flavorList); | |||
| 10016 | ||||
| 10017 | for (uint32_t j = 0; j < flavorList.Length(); ++j) { | |||
| 10018 | nsCString& flavorStr = flavorList[j]; | |||
| 10019 | if (!flavorStr.Length()) { | |||
| 10020 | continue; | |||
| 10021 | } | |||
| 10022 | ||||
| 10023 | nsCOMPtr<nsISupports> data; | |||
| 10024 | nsresult rv = | |||
| 10025 | aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data)); | |||
| 10026 | ||||
| 10027 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) { | |||
| 10028 | if (aInSyncMessage) { | |||
| 10029 | // Can't do anything. | |||
| 10030 | // FIXME: This shouldn't be the case anymore! | |||
| 10031 | continue; | |||
| 10032 | } | |||
| 10033 | ||||
| 10034 | // This is a hack to support kFilePromiseMime. | |||
| 10035 | // On Windows there just needs to be an entry for it, | |||
| 10036 | // and for OSX we need to create | |||
| 10037 | // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider. | |||
| 10038 | if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) { | |||
| 10039 | IPCTransferableDataItem* item = | |||
| 10040 | aTransferableData->items().AppendElement(); | |||
| 10041 | item->flavor() = flavorStr; | |||
| 10042 | item->data() = | |||
| 10043 | AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr)); | |||
| 10044 | continue; | |||
| 10045 | } | |||
| 10046 | ||||
| 10047 | // Empty element, transfer only the flavor | |||
| 10048 | IPCTransferableDataItem* item = | |||
| 10049 | aTransferableData->items().AppendElement(); | |||
| 10050 | item->flavor() = flavorStr; | |||
| 10051 | item->data() = AsIPCTransferableDataString(EmptyString()); | |||
| 10052 | continue; | |||
| 10053 | } | |||
| 10054 | ||||
| 10055 | // We need to handle nsIInputStream before nsISupportsCString, otherwise | |||
| 10056 | // nsStringInputStream would be converted into a wrong type. | |||
| 10057 | if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) { | |||
| 10058 | IPCTransferableDataItem* item = | |||
| 10059 | aTransferableData->items().AppendElement(); | |||
| 10060 | item->flavor() = flavorStr; | |||
| 10061 | nsCString imageData; | |||
| 10062 | DebugOnly<nsresult> rv = | |||
| 10063 | NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData); | |||
| 10064 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10066 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { MOZ_CrashSequence(__null, 10066); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 10065 | rv != NS_BASE_STREAM_WOULD_BLOCK,do { static_assert( mozilla::detail::AssertionConditionType< decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10066 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { MOZ_CrashSequence(__null, 10066); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 10066 | "cannot use async input streams in nsITransferable right now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10066 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { MOZ_CrashSequence(__null, 10066); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10067 | // FIXME: This can probably be simplified once bug 1783240 lands, as | |||
| 10068 | // `nsCString` will be implicitly serialized in shmem when sent over | |||
| 10069 | // IPDL directly. | |||
| 10070 | item->data() = | |||
| 10071 | IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData)))); | |||
| 10072 | continue; | |||
| 10073 | } | |||
| 10074 | ||||
| 10075 | if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) { | |||
| 10076 | nsAutoString dataAsString; | |||
| 10077 | MOZ_ALWAYS_SUCCEEDS(text->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (text->GetData(dataAsString))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(text->GetData(dataAsString))" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10077); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(text->GetData(dataAsString))" ")" ); do { MOZ_CrashSequence(__null, 10077); __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); | |||
| 10078 | ||||
| 10079 | IPCTransferableDataItem* item = | |||
| 10080 | aTransferableData->items().AppendElement(); | |||
| 10081 | item->flavor() = flavorStr; | |||
| 10082 | item->data() = AsIPCTransferableDataString(dataAsString); | |||
| 10083 | continue; | |||
| 10084 | } | |||
| 10085 | ||||
| 10086 | if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) { | |||
| 10087 | nsAutoCString dataAsString; | |||
| 10088 | MOZ_ALWAYS_SUCCEEDS(ctext->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (ctext->GetData(dataAsString))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(ctext->GetData(dataAsString))" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10088); AnnotateMozCrashReason ("MOZ_CRASH(" "NS_SUCCEEDED(ctext->GetData(dataAsString))" ")"); do { MOZ_CrashSequence(__null, 10088); __attribute__(( nomerge)) ::abort(); } while (false); } while (false); } } while (false); | |||
| 10089 | ||||
| 10090 | IPCTransferableDataItem* item = | |||
| 10091 | aTransferableData->items().AppendElement(); | |||
| 10092 | item->flavor() = flavorStr; | |||
| 10093 | item->data() = AsIPCTransferableDataCString(dataAsString); | |||
| 10094 | continue; | |||
| 10095 | } | |||
| 10096 | ||||
| 10097 | if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) { | |||
| 10098 | // Images to be placed on the clipboard are imgIContainers. | |||
| 10099 | RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame( | |||
| 10100 | imgIContainer::FRAME_CURRENT, | |||
| 10101 | imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY); | |||
| 10102 | if (!surface) { | |||
| 10103 | continue; | |||
| 10104 | } | |||
| 10105 | RefPtr<mozilla::gfx::DataSourceSurface> dataSurface = | |||
| 10106 | surface->GetDataSurface(); | |||
| 10107 | if (!dataSurface) { | |||
| 10108 | continue; | |||
| 10109 | } | |||
| 10110 | ||||
| 10111 | auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface); | |||
| 10112 | if (!imageData) { | |||
| 10113 | continue; | |||
| 10114 | } | |||
| 10115 | ||||
| 10116 | IPCTransferableDataItem* item = | |||
| 10117 | aTransferableData->items().AppendElement(); | |||
| 10118 | item->flavor() = flavorStr; | |||
| 10119 | item->data() = IPCTransferableDataImageContainer(std::move(*imageData)); | |||
| 10120 | continue; | |||
| 10121 | } | |||
| 10122 | ||||
| 10123 | // Otherwise, handle this as a file. | |||
| 10124 | nsCOMPtr<BlobImpl> blobImpl; | |||
| 10125 | if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) { | |||
| 10126 | if (aParent) { | |||
| 10127 | bool isDir = false; | |||
| 10128 | if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory (&isDir))), 1))) && isDir) { | |||
| 10129 | nsAutoString path; | |||
| 10130 | if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(file ->GetPath(path))), 0))), "NS_FAILED(file->GetPath(path))" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10130)) { | |||
| 10131 | continue; | |||
| 10132 | } | |||
| 10133 | ||||
| 10134 | RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate(); | |||
| 10135 | fss->GrantAccessToContentProcess(aParent->ChildID(), path); | |||
| 10136 | } | |||
| 10137 | } | |||
| 10138 | ||||
| 10139 | blobImpl = new FileBlobImpl(file); | |||
| 10140 | ||||
| 10141 | IgnoredErrorResult rv; | |||
| 10142 | ||||
| 10143 | // Ensure that file data is cached no that the content process | |||
| 10144 | // has this data available to it when passed over: | |||
| 10145 | blobImpl->GetSize(rv); | |||
| 10146 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10146)) { | |||
| 10147 | continue; | |||
| 10148 | } | |||
| 10149 | ||||
| 10150 | blobImpl->GetLastModified(rv); | |||
| 10151 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10151)) { | |||
| 10152 | continue; | |||
| 10153 | } | |||
| 10154 | } else { | |||
| 10155 | if (aInSyncMessage) { | |||
| 10156 | // Can't do anything. | |||
| 10157 | // FIXME: This shouldn't be the case anymore! | |||
| 10158 | continue; | |||
| 10159 | } | |||
| 10160 | ||||
| 10161 | blobImpl = do_QueryInterface(data); | |||
| 10162 | } | |||
| 10163 | ||||
| 10164 | if (blobImpl) { | |||
| 10165 | // If we failed to create the blob actor, then this blob probably | |||
| 10166 | // can't get the file size for the underlying file, ignore it for | |||
| 10167 | // now. TODO pass this through anyway. | |||
| 10168 | IPCBlob ipcBlob; | |||
| 10169 | nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob); | |||
| 10170 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10170)) { | |||
| 10171 | continue; | |||
| 10172 | } | |||
| 10173 | ||||
| 10174 | IPCTransferableDataItem* item = | |||
| 10175 | aTransferableData->items().AppendElement(); | |||
| 10176 | item->flavor() = flavorStr; | |||
| 10177 | item->data() = IPCTransferableDataBlob(ipcBlob); | |||
| 10178 | } | |||
| 10179 | } | |||
| 10180 | } | |||
| 10181 | } | |||
| 10182 | ||||
| 10183 | void nsContentUtils::TransferableToIPCTransferable( | |||
| 10184 | nsITransferable* aTransferable, IPCTransferable* aIPCTransferable, | |||
| 10185 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
| 10186 | IPCTransferableData ipcTransferableData; | |||
| 10187 | TransferableToIPCTransferableData(aTransferable, &ipcTransferableData, | |||
| 10188 | aInSyncMessage, aParent); | |||
| 10189 | ||||
| 10190 | Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs; | |||
| 10191 | if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
| 10192 | aTransferable->GetCookieJarSettings()) { | |||
| 10193 | net::CookieJarSettingsArgs args; | |||
| 10194 | net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args); | |||
| 10195 | cookieJarSettingsArgs = Some(std::move(args)); | |||
| 10196 | } | |||
| 10197 | ||||
| 10198 | aIPCTransferable->data() = std::move(ipcTransferableData); | |||
| 10199 | aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData(); | |||
| 10200 | aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal(); | |||
| 10201 | aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs); | |||
| 10202 | aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType(); | |||
| 10203 | aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo(); | |||
| 10204 | } | |||
| 10205 | ||||
| 10206 | Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface, | |||
| 10207 | size_t* aLength, | |||
| 10208 | int32_t* aStride) { | |||
| 10209 | mozilla::gfx::DataSourceSurface::MappedSurface map; | |||
| 10210 | if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) { | |||
| 10211 | return Nothing(); | |||
| 10212 | } | |||
| 10213 | ||||
| 10214 | size_t bufLen = 0; | |||
| 10215 | size_t maxBufLen = 0; | |||
| 10216 | nsresult rv = nsContentUtils::CalculateBufferSizeForImage( | |||
| 10217 | map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen, | |||
| 10218 | &bufLen); | |||
| 10219 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 10220 | aSurface.Unmap(); | |||
| 10221 | return Nothing(); | |||
| 10222 | } | |||
| 10223 | ||||
| 10224 | BigBuffer surfaceData(maxBufLen); | |||
| 10225 | memcpy(surfaceData.Data(), map.mData, bufLen); | |||
| 10226 | memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen); | |||
| 10227 | ||||
| 10228 | *aLength = maxBufLen; | |||
| 10229 | *aStride = map.mStride; | |||
| 10230 | ||||
| 10231 | aSurface.Unmap(); | |||
| 10232 | return Some(std::move(surfaceData)); | |||
| 10233 | } | |||
| 10234 | ||||
| 10235 | Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) { | |||
| 10236 | size_t len = 0; | |||
| 10237 | int32_t stride = 0; | |||
| 10238 | auto mem = GetSurfaceData(aSurface, &len, &stride); | |||
| 10239 | if (!mem) { | |||
| 10240 | return Nothing(); | |||
| 10241 | } | |||
| 10242 | return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(), | |||
| 10243 | ImageIntSize::FromUnknownSize(aSurface.GetSize())}); | |||
| 10244 | } | |||
| 10245 | ||||
| 10246 | already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface( | |||
| 10247 | const IPCImage& aImage) { | |||
| 10248 | return BigBufferToDataSurface(aImage.data(), aImage.stride(), | |||
| 10249 | aImage.size().ToUnknownSize(), aImage.format()); | |||
| 10250 | } | |||
| 10251 | ||||
| 10252 | already_AddRefed<imgIContainer> nsContentUtils::IPCImageToImage( | |||
| 10253 | const IPCImage& aImage) { | |||
| 10254 | RefPtr<DataSourceSurface> surface = IPCImageToSurface(aImage); | |||
| 10255 | if (!surface) { | |||
| 10256 | return nullptr; | |||
| 10257 | } | |||
| 10258 | ||||
| 10259 | auto drawable = MakeRefPtr<gfxSurfaceDrawable>(surface, surface->GetSize()); | |||
| 10260 | nsCOMPtr<imgIContainer> imageContainer = | |||
| 10261 | image::ImageOps::CreateFromDrawable(drawable); | |||
| 10262 | return imageContainer.forget(); | |||
| 10263 | } | |||
| 10264 | ||||
| 10265 | Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) { | |||
| 10266 | Modifiers result = 0; | |||
| 10267 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) { | |||
| 10268 | result |= mozilla::MODIFIER_SHIFT; | |||
| 10269 | } | |||
| 10270 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) { | |||
| 10271 | result |= mozilla::MODIFIER_CONTROL; | |||
| 10272 | } | |||
| 10273 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) { | |||
| 10274 | result |= mozilla::MODIFIER_ALT; | |||
| 10275 | } | |||
| 10276 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) { | |||
| 10277 | result |= mozilla::MODIFIER_META; | |||
| 10278 | } | |||
| 10279 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) { | |||
| 10280 | result |= mozilla::MODIFIER_ALTGRAPH; | |||
| 10281 | } | |||
| 10282 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) { | |||
| 10283 | result |= mozilla::MODIFIER_CAPSLOCK; | |||
| 10284 | } | |||
| 10285 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) { | |||
| 10286 | result |= mozilla::MODIFIER_FN; | |||
| 10287 | } | |||
| 10288 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) { | |||
| 10289 | result |= mozilla::MODIFIER_FNLOCK; | |||
| 10290 | } | |||
| 10291 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) { | |||
| 10292 | result |= mozilla::MODIFIER_NUMLOCK; | |||
| 10293 | } | |||
| 10294 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) { | |||
| 10295 | result |= mozilla::MODIFIER_SCROLLLOCK; | |||
| 10296 | } | |||
| 10297 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) { | |||
| 10298 | result |= mozilla::MODIFIER_SYMBOL; | |||
| 10299 | } | |||
| 10300 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) { | |||
| 10301 | result |= mozilla::MODIFIER_SYMBOLLOCK; | |||
| 10302 | } | |||
| 10303 | return result; | |||
| 10304 | } | |||
| 10305 | ||||
| 10306 | nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) { | |||
| 10307 | if (!aPresShell) { | |||
| 10308 | return nullptr; | |||
| 10309 | } | |||
| 10310 | nsIFrame* frame = aPresShell->GetRootFrame(); | |||
| 10311 | if (!frame) { | |||
| 10312 | return nullptr; | |||
| 10313 | } | |||
| 10314 | return aOffset ? frame->GetNearestWidget(*aOffset) | |||
| 10315 | : frame->GetNearestWidget(); | |||
| 10316 | } | |||
| 10317 | ||||
| 10318 | int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) { | |||
| 10319 | switch (aButton) { | |||
| 10320 | case -1: | |||
| 10321 | return MouseButtonsFlag::eNoButtons; | |||
| 10322 | case MouseButton::ePrimary: | |||
| 10323 | return MouseButtonsFlag::ePrimaryFlag; | |||
| 10324 | case MouseButton::eMiddle: | |||
| 10325 | return MouseButtonsFlag::eMiddleFlag; | |||
| 10326 | case MouseButton::eSecondary: | |||
| 10327 | return MouseButtonsFlag::eSecondaryFlag; | |||
| 10328 | case 3: | |||
| 10329 | return MouseButtonsFlag::e4thFlag; | |||
| 10330 | case 4: | |||
| 10331 | return MouseButtonsFlag::e5thFlag; | |||
| 10332 | case MouseButton::eEraser: | |||
| 10333 | return MouseButtonsFlag::eEraserFlag; | |||
| 10334 | default: | |||
| 10335 | NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10335); MOZ_PretendNoReturn (); } while (0); | |||
| 10336 | return 0; | |||
| 10337 | } | |||
| 10338 | } | |||
| 10339 | ||||
| 10340 | LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint( | |||
| 10341 | const CSSPoint& aPoint, const nsPoint& aOffset, | |||
| 10342 | nsPresContext* aPresContext) { | |||
| 10343 | nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset; | |||
| 10344 | nsPoint visualRelative = | |||
| 10345 | ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell()); | |||
| 10346 | return LayoutDeviceIntPoint::FromAppUnitsRounded( | |||
| 10347 | visualRelative, aPresContext->AppUnitsPerDevPixel()); | |||
| 10348 | } | |||
| 10349 | ||||
| 10350 | namespace { | |||
| 10351 | ||||
| 10352 | class SynthesizedEventCallback final : public nsISynthesizedEventCallback { | |||
| 10353 | NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread ; public: | |||
| 10354 | ||||
| 10355 | public: | |||
| 10356 | explicit SynthesizedEventCallback(VoidFunction& aCallback) | |||
| 10357 | : mCallback(&aCallback) {} | |||
| 10358 | ||||
| 10359 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODvirtual nsresult OnCompleteDispatch() override { | |||
| 10360 | MOZ_ASSERT(mCallback, "How can we have a null mCallback here?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCallback)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mCallback))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCallback" " (" "How can we have a null mCallback here?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10360 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCallback" ") (" "How can we have a null mCallback here?" ")"); do { MOZ_CrashSequence(__null, 10360); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10361 | ||||
| 10362 | ErrorResult rv; | |||
| 10363 | MOZ_KnownLive(mCallback)(mCallback)->Call(rv); | |||
| 10364 | if (MOZ_UNLIKELY(rv.Failed())(__builtin_expect(!!(rv.Failed()), 0))) { | |||
| 10365 | return rv.StealNSResult(); | |||
| 10366 | } | |||
| 10367 | ||||
| 10368 | return NS_OK; | |||
| 10369 | } | |||
| 10370 | ||||
| 10371 | private: | |||
| 10372 | virtual ~SynthesizedEventCallback() = default; | |||
| 10373 | ||||
| 10374 | const RefPtr<VoidFunction> mCallback; | |||
| 10375 | }; | |||
| 10376 | ||||
| 10377 | NS_IMPL_ISUPPORTS(SynthesizedEventCallback, nsISynthesizedEventCallback)MozExternalRefCountType SynthesizedEventCallback::AddRef(void ) { static_assert(!std::is_destructible_v<SynthesizedEventCallback >, "Reference-counted class " "SynthesizedEventCallback" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 10377 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SynthesizedEventCallback" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SynthesizedEventCallback" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SynthesizedEventCallback\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 10377); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SynthesizedEventCallback" " not thread-safe" ); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ( "SynthesizedEventCallback"), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType SynthesizedEventCallback::Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 10377 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("SynthesizedEventCallback" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("SynthesizedEventCallback" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"SynthesizedEventCallback\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 10377); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("SynthesizedEventCallback" " not thread-safe" ); const char* const nametmp = "SynthesizedEventCallback"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)) ; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult SynthesizedEventCallback::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10377); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<SynthesizedEventCallback, nsISynthesizedEventCallback >, int32_t( reinterpret_cast<char*>(static_cast<nsISynthesizedEventCallback *>((SynthesizedEventCallback*)0x1000)) - reinterpret_cast< char*>((SynthesizedEventCallback*)0x1000))}, {&mozilla ::detail::kImplementedIID<SynthesizedEventCallback, nsISupports >, int32_t(reinterpret_cast<char*>(static_cast<nsISupports *>( static_cast<nsISynthesizedEventCallback*>((SynthesizedEventCallback *)0x1000))) - reinterpret_cast<char*>((SynthesizedEventCallback *)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table ) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } | |||
| 10378 | ||||
| 10379 | } // namespace | |||
| 10380 | ||||
| 10381 | Result<bool, nsresult> nsContentUtils::SynthesizeMouseEvent( | |||
| 10382 | mozilla::PresShell* aPresShell, nsIWidget* aWidget, const nsAString& aType, | |||
| 10383 | LayoutDeviceIntPoint& aRefPoint, | |||
| 10384 | const SynthesizeMouseEventData& aMouseEventData, | |||
| 10385 | const SynthesizeMouseEventOptions& aOptions, | |||
| 10386 | const Optional<OwningNonNull<VoidFunction>>& aCallback) { | |||
| 10387 | MOZ_ASSERT(aPresShell)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPresShell)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPresShell))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPresShell", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell" ")"); do { MOZ_CrashSequence(__null, 10387); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10388 | MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWidget)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")" ); do { MOZ_CrashSequence(__null, 10388); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10389 | AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeMouseEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10389( "nsContentUtils::SynthesizeMouseEvent" , nullptr, JS::ProfilingCategoryPair::OTHER); | |||
| 10390 | ||||
| 10391 | if (aCallback.WasPassed()) { | |||
| 10392 | if (!XRE_IsParentProcess()) { | |||
| 10393 | // TODO(edgar): There is currently no real use case for synthesizing a | |||
| 10394 | // mouse event with a callback from the content process. For now, throw an | |||
| 10395 | // error in this case. We can add support later if a valid use case | |||
| 10396 | // arises. | |||
| 10397 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10399) | |||
| 10398 | "nsContentUtils::SynthesizeMouseEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10399) | |||
| 10399 | "called in the content process with a callback")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10399); | |||
| 10400 | return Err(NS_ERROR_FAILURE); | |||
| 10401 | } | |||
| 10402 | ||||
| 10403 | if (!aOptions.mIsDOMEventSynthesized) { | |||
| 10404 | // TODO(edgar): There is currently no real use case for synthesizing a | |||
| 10405 | // mouse event with a callback that could be coalesced. For now, throw an | |||
| 10406 | // error. We can add support later if a need arises. | |||
| 10407 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10410) | |||
| 10408 | "nsContentUtils::SynthesizeMouseEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10410) | |||
| 10409 | "called in the parent process with isDOMEventSynthesized=false, due "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10410) | |||
| 10410 | "to the callback doesn't not support on coalesced events")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10410); | |||
| 10411 | return Err(NS_ERROR_FAILURE); | |||
| 10412 | } | |||
| 10413 | } | |||
| 10414 | ||||
| 10415 | EventMessage msg; | |||
| 10416 | Maybe<WidgetMouseEvent::ExitFrom> exitFrom; | |||
| 10417 | bool contextMenuKey = false; | |||
| 10418 | if (aType.EqualsLiteral("mousedown")) { | |||
| 10419 | msg = eMouseDown; | |||
| 10420 | } else if (aType.EqualsLiteral("mouseup")) { | |||
| 10421 | msg = eMouseUp; | |||
| 10422 | } else if (aType.EqualsLiteral("mousemove")) { | |||
| 10423 | msg = eMouseMove; | |||
| 10424 | } else if (aType.EqualsLiteral("mouseover")) { | |||
| 10425 | msg = eMouseEnterIntoWidget; | |||
| 10426 | } else if (aType.EqualsLiteral("mouseout")) { | |||
| 10427 | msg = eMouseExitFromWidget; | |||
| 10428 | exitFrom = Some(WidgetMouseEvent::ePlatformChild); | |||
| 10429 | } else if (aType.EqualsLiteral("mousecancel")) { | |||
| 10430 | msg = eMouseExitFromWidget; | |||
| 10431 | exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel | |||
| 10432 | : WidgetMouseEvent::ePuppet); | |||
| 10433 | } else if (aType.EqualsLiteral("mouselongtap")) { | |||
| 10434 | msg = eMouseLongTap; | |||
| 10435 | } else if (aType.EqualsLiteral("contextmenu")) { | |||
| 10436 | msg = eContextMenu; | |||
| 10437 | contextMenuKey = | |||
| 10438 | !aMouseEventData.mButton && | |||
| 10439 | aMouseEventData.mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH; | |||
| 10440 | } else if (aType.EqualsLiteral("MozMouseHittest")) { | |||
| 10441 | msg = eMouseHitTest; | |||
| 10442 | } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) { | |||
| 10443 | msg = eMouseExploreByTouch; | |||
| 10444 | } else { | |||
| 10445 | return Err(NS_ERROR_FAILURE); | |||
| 10446 | } | |||
| 10447 | ||||
| 10448 | Maybe<WidgetPointerEvent> pointerEvent; | |||
| 10449 | Maybe<WidgetMouseEvent> mouseEvent; | |||
| 10450 | if (IsPointerEventMessage(msg)) { | |||
| 10451 | if (MOZ_UNLIKELY(aOptions.mIsWidgetEventSynthesized)(__builtin_expect(!!(aOptions.mIsWidgetEventSynthesized), 0))) { | |||
| 10452 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10453); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event" ")"); do { MOZ_CrashSequence(__null, 10453); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 10453 | "The event shouldn't be dispatched as a synthesized event")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10453); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event" ")"); do { MOZ_CrashSequence(__null, 10453); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10454 | // `click`, `auxclick` nor `contextmenu` should not be dispatched as a | |||
| 10455 | // synthesized event. | |||
| 10456 | return Err(NS_ERROR_INVALID_ARG); | |||
| 10457 | } | |||
| 10458 | pointerEvent.emplace(true, msg, aWidget, | |||
| 10459 | contextMenuKey ? WidgetMouseEvent::eContextMenuKey | |||
| 10460 | : WidgetMouseEvent::eNormal); | |||
| 10461 | } else { | |||
| 10462 | mouseEvent.emplace(true, msg, aWidget, | |||
| 10463 | aOptions.mIsWidgetEventSynthesized | |||
| 10464 | ? WidgetMouseEvent::eSynthesized | |||
| 10465 | : WidgetMouseEvent::eReal, | |||
| 10466 | contextMenuKey ? WidgetMouseEvent::eContextMenuKey | |||
| 10467 | : WidgetMouseEvent::eNormal); | |||
| 10468 | } | |||
| 10469 | ||||
| 10470 | nsCOMPtr<nsISynthesizedEventCallback> callback; | |||
| 10471 | if (aCallback.WasPassed()) { | |||
| 10472 | callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value()); | |||
| 10473 | } | |||
| 10474 | ||||
| 10475 | mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback); | |||
| 10476 | ||||
| 10477 | WidgetMouseEvent& mouseOrPointerEvent = | |||
| 10478 | pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref(); | |||
| 10479 | mouseOrPointerEvent.pointerId = aMouseEventData.mIdentifier; | |||
| 10480 | mouseOrPointerEvent.mModifiers = | |||
| 10481 | GetWidgetModifiers(aMouseEventData.mModifiers); | |||
| 10482 | mouseOrPointerEvent.mButton = aMouseEventData.mButton; | |||
| 10483 | mouseOrPointerEvent.mButtons = | |||
| 10484 | aMouseEventData.mButtons.WasPassed() | |||
| 10485 | ? aMouseEventData.mButtons.Value() | |||
| 10486 | : (msg != eMouseDown | |||
| 10487 | ? 0 | |||
| 10488 | : GetButtonsFlagForButton(aMouseEventData.mButton)); | |||
| 10489 | // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure. | |||
| 10490 | mouseOrPointerEvent.mPressure = | |||
| 10491 | aMouseEventData.mPressure.WasPassed() | |||
| 10492 | ? aMouseEventData.mPressure.Value() | |||
| 10493 | : ((mouseOrPointerEvent.mButtons == 0) ? 0.0f : 0.5f); | |||
| 10494 | mouseOrPointerEvent.mInputSource = aMouseEventData.mInputSource; | |||
| 10495 | mouseOrPointerEvent.mClickCount = | |||
| 10496 | aMouseEventData.mClickCount.WasPassed() | |||
| 10497 | ? aMouseEventData.mClickCount.Value() | |||
| 10498 | : ((msg == eMouseDown || msg == eMouseUp) ? 1 : 0); | |||
| 10499 | mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = | |||
| 10500 | aOptions.mIsDOMEventSynthesized; | |||
| 10501 | mouseOrPointerEvent.mExitFrom = std::move(exitFrom); | |||
| 10502 | mouseOrPointerEvent.mCallbackId = notifier.SaveCallback(); | |||
| 10503 | ||||
| 10504 | nsPresContext* presContext = aPresShell->GetPresContext(); | |||
| 10505 | if (!presContext) { | |||
| 10506 | return Err(NS_ERROR_FAILURE); | |||
| 10507 | } | |||
| 10508 | ||||
| 10509 | mouseOrPointerEvent.mRefPoint = aRefPoint; | |||
| 10510 | mouseOrPointerEvent.mIgnoreRootScrollFrame = aOptions.mIgnoreRootScrollFrame; | |||
| 10511 | ||||
| 10512 | nsEventStatus status = nsEventStatus_eIgnore; | |||
| 10513 | if (aOptions.mToWindow) { | |||
| 10514 | nsresult rv = aPresShell->HandleEvent(aPresShell->GetRootFrame(), | |||
| 10515 | &mouseOrPointerEvent, false, &status); | |||
| 10516 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 10517 | return Err(rv); | |||
| 10518 | } | |||
| 10519 | } else if (aOptions.mIsAsyncEnabled || | |||
| 10520 | StaticPrefs::test_events_async_enabled()) { | |||
| 10521 | // The event is dispatched asynchronously via WebDriver when it is not | |||
| 10522 | // targeted directly at a window and async dispatching is requested. | |||
| 10523 | mouseOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests = | |||
| 10524 | aOptions.mIsDOMEventSynthesized; | |||
| 10525 | status = aWidget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus; | |||
| 10526 | } else { | |||
| 10527 | status = aWidget->DispatchEvent(&mouseOrPointerEvent); | |||
| 10528 | } | |||
| 10529 | ||||
| 10530 | // The callback ID may be cleared when the event also needs to be dispatched | |||
| 10531 | // to a content process. In such cases, the callback will be notified after | |||
| 10532 | // the event has been dispatched in the target content process. | |||
| 10533 | if (mouseOrPointerEvent.mCallbackId.isSome()) { | |||
| 10534 | mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback( | |||
| 10535 | mouseOrPointerEvent.mCallbackId.ref()); | |||
| 10536 | } | |||
| 10537 | ||||
| 10538 | return status == nsEventStatus_eConsumeNoDefault; | |||
| 10539 | } | |||
| 10540 | ||||
| 10541 | mozilla::Result<bool, nsresult> nsContentUtils::SynthesizeTouchEvent( | |||
| 10542 | nsPresContext* aPresContext, nsIWidget* aWidget, | |||
| 10543 | const nsPoint& aWidgetOffset, const nsAString& aType, | |||
| 10544 | const nsTArray<SynthesizeTouchEventData>& aTouches, | |||
| 10545 | const int32_t aModifiers, const SynthesizeTouchEventOptions& aOptions, | |||
| 10546 | const Optional<OwningNonNull<VoidFunction>>& aCallback) { | |||
| 10547 | MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPresContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPresContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext" ")"); do { MOZ_CrashSequence(__null, 10547); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10548 | MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWidget)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")" ); do { MOZ_CrashSequence(__null, 10548); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10549 | AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeTouchEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10549( "nsContentUtils::SynthesizeTouchEvent" , nullptr, JS::ProfilingCategoryPair::OTHER); | |||
| 10550 | ||||
| 10551 | if (aCallback.WasPassed()) { | |||
| 10552 | if (!XRE_IsParentProcess()) { | |||
| 10553 | // TODO(edgar): There is currently no real use case for synthesizing a | |||
| 10554 | // touch event with a callback from the content process. For now, throw an | |||
| 10555 | // error in this case. We can add support later if a valid use case | |||
| 10556 | // arises. | |||
| 10557 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10559) | |||
| 10558 | "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10559) | |||
| 10559 | "called in the content process with a callback")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10559); | |||
| 10560 | return Err(NS_ERROR_FAILURE); | |||
| 10561 | } | |||
| 10562 | ||||
| 10563 | if (!aOptions.mIsDOMEventSynthesized) { | |||
| 10564 | // TODO(edgar): There is currently no real use case for synthesizing a | |||
| 10565 | // touch event with a callback that could be coalesced. For now, throw an | |||
| 10566 | // error. We can add support later if a need arises. | |||
| 10567 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10570) | |||
| 10568 | "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10570) | |||
| 10569 | "called in the parent process with isDOMEventSynthesized=false, due "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10570) | |||
| 10570 | "to the callback doesn't not support on coalesced events")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process with isDOMEventSynthesized=false, due " "to the callback doesn't not support on coalesced events", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10570); | |||
| 10571 | return Err(NS_ERROR_FAILURE); | |||
| 10572 | } | |||
| 10573 | } | |||
| 10574 | ||||
| 10575 | if (XRE_IsParentProcess() && !aOptions.mIsAsyncEnabled && | |||
| 10576 | !StaticPrefs::test_events_async_enabled()) { | |||
| 10577 | // TODO(edgar): Currently, dispatching touch event from parent process | |||
| 10578 | // without going through APZ would cause content process crash on debug | |||
| 10579 | // build. | |||
| 10580 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process without going through APZ", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10582) | |||
| 10581 | "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process without going through APZ", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10582) | |||
| 10582 | "called in the parent process without going through APZ")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being " "called in the parent process without going through APZ", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10582); | |||
| 10583 | return Err(NS_ERROR_FAILURE); | |||
| 10584 | } | |||
| 10585 | ||||
| 10586 | EventMessage msg; | |||
| 10587 | if (aType.EqualsLiteral("touchstart")) { | |||
| 10588 | msg = eTouchStart; | |||
| 10589 | } else if (aType.EqualsLiteral("touchmove")) { | |||
| 10590 | msg = eTouchMove; | |||
| 10591 | } else if (aType.EqualsLiteral("touchend")) { | |||
| 10592 | msg = eTouchEnd; | |||
| 10593 | } else if (aType.EqualsLiteral("touchcancel")) { | |||
| 10594 | msg = eTouchCancel; | |||
| 10595 | } else { | |||
| 10596 | return Err(NS_ERROR_UNEXPECTED); | |||
| 10597 | } | |||
| 10598 | ||||
| 10599 | nsCOMPtr<nsISynthesizedEventCallback> callback; | |||
| 10600 | if (aCallback.WasPassed()) { | |||
| 10601 | callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value()); | |||
| 10602 | } | |||
| 10603 | ||||
| 10604 | mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback); | |||
| 10605 | ||||
| 10606 | WidgetTouchEvent event(true, msg, aWidget); | |||
| 10607 | event.mFlags.mIsSynthesizedForTests = aOptions.mIsDOMEventSynthesized; | |||
| 10608 | event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers); | |||
| 10609 | if (aOptions.mIsPen) { | |||
| 10610 | event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN; | |||
| 10611 | } | |||
| 10612 | event.mCallbackId = notifier.SaveCallback(); | |||
| 10613 | ||||
| 10614 | uint32_t count = aTouches.Length(); | |||
| 10615 | event.mTouches.SetCapacity(count); | |||
| 10616 | for (uint32_t i = 0; i < count; ++i) { | |||
| 10617 | if (aTouches[i].mAltitudeAngle.WasPassed() != | |||
| 10618 | aTouches[i].mAzimuthAngle.WasPassed()) { | |||
| 10619 | return Err(NS_ERROR_INVALID_ARG); | |||
| 10620 | } | |||
| 10621 | ||||
| 10622 | LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint( | |||
| 10623 | CSSPoint(aTouches[i].mOffsetX, aTouches[i].mOffsetY), aWidgetOffset, | |||
| 10624 | aPresContext); | |||
| 10625 | LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded( | |||
| 10626 | CSSPoint::ToAppUnits( | |||
| 10627 | CSSPoint(aTouches[i].mRadiiX, aTouches[i].mRadiiY)), | |||
| 10628 | aPresContext->AppUnitsPerDevPixel()); | |||
| 10629 | // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure. | |||
| 10630 | float pressure = aTouches[i].mPressure.WasPassed() | |||
| 10631 | ? aTouches[i].mPressure.Value() | |||
| 10632 | : (msg == eTouchEnd ? 0.0f : 0.5f); | |||
| 10633 | ||||
| 10634 | RefPtr<Touch> t = | |||
| 10635 | new Touch(CheckedInt<int32_t>(aTouches[i].mIdentifier).value(), pt, | |||
| 10636 | radius, aTouches[i].mRotationAngle, pressure); | |||
| 10637 | if (aTouches[i].mAltitudeAngle.WasPassed()) { | |||
| 10638 | MOZ_ASSERT(aTouches[i].mAzimuthAngle.WasPassed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTouches[i].mAzimuthAngle.WasPassed())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(aTouches[i].mAzimuthAngle.WasPassed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTouches[i].mAzimuthAngle.WasPassed()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10638); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aTouches[i].mAzimuthAngle.WasPassed()" ")" ); do { MOZ_CrashSequence(__null, 10638); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10639 | t->mAngle.emplace(aTouches[i].mAltitudeAngle.Value(), | |||
| 10640 | aTouches[i].mAzimuthAngle.Value()); | |||
| 10641 | } else { | |||
| 10642 | t->mTilt.emplace(aTouches[i].mTiltX, aTouches[i].mTiltY); | |||
| 10643 | } | |||
| 10644 | t->twist = aTouches[i].mTwist; | |||
| 10645 | event.mTouches.AppendElement(t); | |||
| 10646 | } | |||
| 10647 | ||||
| 10648 | nsEventStatus status = nsEventStatus_eIgnore; | |||
| 10649 | if (aOptions.mToWindow) { | |||
| 10650 | RefPtr<PresShell> presShell = aPresContext->PresShell(); | |||
| 10651 | MOZ_TRY(presShell->HandleEvent(presShell->GetRootFrame(), &event, false,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (presShell->HandleEvent(presShell->GetRootFrame(), & event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }) | |||
| 10652 | &status))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (presShell->HandleEvent(presShell->GetRootFrame(), & event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); | |||
| 10653 | } else if (aOptions.mIsAsyncEnabled || | |||
| 10654 | StaticPrefs::test_events_async_enabled()) { | |||
| 10655 | status = aWidget->DispatchInputEvent(&event).mContentStatus; | |||
| 10656 | } else { | |||
| 10657 | status = aWidget->DispatchEvent(&event); | |||
| 10658 | } | |||
| 10659 | ||||
| 10660 | // The callback ID may be cleared when the event also needs to be dispatched | |||
| 10661 | // to a content process. In such cases, the callback will be notified after | |||
| 10662 | // the event has been dispatched in the target content process. | |||
| 10663 | if (event.mCallbackId.isSome()) { | |||
| 10664 | mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback( | |||
| 10665 | event.mCallbackId.ref()); | |||
| 10666 | } | |||
| 10667 | ||||
| 10668 | return status == nsEventStatus_eConsumeNoDefault; | |||
| 10669 | } | |||
| 10670 | ||||
| 10671 | /* static */ | |||
| 10672 | void nsContentUtils::FirePageHideEventForFrameLoaderSwap( | |||
| 10673 | nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler, | |||
| 10674 | bool aOnlySystemGroup) { | |||
| 10675 | MOZ_DIAGNOSTIC_ASSERT(aItem)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aItem)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aItem))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("aItem", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10675); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem" ")"); do { MOZ_CrashSequence(__null, 10675); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 10676 | MOZ_DIAGNOSTIC_ASSERT(aChromeEventHandler)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChromeEventHandler)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aChromeEventHandler))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChromeEventHandler" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10676); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler" ")"); do { MOZ_CrashSequence(__null, 10676); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
| 10677 | ||||
| 10678 | if (RefPtr<Document> doc = aItem->GetDocument()) { | |||
| 10679 | doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup); | |||
| 10680 | } | |||
| 10681 | ||||
| 10682 | int32_t childCount = 0; | |||
| 10683 | aItem->GetInProcessChildCount(&childCount); | |||
| 10684 | AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids; | |||
| 10685 | kids.AppendElements(childCount); | |||
| 10686 | for (int32_t i = 0; i < childCount; ++i) { | |||
| 10687 | aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i])); | |||
| 10688 | } | |||
| 10689 | ||||
| 10690 | for (uint32_t i = 0; i < kids.Length(); ++i) { | |||
| 10691 | if (kids[i]) { | |||
| 10692 | FirePageHideEventForFrameLoaderSwap( | |||
| 10693 | MOZ_KnownLive(kids[i])(kids[i]), aChromeEventHandler, aOnlySystemGroup); | |||
| 10694 | } | |||
| 10695 | } | |||
| 10696 | } | |||
| 10697 | ||||
| 10698 | // The pageshow event is fired for a given document only if IsShowing() | |||
| 10699 | // returns the same thing as aFireIfShowing. This gives us a way to fire | |||
| 10700 | // pageshow only on documents that are still loading or only on documents that | |||
| 10701 | // are already loaded. | |||
| 10702 | /* static */ | |||
| 10703 | void nsContentUtils::FirePageShowEventForFrameLoaderSwap( | |||
| 10704 | nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler, | |||
| 10705 | bool aFireIfShowing, bool aOnlySystemGroup) { | |||
| 10706 | int32_t childCount = 0; | |||
| 10707 | aItem->GetInProcessChildCount(&childCount); | |||
| 10708 | AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids; | |||
| 10709 | kids.AppendElements(childCount); | |||
| 10710 | for (int32_t i = 0; i < childCount; ++i) { | |||
| 10711 | aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i])); | |||
| 10712 | } | |||
| 10713 | ||||
| 10714 | for (uint32_t i = 0; i < kids.Length(); ++i) { | |||
| 10715 | if (kids[i]) { | |||
| 10716 | FirePageShowEventForFrameLoaderSwap(MOZ_KnownLive(kids[i])(kids[i]), | |||
| 10717 | aChromeEventHandler, aFireIfShowing, | |||
| 10718 | aOnlySystemGroup); | |||
| 10719 | } | |||
| 10720 | } | |||
| 10721 | ||||
| 10722 | RefPtr<Document> doc = aItem->GetDocument(); | |||
| 10723 | if (doc && doc->IsShowing() == aFireIfShowing) { | |||
| 10724 | doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup); | |||
| 10725 | } | |||
| 10726 | } | |||
| 10727 | ||||
| 10728 | /* static */ | |||
| 10729 | already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) { | |||
| 10730 | if (aDoc) { | |||
| 10731 | if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) { | |||
| 10732 | return win->GetTopWindowRoot(); | |||
| 10733 | } | |||
| 10734 | } | |||
| 10735 | return nullptr; | |||
| 10736 | } | |||
| 10737 | ||||
| 10738 | /* static */ | |||
| 10739 | bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor, | |||
| 10740 | nsIURI* aDocURI) { | |||
| 10741 | if (aAnchor.IsEmpty()) { | |||
| 10742 | // anchor parameter not present or empty -> same document reference | |||
| 10743 | return true; | |||
| 10744 | } | |||
| 10745 | ||||
| 10746 | // the document URI might contain a fragment identifier ("#...') | |||
| 10747 | // we want to ignore that because it's invisible to the server | |||
| 10748 | // and just affects the local interpretation in the recipient | |||
| 10749 | nsCOMPtr<nsIURI> contextUri; | |||
| 10750 | nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri)); | |||
| 10751 | ||||
| 10752 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 10753 | // copying failed | |||
| 10754 | return false; | |||
| 10755 | } | |||
| 10756 | ||||
| 10757 | // resolve anchor against context | |||
| 10758 | nsCOMPtr<nsIURI> resolvedUri; | |||
| 10759 | rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri); | |||
| 10760 | ||||
| 10761 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 10762 | // resolving failed | |||
| 10763 | return false; | |||
| 10764 | } | |||
| 10765 | ||||
| 10766 | bool same; | |||
| 10767 | rv = contextUri->Equals(resolvedUri, &same); | |||
| 10768 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 10769 | // comparison failed | |||
| 10770 | return false; | |||
| 10771 | } | |||
| 10772 | ||||
| 10773 | return same; | |||
| 10774 | } | |||
| 10775 | ||||
| 10776 | /* static */ | |||
| 10777 | bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) { | |||
| 10778 | return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || | |||
| 10779 | aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD || | |||
| 10780 | aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || | |||
| 10781 | aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD || | |||
| 10782 | aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD || | |||
| 10783 | aType == nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD || | |||
| 10784 | aType == nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD || | |||
| 10785 | aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD); | |||
| 10786 | } | |||
| 10787 | ||||
| 10788 | // static | |||
| 10789 | bool nsContentUtils::IsImageType(ExtContentPolicy aType) { | |||
| 10790 | return aType == ExtContentPolicy::TYPE_IMAGE || | |||
| 10791 | aType == ExtContentPolicy::TYPE_IMAGESET; | |||
| 10792 | } | |||
| 10793 | ||||
| 10794 | // static | |||
| 10795 | ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel( | |||
| 10796 | nsIChannel* aChannel) { | |||
| 10797 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); | |||
| 10798 | if (!httpChannel) { | |||
| 10799 | return ReferrerPolicy::_empty; | |||
| 10800 | } | |||
| 10801 | ||||
| 10802 | nsresult rv; | |||
| 10803 | nsAutoCString headerValue; | |||
| 10804 | rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue); | |||
| 10805 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) { | |||
| 10806 | return ReferrerPolicy::_empty; | |||
| 10807 | } | |||
| 10808 | ||||
| 10809 | return ReferrerInfo::ReferrerPolicyFromHeaderString( | |||
| 10810 | NS_ConvertUTF8toUTF16(headerValue)); | |||
| 10811 | } | |||
| 10812 | ||||
| 10813 | // static | |||
| 10814 | bool nsContentUtils::HasRelNoReferrer(const Element& aElement) { | |||
| 10815 | // rel=noreferrer is only supported in <a>, <area>, and <form> | |||
| 10816 | if (!aElement.IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area, | |||
| 10817 | nsGkAtoms::form) && | |||
| 10818 | !aElement.IsSVGElement(nsGkAtoms::a)) { | |||
| 10819 | return false; | |||
| 10820 | } | |||
| 10821 | ||||
| 10822 | nsAutoString rel; | |||
| 10823 | aElement.GetAttr(nsGkAtoms::rel, rel); | |||
| 10824 | nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(rel); | |||
| 10825 | ||||
| 10826 | while (tok.hasMoreTokens()) { | |||
| 10827 | const nsAString& token = tok.nextToken(); | |||
| 10828 | if (token.LowerCaseEqualsLiteral("noreferrer")) { | |||
| 10829 | return true; | |||
| 10830 | } | |||
| 10831 | } | |||
| 10832 | ||||
| 10833 | return false; | |||
| 10834 | } | |||
| 10835 | ||||
| 10836 | // static | |||
| 10837 | bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) { | |||
| 10838 | nsLoadFlags loadFlags = 0; | |||
| 10839 | aChannel->GetLoadFlags(&loadFlags); | |||
| 10840 | if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) { | |||
| 10841 | return true; | |||
| 10842 | } | |||
| 10843 | ||||
| 10844 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
| 10845 | nsContentPolicyType type = loadInfo->InternalContentPolicyType(); | |||
| 10846 | return IsNonSubresourceInternalPolicyType(type); | |||
| 10847 | } | |||
| 10848 | ||||
| 10849 | // static | |||
| 10850 | bool nsContentUtils::IsNonSubresourceInternalPolicyType( | |||
| 10851 | nsContentPolicyType aType) { | |||
| 10852 | return aType == nsIContentPolicy::TYPE_DOCUMENT || | |||
| 10853 | aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || | |||
| 10854 | aType == nsIContentPolicy::TYPE_INTERNAL_FRAME || | |||
| 10855 | aType == nsIContentPolicy::TYPE_INTERNAL_WORKER || | |||
| 10856 | aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER; | |||
| 10857 | } | |||
| 10858 | ||||
| 10859 | // static public | |||
| 10860 | bool nsContentUtils::IsThirdPartyTrackingResourceWindow( | |||
| 10861 | nsPIDOMWindowInner* aWindow) { | |||
| 10862 | MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindow", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { MOZ_CrashSequence(__null, 10862); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10863 | ||||
| 10864 | Document* document = aWindow->GetExtantDoc(); | |||
| 10865 | if (!document) { | |||
| 10866 | return false; | |||
| 10867 | } | |||
| 10868 | ||||
| 10869 | nsCOMPtr<nsIClassifiedChannel> classifiedChannel = | |||
| 10870 | do_QueryInterface(document->GetChannel()); | |||
| 10871 | if (!classifiedChannel) { | |||
| 10872 | return false; | |||
| 10873 | } | |||
| 10874 | ||||
| 10875 | return classifiedChannel->IsThirdPartyTrackingResource(); | |||
| 10876 | } | |||
| 10877 | ||||
| 10878 | // static public | |||
| 10879 | bool nsContentUtils::IsFirstPartyTrackingResourceWindow( | |||
| 10880 | nsPIDOMWindowInner* aWindow) { | |||
| 10881 | MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindow", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 10881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { MOZ_CrashSequence(__null, 10881); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10882 | ||||
| 10883 | Document* document = aWindow->GetExtantDoc(); | |||
| 10884 | if (!document) { | |||
| 10885 | return false; | |||
| 10886 | } | |||
| 10887 | ||||
| 10888 | nsCOMPtr<nsIClassifiedChannel> classifiedChannel = | |||
| 10889 | do_QueryInterface(document->GetChannel()); | |||
| 10890 | if (!classifiedChannel) { | |||
| 10891 | return false; | |||
| 10892 | } | |||
| 10893 | ||||
| 10894 | uint32_t classificationFlags = | |||
| 10895 | classifiedChannel->GetFirstPartyClassificationFlags(); | |||
| 10896 | ||||
| 10897 | return mozilla::net::ChannelClassifierUtils::IsTrackingClassificationFlag( | |||
| 10898 | classificationFlags, NS_UsePrivateBrowsing(document->GetChannel())); | |||
| 10899 | } | |||
| 10900 | ||||
| 10901 | namespace { | |||
| 10902 | ||||
| 10903 | // We put StringBuilder in the anonymous namespace to prevent anything outside | |||
| 10904 | // this file from accidentally being linked against it. | |||
| 10905 | class BulkAppender { | |||
| 10906 | using size_type = typename nsAString::size_type; | |||
| 10907 | ||||
| 10908 | public: | |||
| 10909 | explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle) | |||
| 10910 | : mHandle(std::move(aHandle)), mPosition(0) {} | |||
| 10911 | ~BulkAppender() = default; | |||
| 10912 | ||||
| 10913 | template <int N> | |||
| 10914 | void AppendLiteral(const char16_t (&aStr)[N]) { | |||
| 10915 | size_t len = N - 1; | |||
| 10916 | MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPosition + len <= mHandle.Length())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mPosition + len <= mHandle.Length()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10916); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")" ); do { MOZ_CrashSequence(__null, 10916); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10917 | memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t)); | |||
| 10918 | mPosition += len; | |||
| 10919 | } | |||
| 10920 | ||||
| 10921 | void Append(Span<const char16_t> aStr) { | |||
| 10922 | size_t len = aStr.Length(); | |||
| 10923 | MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPosition + len <= mHandle.Length())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mPosition + len <= mHandle.Length()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10923); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")" ); do { MOZ_CrashSequence(__null, 10923); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10924 | // Both mHandle.Elements() and aStr.Elements() are guaranteed | |||
| 10925 | // to be non-null (by the string implementation and by Span, | |||
| 10926 | // respectively), so not checking the pointers for null before | |||
| 10927 | // memcpy does not lead to UB even if len was zero. | |||
| 10928 | memcpy(mHandle.Elements() + mPosition, aStr.Elements(), | |||
| 10929 | len * sizeof(char16_t)); | |||
| 10930 | mPosition += len; | |||
| 10931 | } | |||
| 10932 | ||||
| 10933 | void Append(Span<const char> aStr) { | |||
| 10934 | size_t len = aStr.Length(); | |||
| 10935 | MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPosition + len <= mHandle.Length())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mPosition + len <= mHandle.Length()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10935); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")" ); do { MOZ_CrashSequence(__null, 10935); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 10936 | ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition)); | |||
| 10937 | mPosition += len; | |||
| 10938 | } | |||
| 10939 | ||||
| 10940 | void Finish() { mHandle.Finish(mPosition, false); } | |||
| 10941 | ||||
| 10942 | private: | |||
| 10943 | BulkWriteHandle<char16_t> mHandle; | |||
| 10944 | size_type mPosition; | |||
| 10945 | }; | |||
| 10946 | ||||
| 10947 | class StringBuilderSIMD { | |||
| 10948 | public: | |||
| 10949 | static const bool SIMD = true; | |||
| 10950 | }; | |||
| 10951 | ||||
| 10952 | class StringBuilderALU { | |||
| 10953 | public: | |||
| 10954 | static const bool SIMD = false; | |||
| 10955 | }; | |||
| 10956 | ||||
| 10957 | class StringBuilder { | |||
| 10958 | private: | |||
| 10959 | class Unit { | |||
| 10960 | public: | |||
| 10961 | Unit() : mAtom(nullptr) { MOZ_COUNT_CTOR(StringBuilder::Unit)do { static_assert(std::is_class_v<StringBuilder::Unit> , "Token '" "StringBuilder::Unit" "' is not a class type."); static_assert (!std::is_base_of_v<nsISupports, StringBuilder::Unit>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder::Unit" , sizeof(*this)); } while (0); } | |||
| 10962 | ~Unit() { | |||
| 10963 | if (mType == Type::String || mType == Type::StringWithEncode) { | |||
| 10964 | mString.~nsString(); | |||
| 10965 | } | |||
| 10966 | MOZ_COUNT_DTOR(StringBuilder::Unit)do { static_assert(std::is_class_v<StringBuilder::Unit> , "Token '" "StringBuilder::Unit" "' is not a class type."); static_assert (!std::is_base_of_v<nsISupports, StringBuilder::Unit>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder::Unit" , sizeof(*this)); } while (0); | |||
| 10967 | } | |||
| 10968 | ||||
| 10969 | enum class Type : uint8_t { | |||
| 10970 | Unknown, | |||
| 10971 | Atom, | |||
| 10972 | String, | |||
| 10973 | StringWithEncode, | |||
| 10974 | Literal, | |||
| 10975 | TextFragment, | |||
| 10976 | TextFragmentWithEncode, | |||
| 10977 | }; | |||
| 10978 | ||||
| 10979 | struct LiteralSpan { | |||
| 10980 | const char16_t* mData; | |||
| 10981 | uint32_t mLength; | |||
| 10982 | ||||
| 10983 | Span<const char16_t> AsSpan() { return Span(mData, mLength); } | |||
| 10984 | }; | |||
| 10985 | ||||
| 10986 | union { | |||
| 10987 | nsAtom* mAtom; | |||
| 10988 | LiteralSpan mLiteral; | |||
| 10989 | nsString mString; | |||
| 10990 | const CharacterDataBuffer* mCharacterDataBuffer; | |||
| 10991 | }; | |||
| 10992 | Type mType = Type::Unknown; | |||
| 10993 | }; | |||
| 10994 | ||||
| 10995 | static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*), | |||
| 10996 | "Unit should remain small"); | |||
| 10997 | ||||
| 10998 | public: | |||
| 10999 | // Try to keep the size of StringBuilder close to a jemalloc bucket size | |||
| 11000 | // (the 16kb one in this case). | |||
| 11001 | static constexpr uint32_t TARGET_SIZE = 16 * 1024; | |||
| 11002 | ||||
| 11003 | // The number of units we need to remove from the inline buffer so that the | |||
| 11004 | // rest of the builder members fit. A more precise approach would be to | |||
| 11005 | // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) / | |||
| 11006 | // sizeof(Unit) or so, but this is simpler. | |||
| 11007 | static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2; | |||
| 11008 | ||||
| 11009 | static constexpr uint32_t STRING_BUFFER_UNITS = | |||
| 11010 | TARGET_SIZE / sizeof(Unit) - PADDING_UNITS; | |||
| 11011 | ||||
| 11012 | StringBuilder() : mLast(this), mLength(0) { MOZ_COUNT_CTOR(StringBuilder)do { static_assert(std::is_class_v<StringBuilder>, "Token '" "StringBuilder" "' is not a class type."); static_assert(!std ::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); } | |||
| 11013 | ||||
| 11014 | MOZ_COUNTED_DTOR(StringBuilder)~StringBuilder() { do { static_assert(std::is_class_v<StringBuilder >, "Token '" "StringBuilder" "' is not a class type."); static_assert (!std::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); } | |||
| 11015 | ||||
| 11016 | void Append(nsAtom* aAtom) { | |||
| 11017 | Unit* u = AddUnit(); | |||
| 11018 | u->mAtom = aAtom; | |||
| 11019 | u->mType = Unit::Type::Atom; | |||
| 11020 | uint32_t len = aAtom->GetLength(); | |||
| 11021 | mLength += len; | |||
| 11022 | } | |||
| 11023 | ||||
| 11024 | template <int N> | |||
| 11025 | void Append(const char16_t (&aLiteral)[N]) { | |||
| 11026 | constexpr uint32_t len = N - 1; | |||
| 11027 | Unit* u = AddUnit(); | |||
| 11028 | u->mLiteral = {aLiteral, len}; | |||
| 11029 | u->mType = Unit::Type::Literal; | |||
| 11030 | mLength += len; | |||
| 11031 | } | |||
| 11032 | ||||
| 11033 | void Append(nsString&& aString) { | |||
| 11034 | Unit* u = AddUnit(); | |||
| 11035 | uint32_t len = aString.Length(); | |||
| 11036 | new (&u->mString) nsString(std::move(aString)); | |||
| 11037 | u->mType = Unit::Type::String; | |||
| 11038 | mLength += len; | |||
| 11039 | } | |||
| 11040 | ||||
| 11041 | // aLen can be !isValid(), which will get propagated into mLength. | |||
| 11042 | void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) { | |||
| 11043 | Unit* u = AddUnit(); | |||
| 11044 | new (&u->mString) nsString(std::move(aString)); | |||
| 11045 | u->mType = Unit::Type::StringWithEncode; | |||
| 11046 | mLength += aLen; | |||
| 11047 | } | |||
| 11048 | ||||
| 11049 | void Append(const CharacterDataBuffer* aCharacterDataBuffer) { | |||
| 11050 | Unit* u = AddUnit(); | |||
| 11051 | u->mCharacterDataBuffer = aCharacterDataBuffer; | |||
| 11052 | u->mType = Unit::Type::TextFragment; | |||
| 11053 | uint32_t len = aCharacterDataBuffer->GetLength(); | |||
| 11054 | mLength += len; | |||
| 11055 | } | |||
| 11056 | ||||
| 11057 | // aLen can be !isValid(), which will get propagated into mLength. | |||
| 11058 | void AppendWithEncode(const CharacterDataBuffer* aCharacterDataBuffer, | |||
| 11059 | CheckedInt<uint32_t> aLen) { | |||
| 11060 | Unit* u = AddUnit(); | |||
| 11061 | u->mCharacterDataBuffer = aCharacterDataBuffer; | |||
| 11062 | u->mType = Unit::Type::TextFragmentWithEncode; | |||
| 11063 | mLength += aLen; | |||
| 11064 | } | |||
| 11065 | ||||
| 11066 | bool ToString(nsAString& aOut) { | |||
| 11067 | if (!mLength.isValid()) { | |||
| 11068 | return false; | |||
| 11069 | } | |||
| 11070 | auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true); | |||
| 11071 | if (appenderOrErr.isErr()) { | |||
| 11072 | return false; | |||
| 11073 | } | |||
| 11074 | ||||
| 11075 | BulkAppender appender{appenderOrErr.unwrap()}; | |||
| 11076 | ||||
| 11077 | // Experiment with moving this higher up the call stack | |||
| 11078 | // after we have experience from | |||
| 11079 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1997255 | |||
| 11080 | // on the parser side. | |||
| 11081 | bool simd = mozilla::htmlaccel::htmlaccelEnabled(); | |||
| 11082 | ||||
| 11083 | for (StringBuilder* current = this; current; | |||
| 11084 | current = current->mNext.get()) { | |||
| 11085 | uint32_t len = current->mUnits.Length(); | |||
| 11086 | for (uint32_t i = 0; i < len; ++i) { | |||
| 11087 | Unit& u = current->mUnits[i]; | |||
| 11088 | switch (u.mType) { | |||
| 11089 | case Unit::Type::Atom: | |||
| 11090 | appender.Append(*(u.mAtom)); | |||
| 11091 | break; | |||
| 11092 | case Unit::Type::String: | |||
| 11093 | appender.Append(u.mString); | |||
| 11094 | break; | |||
| 11095 | case Unit::Type::StringWithEncode: | |||
| 11096 | if (simd) { | |||
| 11097 | EncodeAttrString<StringBuilderSIMD>(u.mString, appender); | |||
| 11098 | } else { | |||
| 11099 | EncodeAttrString<StringBuilderALU>(u.mString, appender); | |||
| 11100 | } | |||
| 11101 | break; | |||
| 11102 | case Unit::Type::Literal: | |||
| 11103 | appender.Append(u.mLiteral.AsSpan()); | |||
| 11104 | break; | |||
| 11105 | case Unit::Type::TextFragment: | |||
| 11106 | if (u.mCharacterDataBuffer->Is2b()) { | |||
| 11107 | appender.Append(Span(u.mCharacterDataBuffer->Get2b(), | |||
| 11108 | u.mCharacterDataBuffer->GetLength())); | |||
| 11109 | } else { | |||
| 11110 | appender.Append(Span(u.mCharacterDataBuffer->Get1b(), | |||
| 11111 | u.mCharacterDataBuffer->GetLength())); | |||
| 11112 | } | |||
| 11113 | break; | |||
| 11114 | case Unit::Type::TextFragmentWithEncode: | |||
| 11115 | if (u.mCharacterDataBuffer->Is2b()) { | |||
| 11116 | if (simd) { | |||
| 11117 | EncodeTextFragment<StringBuilderSIMD>( | |||
| 11118 | Span(u.mCharacterDataBuffer->Get2b(), | |||
| 11119 | u.mCharacterDataBuffer->GetLength()), | |||
| 11120 | appender); | |||
| 11121 | ||||
| 11122 | } else { | |||
| 11123 | EncodeTextFragment<StringBuilderALU>( | |||
| 11124 | Span(u.mCharacterDataBuffer->Get2b(), | |||
| 11125 | u.mCharacterDataBuffer->GetLength()), | |||
| 11126 | appender); | |||
| 11127 | } | |||
| 11128 | } else { | |||
| 11129 | if (simd) { | |||
| 11130 | EncodeTextFragment<StringBuilderSIMD>( | |||
| 11131 | Span(u.mCharacterDataBuffer->Get1b(), | |||
| 11132 | u.mCharacterDataBuffer->GetLength()), | |||
| 11133 | appender); | |||
| 11134 | ||||
| 11135 | } else { | |||
| 11136 | EncodeTextFragment<StringBuilderALU>( | |||
| 11137 | Span(u.mCharacterDataBuffer->Get1b(), | |||
| 11138 | u.mCharacterDataBuffer->GetLength()), | |||
| 11139 | appender); | |||
| 11140 | } | |||
| 11141 | } | |||
| 11142 | break; | |||
| 11143 | default: | |||
| 11144 | MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11144); AnnotateMozCrashReason ("MOZ_CRASH(" "Unknown unit type?" ")"); do { MOZ_CrashSequence (__null, 11144); __attribute__((nomerge)) ::abort(); } while ( false); } while (false); | |||
| 11145 | } | |||
| 11146 | } | |||
| 11147 | } | |||
| 11148 | appender.Finish(); | |||
| 11149 | return true; | |||
| 11150 | } | |||
| 11151 | ||||
| 11152 | private: | |||
| 11153 | Unit* AddUnit() { | |||
| 11154 | if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) { | |||
| 11155 | new StringBuilder(this); | |||
| 11156 | } | |||
| 11157 | return mLast->mUnits.AppendElement(); | |||
| 11158 | } | |||
| 11159 | ||||
| 11160 | explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) { | |||
| 11161 | MOZ_COUNT_CTOR(StringBuilder)do { static_assert(std::is_class_v<StringBuilder>, "Token '" "StringBuilder" "' is not a class type."); static_assert(!std ::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); | |||
| 11162 | aFirst->mLast->mNext = WrapUnique(this); | |||
| 11163 | aFirst->mLast = this; | |||
| 11164 | } | |||
| 11165 | ||||
| 11166 | template <class S> | |||
| 11167 | void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) { | |||
| 11168 | size_t flushedUntil = 0; | |||
| 11169 | size_t currentPosition = 0; | |||
| 11170 | const char16_t* ptr = aStr.Elements(); | |||
| 11171 | const char16_t* end = ptr + aStr.Length(); | |||
| 11172 | ||||
| 11173 | // continue by label (committee proposal P3568) isn't in C++, yet, so | |||
| 11174 | // goto is used for what's logically continuing an outer loop. | |||
| 11175 | // | |||
| 11176 | // The purpose of two loop levels is to efficiently stay in the inner | |||
| 11177 | // loop when there isn't a full SIMD stride left. | |||
| 11178 | // | |||
| 11179 | // Strange indent thanks to clang-format. | |||
| 11180 | outer: | |||
| 11181 | // Check for having at least a SIMD stride of data to avoid useless | |||
| 11182 | // non-inline function calls when there isn't a full stride left. | |||
| 11183 | // This should become unnecessary if it turns out to be feasible | |||
| 11184 | // to inline the call without triggering | |||
| 11185 | // https://github.com/llvm/llvm-project/issues/160886 . | |||
| 11186 | if (S::SIMD && (end - ptr >= 16)) { | |||
| 11187 | // Need to check ifdef inside here in order to make even non-opt | |||
| 11188 | // build consider `S::SIMD` used. | |||
| 11189 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 11190 | size_t skipped = | |||
| 11191 | mozilla::htmlaccel::SkipNonEscapedInAttributeValue(ptr, end); | |||
| 11192 | ptr += skipped; | |||
| 11193 | currentPosition += skipped; | |||
| 11194 | #endif | |||
| 11195 | } | |||
| 11196 | while (ptr != end) { | |||
| 11197 | char16_t c = *ptr; | |||
| 11198 | ptr++; | |||
| 11199 | switch (c) { | |||
| 11200 | case '"': | |||
| 11201 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11202 | aAppender.AppendLiteral(u"""); | |||
| 11203 | currentPosition++; | |||
| 11204 | flushedUntil = currentPosition; | |||
| 11205 | goto outer; | |||
| 11206 | case '&': | |||
| 11207 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11208 | aAppender.AppendLiteral(u"&"); | |||
| 11209 | currentPosition++; | |||
| 11210 | flushedUntil = currentPosition; | |||
| 11211 | goto outer; | |||
| 11212 | case 0x00A0: | |||
| 11213 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11214 | aAppender.AppendLiteral(u" "); | |||
| 11215 | currentPosition++; | |||
| 11216 | flushedUntil = currentPosition; | |||
| 11217 | goto outer; | |||
| 11218 | case '<': | |||
| 11219 | if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) { | |||
| 11220 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11221 | aAppender.AppendLiteral(u"<"); | |||
| 11222 | currentPosition++; | |||
| 11223 | flushedUntil = currentPosition; | |||
| 11224 | } else { | |||
| 11225 | currentPosition++; | |||
| 11226 | } | |||
| 11227 | goto outer; | |||
| 11228 | case '>': | |||
| 11229 | if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) { | |||
| 11230 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11231 | aAppender.AppendLiteral(u">"); | |||
| 11232 | currentPosition++; | |||
| 11233 | flushedUntil = currentPosition; | |||
| 11234 | } else { | |||
| 11235 | currentPosition++; | |||
| 11236 | } | |||
| 11237 | goto outer; | |||
| 11238 | default: | |||
| 11239 | currentPosition++; | |||
| 11240 | continue; | |||
| 11241 | } | |||
| 11242 | } | |||
| 11243 | // Logically the outer loop ends here. | |||
| 11244 | if (currentPosition > flushedUntil) { | |||
| 11245 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11246 | } | |||
| 11247 | } | |||
| 11248 | ||||
| 11249 | template <class S, class T> | |||
| 11250 | void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) { | |||
| 11251 | size_t flushedUntil = 0; | |||
| 11252 | size_t currentPosition = 0; | |||
| 11253 | const T* ptr = aStr.Elements(); | |||
| 11254 | const T* end = ptr + aStr.Length(); | |||
| 11255 | ||||
| 11256 | // continue by label (committee proposal P3568) isn't in C++, yet, so | |||
| 11257 | // goto is used for what's logically continuing an outer loop. | |||
| 11258 | // | |||
| 11259 | // The purpose of two loop levels is to efficiently stay in the inner | |||
| 11260 | // loop when there isn't a full SIMD stride left. | |||
| 11261 | // | |||
| 11262 | // Strange indent thanks to clang-format. | |||
| 11263 | outer: | |||
| 11264 | // Check for having at least a SIMD stride of data to avoid useless | |||
| 11265 | // non-inline function calls when there isn't a full stride left. | |||
| 11266 | // This should become unnecessary if it turns out to be feasible | |||
| 11267 | // to inline the call without triggering | |||
| 11268 | // https://github.com/llvm/llvm-project/issues/160886 . | |||
| 11269 | if (S::SIMD && (end - ptr >= 16)) { | |||
| 11270 | // Need to check ifdef inside here in order to make even non-opt | |||
| 11271 | // build consider `S::SIMD` used. | |||
| 11272 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 11273 | size_t skipped = mozilla::htmlaccel::SkipNonEscapedInTextNode(ptr, end); | |||
| 11274 | ptr += skipped; | |||
| 11275 | currentPosition += skipped; | |||
| 11276 | #endif | |||
| 11277 | } | |||
| 11278 | while (ptr != end) { | |||
| 11279 | T c = *ptr; | |||
| 11280 | ++ptr; | |||
| 11281 | switch (c) { | |||
| 11282 | case '<': | |||
| 11283 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11284 | aAppender.AppendLiteral(u"<"); | |||
| 11285 | currentPosition++; | |||
| 11286 | flushedUntil = currentPosition; | |||
| 11287 | goto outer; | |||
| 11288 | case '>': | |||
| 11289 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11290 | aAppender.AppendLiteral(u">"); | |||
| 11291 | currentPosition++; | |||
| 11292 | flushedUntil = currentPosition; | |||
| 11293 | goto outer; | |||
| 11294 | case '&': | |||
| 11295 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11296 | aAppender.AppendLiteral(u"&"); | |||
| 11297 | currentPosition++; | |||
| 11298 | flushedUntil = currentPosition; | |||
| 11299 | goto outer; | |||
| 11300 | case T(0xA0): | |||
| 11301 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11302 | aAppender.AppendLiteral(u" "); | |||
| 11303 | currentPosition++; | |||
| 11304 | flushedUntil = currentPosition; | |||
| 11305 | goto outer; | |||
| 11306 | default: | |||
| 11307 | currentPosition++; | |||
| 11308 | continue; | |||
| 11309 | } | |||
| 11310 | } | |||
| 11311 | // Logically the outer loop ends here. | |||
| 11312 | if (currentPosition > flushedUntil) { | |||
| 11313 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
| 11314 | } | |||
| 11315 | } | |||
| 11316 | ||||
| 11317 | AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits; | |||
| 11318 | UniquePtr<StringBuilder> mNext; | |||
| 11319 | StringBuilder* mLast; | |||
| 11320 | // mLength is used only in the first StringBuilder object in the linked | |||
| 11321 | // list. | |||
| 11322 | CheckedInt<uint32_t> mLength; | |||
| 11323 | }; | |||
| 11324 | ||||
| 11325 | static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE, | |||
| 11326 | "StringBuilder should fit in the target bucket"); | |||
| 11327 | ||||
| 11328 | } // namespace | |||
| 11329 | ||||
| 11330 | static void AppendEncodedCharacters(const CharacterDataBuffer* aText, | |||
| 11331 | StringBuilder& aBuilder) { | |||
| 11332 | uint32_t numEncodedChars = 0; | |||
| 11333 | uint32_t len = aText->GetLength(); | |||
| 11334 | if (aText->Is2b()) { | |||
| 11335 | const char16_t* data = aText->Get2b(); | |||
| 11336 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 11337 | if (mozilla::htmlaccel::htmlaccelEnabled()) { | |||
| 11338 | numEncodedChars = | |||
| 11339 | mozilla::htmlaccel::CountEscapedInTextNode(data, data + len); | |||
| 11340 | } else | |||
| 11341 | #endif | |||
| 11342 | { | |||
| 11343 | for (uint32_t i = 0; i < len; ++i) { | |||
| 11344 | const char16_t c = data[i]; | |||
| 11345 | switch (c) { | |||
| 11346 | case '<': | |||
| 11347 | case '>': | |||
| 11348 | case '&': | |||
| 11349 | case 0x00A0: | |||
| 11350 | ++numEncodedChars; | |||
| 11351 | break; | |||
| 11352 | default: | |||
| 11353 | break; | |||
| 11354 | } | |||
| 11355 | } | |||
| 11356 | } | |||
| 11357 | } else { | |||
| 11358 | const char* data = aText->Get1b(); | |||
| 11359 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 11360 | if (mozilla::htmlaccel::htmlaccelEnabled()) { | |||
| 11361 | numEncodedChars = | |||
| 11362 | mozilla::htmlaccel::CountEscapedInTextNode(data, data + len); | |||
| 11363 | } else | |||
| 11364 | #endif | |||
| 11365 | { | |||
| 11366 | for (uint32_t i = 0; i < len; ++i) { | |||
| 11367 | const unsigned char c = data[i]; | |||
| 11368 | switch (c) { | |||
| 11369 | case '<': | |||
| 11370 | case '>': | |||
| 11371 | case '&': | |||
| 11372 | case 0x00A0: | |||
| 11373 | ++numEncodedChars; | |||
| 11374 | break; | |||
| 11375 | default: | |||
| 11376 | break; | |||
| 11377 | } | |||
| 11378 | } | |||
| 11379 | } | |||
| 11380 | } | |||
| 11381 | ||||
| 11382 | if (numEncodedChars) { | |||
| 11383 | // For simplicity, conservatively estimate the size of the string after | |||
| 11384 | // encoding. This will result in reserving more memory than we actually | |||
| 11385 | // need, but that should be fine unless the string has an enormous number | |||
| 11386 | // of eg < in it. We subtract 1 for the null terminator, then 1 more for | |||
| 11387 | // the existing character that will be replaced. | |||
| 11388 | constexpr uint32_t maxCharExtraSpace = | |||
| 11389 | std::max({std::size("<"), std::size(">"), std::size("&"), | |||
| 11390 | std::size(" ")}) - | |||
| 11391 | 2; | |||
| 11392 | static_assert(maxCharExtraSpace < 100, "Possible underflow"); | |||
| 11393 | CheckedInt<uint32_t> maxExtraSpace = | |||
| 11394 | CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace; | |||
| 11395 | aBuilder.AppendWithEncode(aText, maxExtraSpace + len); | |||
| 11396 | } else { | |||
| 11397 | aBuilder.Append(aText); | |||
| 11398 | } | |||
| 11399 | } | |||
| 11400 | ||||
| 11401 | static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding( | |||
| 11402 | const nsAString& aValue) { | |||
| 11403 | const char16_t* c = aValue.BeginReading(); | |||
| 11404 | const char16_t* end = aValue.EndReading(); | |||
| 11405 | ||||
| 11406 | uint32_t numEncodedChars = 0; | |||
| 11407 | #ifdef MOZ_MAY_HAVE_HTMLACCEL1 | |||
| 11408 | if (mozilla::htmlaccel::htmlaccelEnabled()) { | |||
| 11409 | numEncodedChars = mozilla::htmlaccel::CountEscapedInAttributeValue(c, end); | |||
| 11410 | } else | |||
| 11411 | #endif | |||
| 11412 | { | |||
| 11413 | while (c < end) { | |||
| 11414 | switch (*c) { | |||
| 11415 | case '"': | |||
| 11416 | case '&': | |||
| 11417 | case 0x00A0: // NO-BREAK SPACE | |||
| 11418 | case '<': | |||
| 11419 | case '>': | |||
| 11420 | ++numEncodedChars; | |||
| 11421 | break; | |||
| 11422 | default: | |||
| 11423 | break; | |||
| 11424 | } | |||
| 11425 | ++c; | |||
| 11426 | } | |||
| 11427 | } | |||
| 11428 | ||||
| 11429 | if (!numEncodedChars) { | |||
| 11430 | return 0; | |||
| 11431 | } | |||
| 11432 | ||||
| 11433 | // For simplicity, conservatively estimate the size of the string after | |||
| 11434 | // encoding. This will result in reserving more memory than we actually | |||
| 11435 | // need, but that should be fine unless the string has an enormous number of | |||
| 11436 | // & in it. We subtract 1 for the null terminator, then 1 more for the | |||
| 11437 | // existing character that will be replaced. | |||
| 11438 | constexpr uint32_t maxCharExtraSpace = | |||
| 11439 | std::max({std::size("""), std::size("&"), std::size(" "), | |||
| 11440 | std::size("<"), std::size(">")}) - | |||
| 11441 | 2; | |||
| 11442 | static_assert(maxCharExtraSpace < 100, "Possible underflow"); | |||
| 11443 | return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace; | |||
| 11444 | } | |||
| 11445 | ||||
| 11446 | static void AppendEncodedAtomAttributeValue(nsAtom* aAtom, | |||
| 11447 | StringBuilder& aBuilder) { | |||
| 11448 | nsDependentAtomString atomStr(aAtom); | |||
| 11449 | auto space = ExtraSpaceNeededForAttrEncoding(atomStr); | |||
| 11450 | if (space.isValid() && !space.value()) { | |||
| 11451 | aBuilder.Append(aAtom); | |||
| 11452 | } else { | |||
| 11453 | aBuilder.AppendWithAttrEncode(nsString(atomStr), space + atomStr.Length()); | |||
| 11454 | } | |||
| 11455 | } | |||
| 11456 | ||||
| 11457 | static void AppendEncodedAttributeValue(const nsAttrValue& aValue, | |||
| 11458 | StringBuilder& aBuilder) { | |||
| 11459 | if (nsAtom* atom = aValue.GetStoredAtom()) { | |||
| 11460 | AppendEncodedAtomAttributeValue(atom, aBuilder); | |||
| 11461 | return; | |||
| 11462 | } | |||
| 11463 | ||||
| 11464 | // NOTE(emilio): In most cases this will just be a reference to the stored | |||
| 11465 | // nsStringBuffer. | |||
| 11466 | nsString str; | |||
| 11467 | aValue.ToString(str); | |||
| 11468 | auto space = ExtraSpaceNeededForAttrEncoding(str); | |||
| 11469 | if (!space.isValid() || space.value()) { | |||
| 11470 | aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length()); | |||
| 11471 | } else { | |||
| 11472 | aBuilder.Append(std::move(str)); | |||
| 11473 | } | |||
| 11474 | } | |||
| 11475 | ||||
| 11476 | static void StartElement(Element* aElement, StringBuilder& aBuilder) { | |||
| 11477 | nsAtom* localName = aElement->NodeInfo()->NameAtom(); | |||
| 11478 | const int32_t tagNS = aElement->GetNameSpaceID(); | |||
| 11479 | ||||
| 11480 | aBuilder.Append(u"<"); | |||
| 11481 | if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 || | |||
| 11482 | tagNS == kNameSpaceID_MathML6) { | |||
| 11483 | aBuilder.Append(localName); | |||
| 11484 | } else { | |||
| 11485 | aBuilder.Append(nsString(aElement->NodeName())); | |||
| 11486 | } | |||
| 11487 | ||||
| 11488 | if (CustomElementData* ceData = aElement->GetCustomElementData()) { | |||
| 11489 | nsAtom* isAttr = ceData->GetIs(aElement); | |||
| 11490 | if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) { | |||
| 11491 | aBuilder.Append(uR"( is=")"); | |||
| 11492 | AppendEncodedAtomAttributeValue(isAttr, aBuilder); | |||
| 11493 | aBuilder.Append(uR"(")"); | |||
| 11494 | } | |||
| 11495 | } | |||
| 11496 | ||||
| 11497 | uint32_t i = 0; | |||
| 11498 | while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) { | |||
| 11499 | const nsAttrName* name = info.mName; | |||
| 11500 | ||||
| 11501 | int32_t attNs = name->NamespaceID(); | |||
| 11502 | nsAtom* attName = name->LocalName(); | |||
| 11503 | ||||
| 11504 | // Filter out any attribute starting with [-|_]moz | |||
| 11505 | // FIXME(emilio): Do we still need this? | |||
| 11506 | nsDependentAtomString attrNameStr(attName); | |||
| 11507 | if (StringBeginsWith(attrNameStr, u"_moz"_ns) || | |||
| 11508 | StringBeginsWith(attrNameStr, u"-moz"_ns)) { | |||
| 11509 | continue; | |||
| 11510 | } | |||
| 11511 | ||||
| 11512 | aBuilder.Append(u" "); | |||
| 11513 | ||||
| 11514 | if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) || | |||
| 11515 | (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) { | |||
| 11516 | // Nothing else required | |||
| 11517 | } else if (attNs == kNameSpaceID_XML2) { | |||
| 11518 | aBuilder.Append(u"xml:"); | |||
| 11519 | } else if (attNs == kNameSpaceID_XMLNS1) { | |||
| 11520 | aBuilder.Append(u"xmlns:"); | |||
| 11521 | } else if (attNs == kNameSpaceID_XLink4) { | |||
| 11522 | aBuilder.Append(u"xlink:"); | |||
| 11523 | } else if (nsAtom* prefix = name->GetPrefix()) { | |||
| 11524 | aBuilder.Append(prefix); | |||
| 11525 | aBuilder.Append(u":"); | |||
| 11526 | } | |||
| 11527 | ||||
| 11528 | aBuilder.Append(attName); | |||
| 11529 | aBuilder.Append(uR"(=")"); | |||
| 11530 | AppendEncodedAttributeValue(*info.mValue, aBuilder); | |||
| 11531 | aBuilder.Append(uR"(")"); | |||
| 11532 | } | |||
| 11533 | ||||
| 11534 | aBuilder.Append(u">"); | |||
| 11535 | ||||
| 11536 | /* | |||
| 11537 | // Per HTML spec we should append one \n if the first child of | |||
| 11538 | // pre/textarea/listing is a textnode and starts with a \n. | |||
| 11539 | // But because browsers haven't traditionally had that behavior, | |||
| 11540 | // we're not changing our behavior either - yet. | |||
| 11541 | if (aContent->IsHTMLElement()) { | |||
| 11542 | if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea || | |||
| 11543 | localName == nsGkAtoms::listing) { | |||
| 11544 | nsIContent* fc = aContent->GetFirstChild(); | |||
| 11545 | if (fc && | |||
| 11546 | (fc->NodeType() == nsINode::TEXT_NODE || | |||
| 11547 | fc->NodeType() == nsINode::CDATA_SECTION_NODE)) { | |||
| 11548 | const CharacterDataBuffer* text = fc->GetText(); | |||
| 11549 | if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) { | |||
| 11550 | aBuilder.Append("\n"); | |||
| 11551 | } | |||
| 11552 | } | |||
| 11553 | } | |||
| 11554 | }*/ | |||
| 11555 | } | |||
| 11556 | ||||
| 11557 | static inline bool ShouldEscape(nsIContent* aParent) { | |||
| 11558 | if (!aParent || !aParent->IsHTMLElement()) { | |||
| 11559 | return true; | |||
| 11560 | } | |||
| 11561 | ||||
| 11562 | static const nsAtom* nonEscapingElements[] = { | |||
| 11563 | nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp, | |||
| 11564 | nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes, | |||
| 11565 | nsGkAtoms::plaintext, nsGkAtoms::noscript}; | |||
| 11566 | static mozilla::BitBloomFilter<12, nsAtom> sFilter; | |||
| 11567 | static bool sInitialized = false; | |||
| 11568 | if (!sInitialized) { | |||
| 11569 | sInitialized = true; | |||
| 11570 | for (auto& nonEscapingElement : nonEscapingElements) { | |||
| 11571 | sFilter.add(nonEscapingElement); | |||
| 11572 | } | |||
| 11573 | } | |||
| 11574 | ||||
| 11575 | nsAtom* tag = aParent->NodeInfo()->NameAtom(); | |||
| 11576 | if (sFilter.mightContain(tag)) { | |||
| 11577 | for (auto& nonEscapingElement : nonEscapingElements) { | |||
| 11578 | if (tag == nonEscapingElement) { | |||
| 11579 | if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) && | |||
| 11580 | MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled ()), 0))) { | |||
| 11581 | return true; | |||
| 11582 | } | |||
| 11583 | return false; | |||
| 11584 | } | |||
| 11585 | } | |||
| 11586 | } | |||
| 11587 | return true; | |||
| 11588 | } | |||
| 11589 | ||||
| 11590 | static inline bool IsVoidTag(Element* aElement) { | |||
| 11591 | if (!aElement->IsHTMLElement()) { | |||
| 11592 | return false; | |||
| 11593 | } | |||
| 11594 | return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom()); | |||
| 11595 | } | |||
| 11596 | ||||
| 11597 | static bool StartSerializingShadowDOM( | |||
| 11598 | nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots, | |||
| 11599 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
| 11600 | ShadowRoot* shadow = aNode->GetShadowRoot(); | |||
| 11601 | if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) && | |||
| 11602 | !aShadowRoots.Contains(shadow))) { | |||
| 11603 | return false; | |||
| 11604 | } | |||
| 11605 | ||||
| 11606 | // https://html.spec.whatwg.org/#html-fragment-serialisation-algorithm | |||
| 11607 | // steps 4-12 | |||
| 11608 | ||||
| 11609 | // 4.2.1. Append "<template shadowrootmode="". | |||
| 11610 | aBuilder.Append(u"<template shadowrootmode=\""); | |||
| 11611 | ||||
| 11612 | // 4.2.2. If shadow's mode is "open", then append "open". Otherwise, append | |||
| 11613 | // "closed". | |||
| 11614 | // 3. Append U+0022 ("). | |||
| 11615 | if (shadow->IsClosed()) { | |||
| 11616 | aBuilder.Append(u"closed\""); | |||
| 11617 | } else { | |||
| 11618 | aBuilder.Append(u"open\""); | |||
| 11619 | } | |||
| 11620 | ||||
| 11621 | // 4. If shadow's delegates focus is set, then append " | |||
| 11622 | // shadowrootdelegatesfocus=""". | |||
| 11623 | if (shadow->DelegatesFocus()) { | |||
| 11624 | aBuilder.Append(u" shadowrootdelegatesfocus=\"\""); | |||
| 11625 | } | |||
| 11626 | ||||
| 11627 | // 5. If shadow's serializable is set, then append " | |||
| 11628 | // shadowrootserializable=""". | |||
| 11629 | if (shadow->Serializable()) { | |||
| 11630 | aBuilder.Append(u" shadowrootserializable=\"\""); | |||
| 11631 | } | |||
| 11632 | ||||
| 11633 | // 6. If shadow's slot assignment is "manual", then append " | |||
| 11634 | // shadowrootslotassignment="manual"". | |||
| 11635 | if (StaticPrefs::dom_shadowdom_shadowRootSlotAssignment_enabled() && | |||
| 11636 | shadow->SlotAssignment() == SlotAssignmentMode::Manual) { | |||
| 11637 | aBuilder.Append(u" shadowrootslotassignment=\"manual\""); | |||
| 11638 | } | |||
| 11639 | ||||
| 11640 | // 7. If shadow's slot assignment is "manual", then append " | |||
| 11641 | // shadowrootslotassignment="manual"". | |||
| 11642 | if (shadow->Clonable()) { | |||
| 11643 | aBuilder.Append(u" shadowrootclonable=\"\""); | |||
| 11644 | } | |||
| 11645 | ||||
| 11646 | auto isGlobalCustomElementRegistry = [](CustomElementRegistry* registry) { | |||
| 11647 | return registry && !registry->IsScoped(); | |||
| 11648 | }; | |||
| 11649 | ||||
| 11650 | // 8. Let shouldAppendRegistryAttribute be the result of running these steps: | |||
| 11651 | const bool shouldAppendRegistryAttribute = [&]() { | |||
| 11652 | if (!StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 11653 | return false; | |||
| 11654 | } | |||
| 11655 | ||||
| 11656 | // 8.1. Let documentRegistry be shadow's node document's custom element | |||
| 11657 | // registry. | |||
| 11658 | CustomElementRegistry* documentRegistry = | |||
| 11659 | shadow->OwnerDoc()->GetCustomElementRegistry(); | |||
| 11660 | // 8.2. Let shadowRegistry be shadow's custom element registry. | |||
| 11661 | CustomElementRegistry* shadowRegistry = shadow->GetCustomElementRegistry(); | |||
| 11662 | ||||
| 11663 | // 8.3. If documentRegistry is null and shadowRegistry is null, then return | |||
| 11664 | // false. | |||
| 11665 | if (!documentRegistry && !shadowRegistry) { | |||
| 11666 | return false; | |||
| 11667 | } | |||
| 11668 | // 8.4. If documentRegistry is a global custom element registry and | |||
| 11669 | // shadowRegistry is a global custom element registry, then return | |||
| 11670 | // false. | |||
| 11671 | else if (isGlobalCustomElementRegistry(documentRegistry) && | |||
| 11672 | isGlobalCustomElementRegistry(shadowRegistry)) { | |||
| 11673 | return false; | |||
| 11674 | } | |||
| 11675 | ||||
| 11676 | // 8.5. Return true. | |||
| 11677 | return true; | |||
| 11678 | }(); | |||
| 11679 | ||||
| 11680 | // 9. If shouldAppendRegistryAttribute is true, then append " | |||
| 11681 | // shadowrootcustomelementregistry=""". | |||
| 11682 | if (shouldAppendRegistryAttribute) { | |||
| 11683 | aBuilder.Append(u" shadowrootcustomelementregistry=\"\""); | |||
| 11684 | } | |||
| 11685 | ||||
| 11686 | // 10. Append U+003E (>). | |||
| 11687 | aBuilder.Append(u">"); | |||
| 11688 | ||||
| 11689 | // 11. Append the value of running the HTML fragment serialization algorithm | |||
| 11690 | // with shadow, serializableShadowRoots, and shadowRoots (thus recursing | |||
| 11691 | // into this algorithm for that element). | |||
| 11692 | // (Returning `true` tells the caller to continue). | |||
| 11693 | if (!shadow->HasChildren()) { | |||
| 11694 | // 12. Append "</template>". | |||
| 11695 | aBuilder.Append(u"</template>"); | |||
| 11696 | return false; | |||
| 11697 | } | |||
| 11698 | return true; | |||
| 11699 | } | |||
| 11700 | ||||
| 11701 | template <SerializeShadowRoots ShouldSerializeShadowRoots> | |||
| 11702 | static void SerializeNodeToMarkupInternal( | |||
| 11703 | nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder, | |||
| 11704 | bool aSerializableShadowRoots, | |||
| 11705 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
| 11706 | nsINode* current = | |||
| 11707 | aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot; | |||
| 11708 | if (!current) { | |||
| 11709 | return; | |||
| 11710 | } | |||
| 11711 | ||||
| 11712 | nsIContent* next; | |||
| 11713 | while (true) { | |||
| 11714 | bool isVoid = false; | |||
| 11715 | switch (current->NodeType()) { | |||
| 11716 | case nsINode::ELEMENT_NODE: { | |||
| 11717 | Element* elem = current->AsElement(); | |||
| 11718 | StartElement(elem, aBuilder); | |||
| 11719 | ||||
| 11720 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
| 11721 | if (StartSerializingShadowDOM( | |||
| 11722 | current, aBuilder, aSerializableShadowRoots, aShadowRoots)) { | |||
| 11723 | current = current->GetShadowRoot()->GetFirstChild(); | |||
| 11724 | continue; | |||
| 11725 | } | |||
| 11726 | } | |||
| 11727 | ||||
| 11728 | isVoid = IsVoidTag(elem); | |||
| 11729 | if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) { | |||
| 11730 | current = next; | |||
| 11731 | continue; | |||
| 11732 | } | |||
| 11733 | break; | |||
| 11734 | } | |||
| 11735 | ||||
| 11736 | case nsINode::TEXT_NODE: | |||
| 11737 | case nsINode::CDATA_SECTION_NODE: { | |||
| 11738 | const CharacterDataBuffer* characterDataBuffer = | |||
| 11739 | ¤t->AsText()->DataBuffer(); | |||
| 11740 | nsIContent* parent = current->GetParent(); | |||
| 11741 | if (ShouldEscape(parent)) { | |||
| 11742 | AppendEncodedCharacters(characterDataBuffer, aBuilder); | |||
| 11743 | } else { | |||
| 11744 | aBuilder.Append(characterDataBuffer); | |||
| 11745 | } | |||
| 11746 | break; | |||
| 11747 | } | |||
| 11748 | ||||
| 11749 | case nsINode::COMMENT_NODE: { | |||
| 11750 | aBuilder.Append(u"<!--"); | |||
| 11751 | aBuilder.Append( | |||
| 11752 | static_cast<nsIContent*>(current)->GetCharacterDataBuffer()); | |||
| 11753 | aBuilder.Append(u"-->"); | |||
| 11754 | break; | |||
| 11755 | } | |||
| 11756 | ||||
| 11757 | case nsINode::DOCUMENT_TYPE_NODE: { | |||
| 11758 | aBuilder.Append(u"<!DOCTYPE "); | |||
| 11759 | aBuilder.Append(nsString(current->NodeName())); | |||
| 11760 | aBuilder.Append(u">"); | |||
| 11761 | break; | |||
| 11762 | } | |||
| 11763 | ||||
| 11764 | case nsINode::PROCESSING_INSTRUCTION_NODE: { | |||
| 11765 | aBuilder.Append(u"<?"); | |||
| 11766 | aBuilder.Append(nsString(current->NodeName())); | |||
| 11767 | aBuilder.Append(u" "); | |||
| 11768 | aBuilder.Append( | |||
| 11769 | static_cast<nsIContent*>(current)->GetCharacterDataBuffer()); | |||
| 11770 | aBuilder.Append(u">"); | |||
| 11771 | break; | |||
| 11772 | } | |||
| 11773 | } | |||
| 11774 | ||||
| 11775 | while (true) { | |||
| 11776 | if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) { | |||
| 11777 | aBuilder.Append(u"</"); | |||
| 11778 | nsIContent* elem = static_cast<nsIContent*>(current); | |||
| 11779 | if (elem->IsHTMLElement() || elem->IsSVGElement() || | |||
| 11780 | elem->IsMathMLElement()) { | |||
| 11781 | aBuilder.Append(elem->NodeInfo()->NameAtom()); | |||
| 11782 | } else { | |||
| 11783 | aBuilder.Append(nsString(current->NodeName())); | |||
| 11784 | } | |||
| 11785 | aBuilder.Append(u">"); | |||
| 11786 | } | |||
| 11787 | isVoid = false; | |||
| 11788 | ||||
| 11789 | if (current == aRoot) { | |||
| 11790 | return; | |||
| 11791 | } | |||
| 11792 | ||||
| 11793 | if ((next = current->GetNextSibling())) { | |||
| 11794 | current = next; | |||
| 11795 | break; | |||
| 11796 | } | |||
| 11797 | ||||
| 11798 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
| 11799 | // If the current node is a shadow root, then we must go to its host. | |||
| 11800 | // Since shadow DOMs are serialized declaratively as template | |||
| 11801 | // elements, we serialize the end tag of the template before going | |||
| 11802 | // back to serializing the shadow host. | |||
| 11803 | if (current->IsShadowRoot()) { | |||
| 11804 | current = current->GetContainingShadowHost(); | |||
| 11805 | aBuilder.Append(u"</template>"); | |||
| 11806 | ||||
| 11807 | if (current->HasChildren()) { | |||
| 11808 | current = current->GetFirstChildOfTemplateOrNode(); | |||
| 11809 | break; | |||
| 11810 | } | |||
| 11811 | continue; | |||
| 11812 | } | |||
| 11813 | } | |||
| 11814 | ||||
| 11815 | current = current->GetParentNode(); | |||
| 11816 | ||||
| 11817 | // Handle template element. If the parent is a template's content, | |||
| 11818 | // then adjust the parent to be the template element. | |||
| 11819 | if (current != aRoot && | |||
| 11820 | current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) { | |||
| 11821 | DocumentFragment* frag = static_cast<DocumentFragment*>(current); | |||
| 11822 | nsIContent* fragHost = frag->GetHost(); | |||
| 11823 | if (fragHost && fragHost->IsTemplateElement()) { | |||
| 11824 | current = fragHost; | |||
| 11825 | } | |||
| 11826 | } | |||
| 11827 | ||||
| 11828 | if (aDescendantsOnly && current == aRoot) { | |||
| 11829 | return; | |||
| 11830 | } | |||
| 11831 | } | |||
| 11832 | } | |||
| 11833 | } | |||
| 11834 | ||||
| 11835 | template <SerializeShadowRoots ShouldSerializeShadowRoots> | |||
| 11836 | bool nsContentUtils::SerializeNodeToMarkup( | |||
| 11837 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
| 11838 | bool aSerializableShadowRoots, | |||
| 11839 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
| 11840 | // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true | |||
| 11841 | MOZ_ASSERT(aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDescendantsOnly || aRoot->NodeType() != nsINode:: DOCUMENT_NODE)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aDescendantsOnly || aRoot->NodeType () != nsINode::DOCUMENT_NODE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11841); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE" ")"); do { MOZ_CrashSequence(__null, 11841); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 11842 | ||||
| 11843 | StringBuilder builder; | |||
| 11844 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
| 11845 | if (aDescendantsOnly && | |||
| 11846 | StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots, | |||
| 11847 | aShadowRoots)) { | |||
| 11848 | SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>( | |||
| 11849 | aRoot->GetShadowRoot(), true, builder, aSerializableShadowRoots, | |||
| 11850 | aShadowRoots); | |||
| 11851 | // The template tag is opened in StartSerializingShadowDOM, so we need | |||
| 11852 | // to close it here before serializing any children of aRoot. | |||
| 11853 | builder.Append(u"</template>"); | |||
| 11854 | } | |||
| 11855 | } | |||
| 11856 | ||||
| 11857 | SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>( | |||
| 11858 | aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots); | |||
| 11859 | return builder.ToString(aOut); | |||
| 11860 | } | |||
| 11861 | ||||
| 11862 | template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>( | |||
| 11863 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
| 11864 | bool aSerializableShadowRoots, | |||
| 11865 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots); | |||
| 11866 | template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>( | |||
| 11867 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
| 11868 | bool aSerializableShadowRoots, | |||
| 11869 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots); | |||
| 11870 | ||||
| 11871 | bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) { | |||
| 11872 | // aUri must start with about: or this isn't the right function to be using. | |||
| 11873 | MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(strncmp(aUri, "about:", 6) == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(strncmp(aUri, "about:", 6) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("strncmp(aUri, \"about:\", 6) == 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 11873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0" ")"); do { MOZ_CrashSequence(__null, 11873); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 11874 | ||||
| 11875 | // Make sure the global is a window | |||
| 11876 | MOZ_DIAGNOSTIC_ASSERT(JS_IsGlobalObject(aGlobal))do { static_assert( mozilla::detail::AssertionConditionType< decltype(JS_IsGlobalObject(aGlobal))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(aGlobal))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(aGlobal)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11876); AnnotateMozCrashReason ("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)" ")" ); do { MOZ_CrashSequence(__null, 11876); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 11877 | nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal); | |||
| 11878 | if (!win) { | |||
| 11879 | return false; | |||
| 11880 | } | |||
| 11881 | ||||
| 11882 | nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal(); | |||
| 11883 | NS_ENSURE_TRUE(principal, false)do { if ((__builtin_expect(!!(!(principal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principal" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11883); return false; } } while (false); | |||
| 11884 | ||||
| 11885 | // First check the scheme to avoid getting long specs in the common case. | |||
| 11886 | if (!principal->SchemeIs("about")) { | |||
| 11887 | return false; | |||
| 11888 | } | |||
| 11889 | ||||
| 11890 | nsAutoCString spec; | |||
| 11891 | principal->GetAsciiSpec(spec); | |||
| 11892 | ||||
| 11893 | return spec.EqualsASCII(aUri); | |||
| 11894 | } | |||
| 11895 | ||||
| 11896 | /* static */ | |||
| 11897 | nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) { | |||
| 11898 | if (!aTarget) { | |||
| 11899 | return nullptr; | |||
| 11900 | } | |||
| 11901 | ||||
| 11902 | nsCOMPtr<nsPIDOMWindowInner> innerWindow; | |||
| 11903 | if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) { | |||
| 11904 | bool ignore; | |||
| 11905 | innerWindow = | |||
| 11906 | do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore)); | |||
| 11907 | } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) { | |||
| 11908 | // Nothing else to do | |||
| 11909 | } else if (nsCOMPtr<DOMEventTargetHelper> helper = | |||
| 11910 | do_QueryInterface(aTarget)) { | |||
| 11911 | innerWindow = helper->GetOwnerWindow(); | |||
| 11912 | } | |||
| 11913 | ||||
| 11914 | if (innerWindow) { | |||
| 11915 | return innerWindow->GetDocShell(); | |||
| 11916 | } | |||
| 11917 | ||||
| 11918 | return nullptr; | |||
| 11919 | } | |||
| 11920 | ||||
| 11921 | /* | |||
| 11922 | * Note: this function only relates to figuring out HTTPS state, which is an | |||
| 11923 | * input to the Secure Context algorithm. We are not actually implementing | |||
| 11924 | * any part of the Secure Context algorithm itself here. | |||
| 11925 | * | |||
| 11926 | * This is a bit of a hack. Ideally we'd propagate HTTPS state through | |||
| 11927 | * nsIChannel as described in the Fetch and HTML specs, but making channels | |||
| 11928 | * know about whether they should inherit HTTPS state, propagating information | |||
| 11929 | * about who the channel's "client" is, exposing GetHttpsState API on channels | |||
| 11930 | * and modifying the various cache implementations to store and retrieve HTTPS | |||
| 11931 | * state involves a huge amount of code (see bug 1220687). We avoid that for | |||
| 11932 | * now using this function. | |||
| 11933 | * | |||
| 11934 | * This function takes advantage of the observation that we can return true if | |||
| 11935 | * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for | |||
| 11936 | * the document's origin (e.g. the origin has a scheme of 'https' or host | |||
| 11937 | * 'localhost' etc.). Since we generally propagate a creator document's | |||
| 11938 | * origin onto data:, blob:, etc. documents, this works for them too. | |||
| 11939 | * | |||
| 11940 | * The scenario where this observation breaks down is sandboxing without the | |||
| 11941 | * 'allow-same-origin' flag, since in this case a document is given a unique | |||
| 11942 | * origin (IsOriginPotentiallyTrustworthy would return false). We handle that | |||
| 11943 | * by using the origin that the document would have had had it not been | |||
| 11944 | * sandboxed. | |||
| 11945 | * | |||
| 11946 | * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's | |||
| 11947 | * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of | |||
| 11948 | * sandboxing is limited to the immediate sandbox. In the case that aDocument | |||
| 11949 | * should inherit its origin (e.g. data: URI) but its parent has ended up | |||
| 11950 | * with a unique origin due to sandboxing further up the parent chain we may | |||
| 11951 | * end up returning false when we would ideally return true (since we will | |||
| 11952 | * examine the parent's origin for 'https' and not finding it.) This means | |||
| 11953 | * that we may restrict the privileges of some pages unnecessarily in this | |||
| 11954 | * edge case. | |||
| 11955 | */ | |||
| 11956 | /* static */ | |||
| 11957 | bool nsContentUtils::HttpsStateIsModern(Document* aDocument) { | |||
| 11958 | if (!aDocument) { | |||
| 11959 | return false; | |||
| 11960 | } | |||
| 11961 | ||||
| 11962 | nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal(); | |||
| 11963 | ||||
| 11964 | if (principal->IsSystemPrincipal()) { | |||
| 11965 | return true; | |||
| 11966 | } | |||
| 11967 | ||||
| 11968 | // If aDocument is sandboxed, try and get the principal that it would have | |||
| 11969 | // been given had it not been sandboxed: | |||
| 11970 | if (principal->GetIsNullPrincipal() && | |||
| 11971 | (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) { | |||
| 11972 | nsIChannel* channel = aDocument->GetChannel(); | |||
| 11973 | if (channel) { | |||
| 11974 | nsCOMPtr<nsIScriptSecurityManager> ssm = | |||
| 11975 | nsContentUtils::GetSecurityManager(); | |||
| 11976 | nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed( | |||
| 11977 | channel, getter_AddRefs(principal)); | |||
| 11978 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 11979 | return false; | |||
| 11980 | } | |||
| 11981 | if (principal->IsSystemPrincipal()) { | |||
| 11982 | // If a document with the system principal is sandboxing a subdocument | |||
| 11983 | // that would normally inherit the embedding element's principal (e.g. | |||
| 11984 | // a srcdoc document) then the embedding document does not trust the | |||
| 11985 | // content that is written to the embedded document. Unlike when the | |||
| 11986 | // embedding document is https, in this case we have no indication as | |||
| 11987 | // to whether the embedded document's contents are delivered securely | |||
| 11988 | // or not, and the sandboxing would possibly indicate that they were | |||
| 11989 | // not. To play it safe we return false here. (See bug 1162772 | |||
| 11990 | // comment 73-80.) | |||
| 11991 | return false; | |||
| 11992 | } | |||
| 11993 | } | |||
| 11994 | } | |||
| 11995 | ||||
| 11996 | if (principal->GetIsNullPrincipal()) { | |||
| 11997 | return false; | |||
| 11998 | } | |||
| 11999 | ||||
| 12000 | MOZ_ASSERT(principal->GetIsContentPrincipal())do { static_assert( mozilla::detail::AssertionConditionType< decltype(principal->GetIsContentPrincipal())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(principal->GetIsContentPrincipal()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("principal->GetIsContentPrincipal()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12000); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()" ")" ); do { MOZ_CrashSequence(__null, 12000); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12001 | ||||
| 12002 | return principal->GetIsOriginPotentiallyTrustworthy(); | |||
| 12003 | } | |||
| 12004 | ||||
| 12005 | /* static */ | |||
| 12006 | bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) { | |||
| 12007 | MOZ_ASSERT(aChannel)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChannel)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aChannel))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")" ); do { MOZ_CrashSequence(__null, 12007); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12008 | ||||
| 12009 | nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager(); | |||
| 12010 | nsCOMPtr<nsIPrincipal> principal; | |||
| 12011 | nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed( | |||
| 12012 | aChannel, getter_AddRefs(principal)); | |||
| 12013 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 12014 | return false; | |||
| 12015 | } | |||
| 12016 | ||||
| 12017 | const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
| 12018 | ||||
| 12019 | if (principal->IsSystemPrincipal()) { | |||
| 12020 | // If the load would've been sandboxed, treat this load as an untrusted | |||
| 12021 | // load, as system code considers sandboxed resources insecure. | |||
| 12022 | return !loadInfo->GetLoadingSandboxed(); | |||
| 12023 | } | |||
| 12024 | ||||
| 12025 | if (principal->GetIsNullPrincipal()) { | |||
| 12026 | return false; | |||
| 12027 | } | |||
| 12028 | ||||
| 12029 | if (const RefPtr<WindowContext> windowContext = | |||
| 12030 | WindowContext::GetById(loadInfo->GetInnerWindowID())) { | |||
| 12031 | if (!windowContext->GetIsSecureContext()) { | |||
| 12032 | return false; | |||
| 12033 | } | |||
| 12034 | } | |||
| 12035 | ||||
| 12036 | return principal->GetIsOriginPotentiallyTrustworthy(); | |||
| 12037 | } | |||
| 12038 | ||||
| 12039 | /* https://html.spec.whatwg.org/#concept-try-upgrade */ | |||
| 12040 | void nsContentUtils::TryToUpgradeElement(Element* aElement) { | |||
| 12041 | // 1. "Let definition be the result of looking up a custom element definition | |||
| 12042 | // given element's custom element registry, element's namespace, element's | |||
| 12043 | // local name, and element's is value." | |||
| 12044 | NodeInfo* nodeInfo = aElement->NodeInfo(); | |||
| 12045 | RefPtr<nsAtom> typeAtom = | |||
| 12046 | aElement->GetCustomElementData()->GetCustomElementType(); | |||
| 12047 | ||||
| 12048 | MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12048); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" ")"); do { MOZ_CrashSequence(__null, 12048); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12049 | ||||
| 12050 | // When scoped custom element registries are enabled, look up the element's | |||
| 12051 | // own custom element registry (which may be a scoped registry, null, or the | |||
| 12052 | // document's global registry as fallback). | |||
| 12053 | CustomElementRegistry* registry = nullptr; | |||
| 12054 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 12055 | registry = aElement->GetCustomElementRegistry(); | |||
| 12056 | if (!registry) { | |||
| 12057 | return; | |||
| 12058 | } | |||
| 12059 | } | |||
| 12060 | ||||
| 12061 | CustomElementDefinition* definition = nullptr; | |||
| 12062 | if (registry) { | |||
| 12063 | definition = registry->LookupCustomElementDefinition( | |||
| 12064 | nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom); | |||
| 12065 | } else { | |||
| 12066 | MOZ_ASSERT(!StaticPrefs::dom_scoped_custom_element_registries_enabled())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!StaticPrefs::dom_scoped_custom_element_registries_enabled ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!StaticPrefs::dom_scoped_custom_element_registries_enabled ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!StaticPrefs::dom_scoped_custom_element_registries_enabled()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12066); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()" ")"); do { MOZ_CrashSequence(__null, 12066); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12067 | definition = nsContentUtils::LookupCustomElementDefinition( | |||
| 12068 | nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(), | |||
| 12069 | typeAtom); | |||
| 12070 | } | |||
| 12071 | ||||
| 12072 | // 2. "If definition is not null, then enqueue a custom element upgrade | |||
| 12073 | // reaction given element and definition." | |||
| 12074 | if (definition) { | |||
| 12075 | nsContentUtils::EnqueueUpgradeReaction(aElement, definition); | |||
| 12076 | } else if (registry) { | |||
| 12077 | registry->RegisterUnresolvedElement(aElement, typeAtom); | |||
| 12078 | } else { | |||
| 12079 | MOZ_ASSERT(!StaticPrefs::dom_scoped_custom_element_registries_enabled())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!StaticPrefs::dom_scoped_custom_element_registries_enabled ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!StaticPrefs::dom_scoped_custom_element_registries_enabled ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!StaticPrefs::dom_scoped_custom_element_registries_enabled()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12079); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()" ")"); do { MOZ_CrashSequence(__null, 12079); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12080 | // XXX: Not in spec. Add an unresolved custom element that is a candidate | |||
| 12081 | // for upgrade when a custom element is connected to the document. | |||
| 12082 | nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom); | |||
| 12083 | } | |||
| 12084 | } | |||
| 12085 | ||||
| 12086 | MOZ_CAN_RUN_SCRIPT | |||
| 12087 | static void DoCustomElementCreate(Element** aElement, JSContext* aCx, | |||
| 12088 | Document* aDoc, NodeInfo* aNodeInfo, | |||
| 12089 | CustomElementConstructor* aConstructor, | |||
| 12090 | ErrorResult& aRv, FromParser aFromParser) { | |||
| 12091 | JS::Rooted<JS::Value> constructResult(aCx); | |||
| 12092 | aConstructor->Construct(&constructResult, aRv, "Custom Element Create", | |||
| 12093 | CallbackFunction::eRethrowExceptions); | |||
| 12094 | if (aRv.Failed()) { | |||
| 12095 | return; | |||
| 12096 | } | |||
| 12097 | ||||
| 12098 | RefPtr<Element> element; | |||
| 12099 | // constructResult is an ObjectValue because construction with a callback | |||
| 12100 | // always forms the return value from a JSObject. | |||
| 12101 | UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts < mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding ::NativeType>(&constructResult, element); | |||
| 12102 | if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
| 12103 | if (!element || !element->IsHTMLElement()) { | |||
| 12104 | aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"", | |||
| 12105 | "HTMLElement"); | |||
| 12106 | return; | |||
| 12107 | } | |||
| 12108 | } else { | |||
| 12109 | if (!element || !element->IsXULElement()) { | |||
| 12110 | aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"", | |||
| 12111 | "XULElement"); | |||
| 12112 | return; | |||
| 12113 | } | |||
| 12114 | } | |||
| 12115 | ||||
| 12116 | nsAtom* localName = aNodeInfo->NameAtom(); | |||
| 12117 | ||||
| 12118 | if (aDoc != element->OwnerDoc() || element->GetParentNode() || | |||
| 12119 | element->HasChildren() || element->GetAttrCount() || | |||
| 12120 | element->NodeInfo()->NameAtom() != localName) { | |||
| 12121 | aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); | |||
| 12122 | return; | |||
| 12123 | } | |||
| 12124 | ||||
| 12125 | if (element->IsHTMLElement()) { | |||
| 12126 | static_cast<HTMLElement*>(&*element)->InhibitRestoration( | |||
| 12127 | !(aFromParser & FROM_PARSER_NETWORK)); | |||
| 12128 | } | |||
| 12129 | ||||
| 12130 | element.forget(aElement); | |||
| 12131 | } | |||
| 12132 | ||||
| 12133 | /* https://dom.spec.whatwg.org/#concept-create-element */ | |||
| 12134 | nsresult nsContentUtils::NewXULOrHTMLElement( | |||
| 12135 | Element** aResult, mozilla::dom::NodeInfo* aNodeInfo, | |||
| 12136 | FromParser aFromParser, nsAtom* aIsAtom, | |||
| 12137 | mozilla::dom::CustomElementDefinition* aDefinition, | |||
| 12138 | Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry) { | |||
| 12139 | RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo; | |||
| 12140 | MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" " (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence (__null, 12142); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| ||||
| 12141 | nodeInfo->NamespaceEquals(kNameSpaceID_XUL),do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" " (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence (__null, 12142); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 12142 | "Can only create XUL or XHTML elements.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals (8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" " (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence (__null, 12142); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 12143 | ||||
| 12144 | nsAtom* name = nodeInfo->NameAtom(); | |||
| 12145 | bool isCustomElementName = false; | |||
| 12146 | const Maybe<const nsHTMLTag>& tag = nodeInfo->HTMLTag(); | |||
| 12147 | if (tag.isSome()) { | |||
| 12148 | MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NamespaceEquals(3))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nodeInfo->NamespaceEquals (3)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NamespaceEquals(3)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3)" ")"); do { MOZ_CrashSequence(__null, 12148); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12149 | isCustomElementName = | |||
| 12150 | (*tag == eHTMLTag_userdefined && | |||
| 12151 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3)); | |||
| 12152 | } else { | |||
| 12153 | MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XUL))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NamespaceEquals(8))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nodeInfo->NamespaceEquals (8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NamespaceEquals(8)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(8)" ")"); do { MOZ_CrashSequence(__null, 12153); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12154 | if (aIsAtom) { | |||
| 12155 | // Make sure the customized built-in element to be constructed confirms | |||
| 12156 | // to our naming requirement, i.e. [is] must be a dashed name and | |||
| 12157 | // the tag name must not. | |||
| 12158 | // if so, set isCustomElementName to false to kick off all the logics | |||
| 12159 | // that pick up aIsAtom. | |||
| 12160 | if (nsContentUtils::IsNameWithDash(aIsAtom) && | |||
| 12161 | !nsContentUtils::IsNameWithDash(name)) { | |||
| 12162 | isCustomElementName = false; | |||
| 12163 | } else { | |||
| 12164 | isCustomElementName = | |||
| 12165 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8); | |||
| 12166 | } | |||
| 12167 | } else { | |||
| 12168 | isCustomElementName = | |||
| 12169 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8); | |||
| 12170 | } | |||
| 12171 | } | |||
| 12172 | ||||
| 12173 | nsAtom* tagAtom = nodeInfo->NameAtom(); | |||
| 12174 | nsAtom* typeAtom = nullptr; | |||
| 12175 | bool isCustomElement = isCustomElementName
| |||
| 12176 | if (isCustomElement
| |||
| 12177 | typeAtom = isCustomElementName
| |||
| 12178 | } | |||
| 12179 | ||||
| 12180 | MOZ_ASSERT_IF(aDefinition, isCustomElement)do { if (aDefinition) { do { static_assert( mozilla::detail:: AssertionConditionType<decltype(isCustomElement)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(isCustomElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("isCustomElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement" ")"); do { MOZ_CrashSequence(__null, 12180); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); | |||
| 12181 | ||||
| 12182 | // 3. "Let definition be the result of looking up a custom element definition | |||
| 12183 | // given registry, namespace, localName, and is." | |||
| 12184 | RefPtr<CustomElementDefinition> definition = aDefinition; | |||
| 12185 | if (isCustomElement
| |||
| 12186 | MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12186); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" ")"); do { MOZ_CrashSequence(__null, 12186); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12187 | // When a custom element registry is provided (e.g. from fragment parsing | |||
| 12188 | // with a scoped registry), use it for definition lookup. | |||
| 12189 | if (aCustomElementRegistry.isSome()) { | |||
| 12190 | if (RefPtr<CustomElementRegistry> registry = | |||
| 12191 | aCustomElementRegistry.value()) { | |||
| 12192 | definition = registry->LookupCustomElementDefinition( | |||
| 12193 | nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom); | |||
| 12194 | } | |||
| 12195 | // If registry is explicitly null, definition stays null (no upgrade). | |||
| 12196 | } else { | |||
| 12197 | definition = nsContentUtils::LookupCustomElementDefinition( | |||
| 12198 | nodeInfo->GetDocument(), nodeInfo->NameAtom(), | |||
| 12199 | nodeInfo->NamespaceID(), typeAtom); | |||
| 12200 | } | |||
| 12201 | } | |||
| 12202 | ||||
| 12203 | /* | |||
| 12204 | * Synchronous custom elements flag is determined by 3 places in spec, | |||
| 12205 | * 1) create an element for a token, the flag is determined by | |||
| 12206 | * "will execute script" which is not originally created | |||
| 12207 | * for the HTML fragment parsing algorithm. | |||
| 12208 | * 2) createElement and createElementNS, the flag is the same as | |||
| 12209 | * NOT_FROM_PARSER. | |||
| 12210 | * 3) clone a node, our implementation will not go into this function. | |||
| 12211 | * For the unset case which is non-synchronous only applied for | |||
| 12212 | * inner/outerHTML. | |||
| 12213 | */ | |||
| 12214 | bool synchronousCustomElements = | |||
| 12215 | definition && aFromParser != dom::FROM_PARSER_FRAGMENT; | |||
| 12216 | auto setRegistryOnExit = MakeScopeExit([&]() { | |||
| 12217 | if (!*aResult || | |||
| 12218 | !StaticPrefs::dom_scoped_custom_element_registries_enabled() || | |||
| 12219 | synchronousCustomElements) { | |||
| 12220 | return; | |||
| 12221 | } | |||
| 12222 | if (aCustomElementRegistry.isSome()) { | |||
| 12223 | RefPtr<CustomElementRegistry> registry = aCustomElementRegistry.value(); | |||
| 12224 | if (registry) { | |||
| 12225 | (*aResult)->SetCustomElementRegistry(registry); | |||
| 12226 | } else { | |||
| 12227 | (*aResult)->SetNullCustomElementRegistry(); | |||
| 12228 | } | |||
| 12229 | } else { | |||
| 12230 | Document* doc = (*aResult)->OwnerDoc(); | |||
| 12231 | if (CustomElementRegistry* globalRegistry = | |||
| 12232 | doc->GetEffectiveGlobalCustomElementRegistry()) { | |||
| 12233 | (*aResult)->SetCustomElementRegistry(globalRegistry); | |||
| 12234 | } | |||
| 12235 | } | |||
| 12236 | }); | |||
| 12237 | ||||
| 12238 | // It might be a problem that parser synchronously calls constructor, so | |||
| 12239 | // filed bug 1378079 to figure out what we should do for parser case. | |||
| 12240 | if (definition) { | |||
| 12241 | // Per discussion in https://github.com/w3c/webcomponents/issues/635, | |||
| 12242 | // use entry global in those places that are called from JS APIs and use | |||
| 12243 | // the node document's global object if it is called from parser. | |||
| 12244 | nsIGlobalObject* global; | |||
| 12245 | if (aFromParser == dom::NOT_FROM_PARSER) { | |||
| 12246 | global = GetEntryGlobal(); | |||
| 12247 | ||||
| 12248 | // Documents created from the PrototypeDocumentSink always use | |||
| 12249 | // NOT_FROM_PARSER for non-XUL elements. We can get the global from the | |||
| 12250 | // document in that case. | |||
| 12251 | if (!global) { | |||
| 12252 | Document* doc = nodeInfo->GetDocument(); | |||
| 12253 | if (doc && doc->LoadedFromPrototype()) { | |||
| 12254 | global = doc->GetScopeObject(); | |||
| 12255 | } | |||
| 12256 | } | |||
| 12257 | } else { | |||
| 12258 | global = nodeInfo->GetDocument()->GetScopeObject(); | |||
| 12259 | } | |||
| 12260 | if (!global
| |||
| 12261 | // In browser chrome code, one may have access to a document which | |||
| 12262 | // doesn't have scope object anymore. | |||
| 12263 | return NS_ERROR_FAILURE; | |||
| 12264 | } | |||
| 12265 | ||||
| 12266 | AutoAllowLegacyScriptExecution exemption; | |||
| 12267 | AutoEntryScript aes(global, "create custom elements"); | |||
| 12268 | JSContext* cx = aes.cx(); | |||
| 12269 | ErrorResult rv; | |||
| 12270 | ||||
| 12271 | // 4. "If definition is non-null, and definition's name is not equal to its | |||
| 12272 | // local name (i.e., definition represents a customized built-in | |||
| 12273 | // element):" | |||
| 12274 | if (definition->IsCustomBuiltIn()) { | |||
| 12275 | // 4.2. "Set result to the result of creating an element internal..." | |||
| 12276 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
| 12277 | *aResult = | |||
| 12278 | CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take(); | |||
| 12279 | } else { | |||
| 12280 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
| 12281 | } | |||
| 12282 | (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom)); | |||
| ||||
| 12283 | if (synchronousCustomElements) { | |||
| 12284 | // 4.3. "If synchronousCustomElements is true, then run this step while | |||
| 12285 | // catching any exceptions: Upgrade result using definition." | |||
| 12286 | CustomElementRegistry::Upgrade(*aResult, definition, rv); | |||
| 12287 | if (rv.MaybeSetPendingException(cx)) { | |||
| 12288 | aes.ReportException(); | |||
| 12289 | } | |||
| 12290 | } else { | |||
| 12291 | // 4.4. "Otherwise, enqueue a custom element upgrade reaction given | |||
| 12292 | // result and definition." | |||
| 12293 | nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); | |||
| 12294 | } | |||
| 12295 | ||||
| 12296 | return NS_OK; | |||
| 12297 | } | |||
| 12298 | ||||
| 12299 | // 5. "Otherwise, if definition is non-null:" | |||
| 12300 | // 5.1. "If synchronousCustomElements is true:" | |||
| 12301 | if (synchronousCustomElements) { | |||
| 12302 | { | |||
| 12303 | // 5.1.1. "Let C be definition's constructor." | |||
| 12304 | CustomElementConstructor* constructor = definition->mConstructor; | |||
| 12305 | ||||
| 12306 | RefPtr<Document> doc = nodeInfo->GetDocument(); | |||
| 12307 | DocGroup* docGroup = doc->GetDocGroup(); | |||
| 12308 | ||||
| 12309 | // XXX: https://github.com/whatwg/dom/pull/1494 | |||
| 12310 | // 5.1.2. Let previousRegistry be the surrounding agent's active | |||
| 12311 | // custom element constructor map[C] with default null. | |||
| 12312 | // 5.1.3. Set the surrounding agent's active custom element constructor | |||
| 12313 | // map[C] to registry. | |||
| 12314 | Maybe<DocGroup::AutoActiveConstructorRegistry> | |||
| 12315 | activeConstructorRegistry; | |||
| 12316 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled() && | |||
| 12317 | constructor->CallableOrNull() && docGroup) { | |||
| 12318 | if (aCustomElementRegistry.isSome()) { | |||
| 12319 | activeConstructorRegistry.emplace(docGroup, constructor, | |||
| 12320 | aCustomElementRegistry.ref()); | |||
| 12321 | } else { | |||
| 12322 | activeConstructorRegistry.emplace( | |||
| 12323 | docGroup, constructor, | |||
| 12324 | doc->GetEffectiveGlobalCustomElementRegistry()); | |||
| 12325 | } | |||
| 12326 | } | |||
| 12327 | ||||
| 12328 | // 5.1.4. "Run these steps while catching any exceptions: | |||
| 12329 | DoCustomElementCreate(aResult, cx, doc, nodeInfo, | |||
| 12330 | MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv, | |||
| 12331 | aFromParser); | |||
| 12332 | ||||
| 12333 | // 5.1.5. If previousRegistry is null, then remove the surrounding | |||
| 12334 | // agent's active custom element constructor map[C]. Otherwise, | |||
| 12335 | // set it back to previousRegistry. | |||
| 12336 | // 5.1.6. Otherwise, set the surrounding agent ’s active custom element | |||
| 12337 | // constructor map[C] to previousRegistry. | |||
| 12338 | // (Handled by `activeRegistry`'s destructor during scope exit). | |||
| 12339 | } | |||
| 12340 | ||||
| 12341 | if (rv.MaybeSetPendingException(cx)) { | |||
| 12342 | // "If any of these steps threw an exception: ... Set result to the | |||
| 12343 | // result of creating an element internal given document, | |||
| 12344 | // HTMLUnknownElement..." | |||
| 12345 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
| 12346 | NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget (), aFromParser)) | |||
| 12347 | aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget (), aFromParser)); | |||
| 12348 | } else { | |||
| 12349 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
| 12350 | } | |||
| 12351 | (*aResult)->SetDefined(false); | |||
| 12352 | // Set the fallback element's registry even on failure. | |||
| 12353 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 12354 | if (aCustomElementRegistry.isSome()) { | |||
| 12355 | if (CustomElementRegistry* registry = | |||
| 12356 | aCustomElementRegistry.ref()) { | |||
| 12357 | (*aResult)->SetCustomElementRegistry(registry); | |||
| 12358 | } else { | |||
| 12359 | (*aResult)->SetNullCustomElementRegistry(); | |||
| 12360 | } | |||
| 12361 | } | |||
| 12362 | } | |||
| 12363 | } else if (*aResult && nodeInfo->GetPrefixAtom()) { | |||
| 12364 | // 5.1.3.9. Set result's namespace prefix to prefix. | |||
| 12365 | (*aResult)->SetNamespacePrefix(nodeInfo->GetPrefixAtom()); | |||
| 12366 | } | |||
| 12367 | return NS_OK; | |||
| 12368 | } | |||
| 12369 | ||||
| 12370 | // 5.2. "Otherwise:" | |||
| 12371 | // 5.2.1. "Set result to the result of creating an element internal given | |||
| 12372 | // document, HTMLElement, localName..." | |||
| 12373 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
| 12374 | NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )) | |||
| 12375 | NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )); | |||
| 12376 | } else { | |||
| 12377 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
| 12378 | } | |||
| 12379 | (*aResult)->SetCustomElementData( | |||
| 12380 | MakeUnique<CustomElementData>(definition->mType)); | |||
| 12381 | // 5.2.2. "Enqueue a custom element upgrade reaction given result and | |||
| 12382 | // definition." | |||
| 12383 | nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); | |||
| 12384 | return NS_OK; | |||
| 12385 | } | |||
| 12386 | ||||
| 12387 | // 6. "Otherwise:" | |||
| 12388 | // 6.1. "Let interface be the element interface for localName and namespace." | |||
| 12389 | // 6.2. "Set result to the result of creating an element internal..." | |||
| 12390 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
| 12391 | // Per the Custom Element specification, unknown tags that are valid | |||
| 12392 | // custom element names should be HTMLElement instead of | |||
| 12393 | // HTMLUnknownElement. | |||
| 12394 | if (isCustomElementName) { | |||
| 12395 | NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )) | |||
| 12396 | NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )); | |||
| 12397 | } else { | |||
| 12398 | *aResult = CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take(); | |||
| 12399 | } | |||
| 12400 | } else { | |||
| 12401 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
| 12402 | } | |||
| 12403 | ||||
| 12404 | if (!*aResult) { | |||
| 12405 | return NS_ERROR_OUT_OF_MEMORY; | |||
| 12406 | } | |||
| 12407 | ||||
| 12408 | // 6.3. "If namespace is the HTML namespace, and either localName is a valid | |||
| 12409 | // custom element name or is is non-null, then set result's custom | |||
| 12410 | // element state to "undefined"." | |||
| 12411 | if (isCustomElement) { | |||
| 12412 | (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom)); | |||
| 12413 | if (aCustomElementRegistry.isSome()) { | |||
| 12414 | // When an explicit custom element registry is provided, register for | |||
| 12415 | // upgrade on that registry (if non-null), not the document's. | |||
| 12416 | if (CustomElementRegistry* registry = aCustomElementRegistry.ref()) { | |||
| 12417 | registry->RegisterCallbackUpgradeElement(*aResult, typeAtom); | |||
| 12418 | } | |||
| 12419 | } else { | |||
| 12420 | nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom); | |||
| 12421 | } | |||
| 12422 | } | |||
| 12423 | ||||
| 12424 | // 7. "Return result." | |||
| 12425 | return NS_OK; | |||
| 12426 | } | |||
| 12427 | ||||
| 12428 | // https://html.spec.whatwg.org/#look-up-a-custom-element-registry | |||
| 12429 | Maybe<RefPtr<CustomElementRegistry>> nsContentUtils::GetCustomElementRegistry( | |||
| 12430 | nsINode* aNode) { | |||
| 12431 | if (!aNode || !StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 12432 | return Nothing(); | |||
| 12433 | } | |||
| 12434 | // 1. If node is an Element object, then return node's custom element | |||
| 12435 | // registry. | |||
| 12436 | // 2. If node is a ShadowRoot object, then return node's custom element | |||
| 12437 | // registry. | |||
| 12438 | // 3. If node is a Document object, then return node's custom element | |||
| 12439 | // registry. | |||
| 12440 | // A node specifies its own registry only when its state is not Global (i.e. | |||
| 12441 | // scoped, or explicitly null). A Global-state node inherits the global | |||
| 12442 | // registry, which we report as Nothing() so callers can fall back to a | |||
| 12443 | // context registry when parsing into the node. | |||
| 12444 | CustomElementRegistryState state = CustomElementRegistryState::Global; | |||
| 12445 | if (aNode->IsElement()) { | |||
| 12446 | state = aNode->AsElement()->GetCustomElementRegistryState(); | |||
| 12447 | } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) { | |||
| 12448 | state = shadowRoot->GetCustomElementRegistryState(); | |||
| 12449 | } else if (aNode->IsDocument()) { | |||
| 12450 | if (!aNode->AsDocument()->HasScopedCustomElementRegistry()) { | |||
| 12451 | // 4. Return null (reported as Nothing(): inherit the global registry). | |||
| 12452 | return Nothing(); | |||
| 12453 | } | |||
| 12454 | state = CustomElementRegistryState::Scoped; | |||
| 12455 | } else { | |||
| 12456 | // 4. Return null. | |||
| 12457 | return Nothing(); | |||
| 12458 | } | |||
| 12459 | if (state == CustomElementRegistryState::Global) { | |||
| 12460 | return Nothing(); | |||
| 12461 | } | |||
| 12462 | RefPtr<CustomElementRegistry> registry; | |||
| 12463 | if (aNode->IsElement()) { | |||
| 12464 | registry = aNode->AsElement()->GetCustomElementRegistry(); | |||
| 12465 | } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) { | |||
| 12466 | registry = shadowRoot->GetCustomElementRegistry(); | |||
| 12467 | } else { | |||
| 12468 | registry = aNode->AsDocument()->GetCustomElementRegistry(); | |||
| 12469 | } | |||
| 12470 | return Some(std::move(registry)); | |||
| 12471 | } | |||
| 12472 | ||||
| 12473 | /* https://html.spec.whatwg.org/#look-up-a-custom-element-definition */ | |||
| 12474 | CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition( | |||
| 12475 | DocumentOrShadowRoot* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID, | |||
| 12476 | nsAtom* aTypeAtom) { | |||
| 12477 | // 2. If namespace is not the HTML namespace, then return null. | |||
| 12478 | if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) { | |||
| 12479 | return nullptr; | |||
| 12480 | } | |||
| 12481 | ||||
| 12482 | // 1. If registry is null, then return null. | |||
| 12483 | // TODO(keithamus): re-order for Scoped Registries | |||
| 12484 | RefPtr<CustomElementRegistry> registry = aDoc->GetCustomElementRegistry(); | |||
| 12485 | if (!registry) { | |||
| 12486 | return nullptr; | |||
| 12487 | } | |||
| 12488 | ||||
| 12489 | // XXX: Steps 3-5 performed by | |||
| 12490 | // CustomElementRegistry::LookupCustomElementDefinition: | |||
| 12491 | // 3. If registry's custom element definition set contains an item with name | |||
| 12492 | // and local name both equal to localName, then return that item. | |||
| 12493 | // 4. If registry's custom element definition set contains an item with name | |||
| 12494 | // equal to is and local name equal to localName, then return that item. | |||
| 12495 | // 5. Return null. | |||
| 12496 | return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID, | |||
| 12497 | aTypeAtom); | |||
| 12498 | } | |||
| 12499 | ||||
| 12500 | /* static */ | |||
| 12501 | void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement, | |||
| 12502 | nsAtom* aTypeName) { | |||
| 12503 | MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { MOZ_CrashSequence(__null, 12503); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12504 | ||||
| 12505 | CustomElementRegistry* registry = aElement->GetCustomElementRegistry(); | |||
| 12506 | if (registry) { | |||
| 12507 | registry->RegisterCallbackUpgradeElement(aElement, aTypeName); | |||
| 12508 | } | |||
| 12509 | } | |||
| 12510 | ||||
| 12511 | /* static */ | |||
| 12512 | void nsContentUtils::RegisterUnresolvedElement(Element* aElement, | |||
| 12513 | nsAtom* aTypeName) { | |||
| 12514 | MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12514); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { MOZ_CrashSequence(__null, 12514); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12515 | ||||
| 12516 | CustomElementRegistry* registry = aElement->GetCustomElementRegistry(); | |||
| 12517 | if (registry) { | |||
| 12518 | registry->RegisterUnresolvedElement(aElement, aTypeName); | |||
| 12519 | } | |||
| 12520 | } | |||
| 12521 | ||||
| 12522 | /* static */ | |||
| 12523 | void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) { | |||
| 12524 | MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { MOZ_CrashSequence(__null, 12524); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12525 | ||||
| 12526 | nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType(); | |||
| 12527 | CustomElementRegistry* registry = aElement->GetCustomElementRegistry(); | |||
| 12528 | if (registry) { | |||
| 12529 | registry->UnregisterUnresolvedElement(aElement, typeAtom); | |||
| 12530 | } | |||
| 12531 | } | |||
| 12532 | ||||
| 12533 | /* static */ | |||
| 12534 | void nsContentUtils::EnqueueUpgradeReaction( | |||
| 12535 | Element* aElement, CustomElementDefinition* aDefinition) { | |||
| 12536 | MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElement)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { MOZ_CrashSequence(__null, 12536); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12537 | ||||
| 12538 | Document* doc = aElement->OwnerDoc(); | |||
| 12539 | ||||
| 12540 | // No DocGroup means no custom element reactions stack. | |||
| 12541 | if (!doc->GetDocGroup()) { | |||
| 12542 | return; | |||
| 12543 | } | |||
| 12544 | ||||
| 12545 | CustomElementReactionsStack* stack = | |||
| 12546 | doc->GetDocGroup()->CustomElementReactionsStack(); | |||
| 12547 | stack->EnqueueUpgradeReaction(aElement, aDefinition); | |||
| 12548 | } | |||
| 12549 | ||||
| 12550 | /* static */ | |||
| 12551 | void nsContentUtils::EnqueueLifecycleCallback( | |||
| 12552 | ElementCallbackType aType, Element* aCustomElement, | |||
| 12553 | const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) { | |||
| 12554 | // No DocGroup means no custom element reactions stack. | |||
| 12555 | if (!aCustomElement->OwnerDoc()->GetDocGroup()) { | |||
| 12556 | return; | |||
| 12557 | } | |||
| 12558 | ||||
| 12559 | CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs, | |||
| 12560 | aDefinition); | |||
| 12561 | } | |||
| 12562 | ||||
| 12563 | /* static */ | |||
| 12564 | CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue( | |||
| 12565 | const Nullable<OwningFileOrUSVStringOrFormData>& aState) { | |||
| 12566 | if (aState.IsNull()) { | |||
| 12567 | return void_t{}; | |||
| 12568 | } | |||
| 12569 | const auto& state = aState.Value(); | |||
| 12570 | if (state.IsFile()) { | |||
| 12571 | RefPtr<BlobImpl> impl = state.GetAsFile()->Impl(); | |||
| 12572 | return {std::move(impl)}; | |||
| 12573 | } | |||
| 12574 | if (state.IsUSVString()) { | |||
| 12575 | return state.GetAsUSVString(); | |||
| 12576 | } | |||
| 12577 | return state.GetAsFormData()->ConvertToCustomElementFormValue(); | |||
| 12578 | } | |||
| 12579 | ||||
| 12580 | /* static */ | |||
| 12581 | Nullable<OwningFileOrUSVStringOrFormData> | |||
| 12582 | nsContentUtils::ExtractFormAssociatedCustomElementValue( | |||
| 12583 | nsIGlobalObject* aGlobal, | |||
| 12584 | const mozilla::dom::CustomElementFormValue& aCEValue) { | |||
| 12585 | MOZ_ASSERT(aGlobal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aGlobal", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")" ); do { MOZ_CrashSequence(__null, 12585); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12586 | ||||
| 12587 | OwningFileOrUSVStringOrFormData value; | |||
| 12588 | switch (aCEValue.type()) { | |||
| 12589 | case CustomElementFormValue::TBlobImpl: { | |||
| 12590 | RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl()); | |||
| 12591 | if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12591)) { | |||
| 12592 | return {}; | |||
| 12593 | } | |||
| 12594 | value.SetAsFile() = file; | |||
| 12595 | } break; | |||
| 12596 | ||||
| 12597 | case CustomElementFormValue::TnsString: | |||
| 12598 | value.SetAsUSVString() = aCEValue.get_nsString(); | |||
| 12599 | break; | |||
| 12600 | ||||
| 12601 | case CustomElementFormValue::TArrayOfFormDataTuple: { | |||
| 12602 | const auto& array = aCEValue.get_ArrayOfFormDataTuple(); | |||
| 12603 | auto formData = MakeRefPtr<FormData>(); | |||
| 12604 | ||||
| 12605 | for (auto i = 0ul; i < array.Length(); ++i) { | |||
| 12606 | const auto& item = array.ElementAt(i); | |||
| 12607 | switch (item.value().type()) { | |||
| 12608 | case IPCFormDataValue::TnsString: | |||
| 12609 | formData->AddNameValuePair(item.name(), | |||
| 12610 | item.value().get_nsString()); | |||
| 12611 | break; | |||
| 12612 | ||||
| 12613 | case IPCFormDataValue::TBlobImpl: { | |||
| 12614 | auto blobImpl = item.value().get_BlobImpl(); | |||
| 12615 | RefPtr<Blob> blob = Blob::Create(aGlobal, blobImpl); | |||
| 12616 | formData->AddNameBlobPair(item.name(), blob); | |||
| 12617 | } break; | |||
| 12618 | ||||
| 12619 | default: | |||
| 12620 | continue; | |||
| 12621 | } | |||
| 12622 | } | |||
| 12623 | ||||
| 12624 | value.SetAsFormData() = formData; | |||
| 12625 | } break; | |||
| 12626 | case CustomElementFormValue::Tvoid_t: | |||
| 12627 | return {}; | |||
| 12628 | default: | |||
| 12629 | NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12629); | |||
| 12630 | return {}; | |||
| 12631 | } | |||
| 12632 | return value; | |||
| 12633 | } | |||
| 12634 | ||||
| 12635 | /* static */ | |||
| 12636 | void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo( | |||
| 12637 | Document* aDocument, nsTArray<nsIContent*>& aElements) { | |||
| 12638 | MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDocument)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"); do { MOZ_CrashSequence(__null, 12638); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12639 | #ifdef DEBUG1 | |||
| 12640 | size_t oldLength = aElements.Length(); | |||
| 12641 | #endif | |||
| 12642 | ||||
| 12643 | if (PresShell* presShell = aDocument->GetPresShell()) { | |||
| 12644 | if (ScrollContainerFrame* rootScrollContainerFrame = | |||
| 12645 | presShell->GetRootScrollContainerFrame()) { | |||
| 12646 | rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0); | |||
| 12647 | } | |||
| 12648 | if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) { | |||
| 12649 | canvasFrame->AppendAnonymousContentTo(aElements, 0); | |||
| 12650 | } | |||
| 12651 | } | |||
| 12652 | ||||
| 12653 | if (auto* el = aDocument->GetCustomContentContainer()) { | |||
| 12654 | aElements.AppendElement(el); | |||
| 12655 | } | |||
| 12656 | ||||
| 12657 | #ifdef DEBUG1 | |||
| 12658 | for (size_t i = oldLength; i < aElements.Length(); i++) { | |||
| 12659 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" " (" "Someone here has lied, or missed to flag the node" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12661); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 12660 | aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent),do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" " (" "Someone here has lied, or missed to flag the node" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12661); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
| 12661 | "Someone here has lied, or missed to flag the node")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" " (" "Someone here has lied, or missed to flag the node" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12661); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 12662 | } | |||
| 12663 | #endif | |||
| 12664 | } | |||
| 12665 | ||||
| 12666 | static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame, | |||
| 12667 | nsTArray<nsIContent*>& aKids, | |||
| 12668 | uint32_t aFlags) { | |||
| 12669 | if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) { | |||
| 12670 | ac->AppendAnonymousContentTo(aKids, aFlags); | |||
| 12671 | } | |||
| 12672 | } | |||
| 12673 | ||||
| 12674 | /* static */ | |||
| 12675 | void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent, | |||
| 12676 | nsTArray<nsIContent*>& aKids, | |||
| 12677 | uint32_t aFlags) { | |||
| 12678 | if (aContent->MayHaveAnonymousChildren()) { | |||
| 12679 | if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) { | |||
| 12680 | // NAC created by the element's primary frame. | |||
| 12681 | AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags); | |||
| 12682 | ||||
| 12683 | // NAC created by any other non-primary frames for the element. | |||
| 12684 | AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes; | |||
| 12685 | primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes); | |||
| 12686 | for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) { | |||
| 12687 | MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == aContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(box.mAnonBoxFrame->GetContent() == aContent)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(box.mAnonBoxFrame->GetContent() == aContent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("box.mAnonBoxFrame->GetContent() == aContent" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12687); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent" ")"); do { MOZ_CrashSequence(__null, 12687); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12688 | AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids, | |||
| 12689 | aFlags); | |||
| 12690 | } | |||
| 12691 | } | |||
| 12692 | ||||
| 12693 | // View transition pseudos. | |||
| 12694 | if (aContent->IsRootElement()) { | |||
| 12695 | if (auto* vt = aContent->OwnerDoc()->GetActiveViewTransition()) { | |||
| 12696 | if (auto* root = vt->GetSnapshotContainingBlock()) { | |||
| 12697 | aKids.AppendElement(root); | |||
| 12698 | } | |||
| 12699 | } | |||
| 12700 | } | |||
| 12701 | ||||
| 12702 | // Get manually created NAC (editor resize handles, etc.). | |||
| 12703 | if (auto nac = static_cast<ManualNACArray*>( | |||
| 12704 | aContent->GetProperty(nsGkAtoms::manualNACProperty))) { | |||
| 12705 | aKids.AppendElements(*nac); | |||
| 12706 | } | |||
| 12707 | } | |||
| 12708 | ||||
| 12709 | // The root scroll frame is not the primary frame of the root element. | |||
| 12710 | // Detect and handle this case. | |||
| 12711 | if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) && | |||
| 12712 | aContent->IsRootElement()) { | |||
| 12713 | AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids); | |||
| 12714 | } | |||
| 12715 | } | |||
| 12716 | ||||
| 12717 | bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI, | |||
| 12718 | nsIPrincipal* aDefaultTriggeringPrincipal, | |||
| 12719 | CORSMode aCORSMode) { | |||
| 12720 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; | |||
| 12721 | QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal, | |||
| 12722 | getter_AddRefs(triggeringPrincipal)); | |||
| 12723 | MOZ_ASSERT(triggeringPrincipal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(triggeringPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(triggeringPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("triggeringPrincipal" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12723); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "triggeringPrincipal" ")"); do { MOZ_CrashSequence (__null, 12723); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 12724 | ||||
| 12725 | Document* doc = aLoadingNode->OwnerDoc(); | |||
| 12726 | return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc); | |||
| 12727 | } | |||
| 12728 | ||||
| 12729 | bool nsContentUtils::IsImageAvailable(nsIURI* aURI, | |||
| 12730 | nsIPrincipal* aTriggeringPrincipal, | |||
| 12731 | CORSMode aCORSMode, Document* aDoc) { | |||
| 12732 | imgLoader* imgLoader = GetImgLoaderForDocument(aDoc); | |||
| 12733 | return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode, | |||
| 12734 | aDoc); | |||
| 12735 | } | |||
| 12736 | ||||
| 12737 | /* static */ | |||
| 12738 | bool nsContentUtils::QueryTriggeringPrincipal( | |||
| 12739 | nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal, | |||
| 12740 | nsIPrincipal** aTriggeringPrincipal) { | |||
| 12741 | MOZ_ASSERT(aLoadingNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLoadingNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLoadingNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadingNode", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode" ")"); do { MOZ_CrashSequence(__null, 12741); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 12742 | MOZ_ASSERT(aTriggeringPrincipal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTriggeringPrincipal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTriggeringPrincipal))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("aTriggeringPrincipal" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12742); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aTriggeringPrincipal" ")"); do { MOZ_CrashSequence (__null, 12742); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 12743 | ||||
| 12744 | bool result = false; | |||
| 12745 | nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal; | |||
| 12746 | if (!loadingPrincipal) { | |||
| 12747 | loadingPrincipal = aLoadingNode->NodePrincipal(); | |||
| 12748 | } | |||
| 12749 | ||||
| 12750 | // If aLoadingNode is content, bail out early. | |||
| 12751 | if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) { | |||
| 12752 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
| 12753 | return result; | |||
| 12754 | } | |||
| 12755 | ||||
| 12756 | nsAutoString loadingStr; | |||
| 12757 | if (aLoadingNode->IsElement()) { | |||
| 12758 | aLoadingNode->AsElement()->GetAttr( | |||
| 12759 | kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr); | |||
| 12760 | } | |||
| 12761 | ||||
| 12762 | // Fall back if 'triggeringprincipal' isn't specified, | |||
| 12763 | if (loadingStr.IsEmpty()) { | |||
| 12764 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
| 12765 | return result; | |||
| 12766 | } | |||
| 12767 | ||||
| 12768 | nsCString binary; | |||
| 12769 | nsCOMPtr<nsIPrincipal> serializedPrin = | |||
| 12770 | BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr)); | |||
| 12771 | if (serializedPrin) { | |||
| 12772 | result = true; | |||
| 12773 | serializedPrin.forget(aTriggeringPrincipal); | |||
| 12774 | } | |||
| 12775 | ||||
| 12776 | if (!result) { | |||
| 12777 | // Fallback if the deserialization is failed. | |||
| 12778 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
| 12779 | } | |||
| 12780 | ||||
| 12781 | return result; | |||
| 12782 | } | |||
| 12783 | ||||
| 12784 | /* static */ | |||
| 12785 | void nsContentUtils::GetContentPolicyTypeForUIImageLoading( | |||
| 12786 | nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal, | |||
| 12787 | nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) { | |||
| 12788 | MOZ_ASSERT(aRequestContextID)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aRequestContextID)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aRequestContextID))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequestContextID" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12788); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aRequestContextID" ")"); do { MOZ_CrashSequence (__null, 12788); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 12789 | ||||
| 12790 | bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal); | |||
| 12791 | if (result) { | |||
| 12792 | // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for | |||
| 12793 | // indicating it's a favicon loading. | |||
| 12794 | aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; | |||
| 12795 | ||||
| 12796 | nsAutoString requestContextID; | |||
| 12797 | if (aLoadingNode->IsElement()) { | |||
| 12798 | aLoadingNode->AsElement()->GetAttr( | |||
| 12799 | kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID); | |||
| 12800 | } | |||
| 12801 | nsresult rv; | |||
| 12802 | int64_t val = requestContextID.ToInteger64(&rv); | |||
| 12803 | *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0; | |||
| 12804 | } else { | |||
| 12805 | aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; | |||
| 12806 | } | |||
| 12807 | } | |||
| 12808 | ||||
| 12809 | /* static */ | |||
| 12810 | nsresult nsContentUtils::CreateJSValueFromSequenceOfObject( | |||
| 12811 | JSContext* aCx, const Sequence<JSObject*>& aTransfer, | |||
| 12812 | JS::MutableHandle<JS::Value> aValue) { | |||
| 12813 | if (aTransfer.IsEmpty()) { | |||
| 12814 | return NS_OK; | |||
| 12815 | } | |||
| 12816 | ||||
| 12817 | JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length())); | |||
| 12818 | if (!array) { | |||
| 12819 | return NS_ERROR_OUT_OF_MEMORY; | |||
| 12820 | } | |||
| 12821 | ||||
| 12822 | for (uint32_t i = 0; i < aTransfer.Length(); ++i) { | |||
| 12823 | JS::Rooted<JSObject*> object(aCx, aTransfer[i]); | |||
| 12824 | if (!object) { | |||
| 12825 | continue; | |||
| 12826 | } | |||
| 12827 | ||||
| 12828 | if (NS_WARN_IF(NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE ), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12829) | |||
| 12829 | !JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE))NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE ), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12829)) { | |||
| 12830 | return NS_ERROR_OUT_OF_MEMORY; | |||
| 12831 | } | |||
| 12832 | } | |||
| 12833 | ||||
| 12834 | aValue.setObject(*array); | |||
| 12835 | return NS_OK; | |||
| 12836 | } | |||
| 12837 | ||||
| 12838 | /* static */ | |||
| 12839 | void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal, | |||
| 12840 | JS::Handle<JS::Value> aValue, | |||
| 12841 | const StructuredSerializeOptions& aOptions, | |||
| 12842 | JS::MutableHandle<JS::Value> aRetval, | |||
| 12843 | ErrorResult& aError) { | |||
| 12844 | JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue()); | |||
| 12845 | aError = nsContentUtils::CreateJSValueFromSequenceOfObject( | |||
| 12846 | aCx, aOptions.mTransfer, &transferArray); | |||
| 12847 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12847)) { | |||
| 12848 | return; | |||
| 12849 | } | |||
| 12850 | ||||
| 12851 | JS::CloneDataPolicy clonePolicy; | |||
| 12852 | // We are definitely staying in the same agent cluster. | |||
| 12853 | clonePolicy.allowIntraClusterClonableSharedObjects(); | |||
| 12854 | if (aGlobal->IsSharedMemoryAllowed()) { | |||
| 12855 | clonePolicy.allowSharedMemoryObjects(); | |||
| 12856 | } | |||
| 12857 | ||||
| 12858 | // 2.7.10 Structured cloning API | |||
| 12859 | // Step 1: Let serialized be | |||
| 12860 | // ? StructuredSerializeWithTransfer(value, options["transfer"]) | |||
| 12861 | StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, | |||
| 12862 | StructuredCloneHolder::TransferringSupported, | |||
| 12863 | JS::StructuredCloneScope::SameProcess); | |||
| 12864 | holder.Write(aCx, aValue, transferArray, clonePolicy, aError); | |||
| 12865 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12865)) { | |||
| 12866 | return; | |||
| 12867 | } | |||
| 12868 | ||||
| 12869 | // Step 2: Let deserializeRecord be | |||
| 12870 | // ? StructuredDeserializeWithTransfer(serialized, this's relevant realm). | |||
| 12871 | JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject()); | |||
| 12872 | holder.Read(aCx, aRetval, clonePolicy, aError); | |||
| 12873 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 12873)) { | |||
| 12874 | return; | |||
| 12875 | } | |||
| 12876 | ||||
| 12877 | // Step 3: Return deserializeRecord.[[Deserialized]]. | |||
| 12878 | // (discarding deserializeRecord.[[TransferredValues]]) | |||
| 12879 | nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts(); | |||
| 12880 | (void)ports; | |||
| 12881 | } | |||
| 12882 | ||||
| 12883 | /* static */ | |||
| 12884 | bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) { | |||
| 12885 | nsCOMPtr<nsIPrincipal> principal; | |||
| 12886 | RefPtr<Element> targetElement = | |||
| 12887 | Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget); | |||
| 12888 | nsCOMPtr<nsIBrowser> targetBrowser; | |||
| 12889 | if (targetElement) { | |||
| 12890 | targetBrowser = targetElement->AsBrowser(); | |||
| 12891 | } | |||
| 12892 | bool isRemoteBrowser = false; | |||
| 12893 | if (targetBrowser) { | |||
| 12894 | targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser); | |||
| 12895 | } | |||
| 12896 | ||||
| 12897 | if (isRemoteBrowser) { | |||
| 12898 | targetBrowser->GetContentPrincipal(getter_AddRefs(principal)); | |||
| 12899 | return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns) | |||
| 12900 | : false; | |||
| 12901 | } | |||
| 12902 | ||||
| 12903 | if (targetElement) { | |||
| 12904 | Document* doc = targetElement->GetUncomposedDoc(); | |||
| 12905 | if (doc) { | |||
| 12906 | RefPtr<WindowContext> wc = doc->GetWindowContext(); | |||
| 12907 | if (wc) { | |||
| 12908 | return wc->TopWindowContext()->GetShortcutsPermission() == | |||
| 12909 | nsIPermissionManager::DENY_ACTION; | |||
| 12910 | } | |||
| 12911 | } | |||
| 12912 | } | |||
| 12913 | ||||
| 12914 | return false; | |||
| 12915 | } | |||
| 12916 | ||||
| 12917 | /** | |||
| 12918 | * Checks whether the given type is a supported document type for | |||
| 12919 | * loading within the nsObjectLoadingContent specified by aContent. | |||
| 12920 | * | |||
| 12921 | * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType. | |||
| 12922 | * NOTE Does not take content policy or capabilities into account | |||
| 12923 | */ | |||
| 12924 | static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) { | |||
| 12925 | nsCOMPtr<nsIWebNavigationInfo> info( | |||
| 12926 | do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1")); | |||
| 12927 | if (!info) { | |||
| 12928 | return false; | |||
| 12929 | } | |||
| 12930 | ||||
| 12931 | uint32_t supported; | |||
| 12932 | nsresult rv = info->IsTypeSupported(aMimeType, &supported); | |||
| 12933 | ||||
| 12934 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 12935 | return false; | |||
| 12936 | } | |||
| 12937 | ||||
| 12938 | if (supported != nsIWebNavigationInfo::UNSUPPORTED) { | |||
| 12939 | return true; | |||
| 12940 | } | |||
| 12941 | ||||
| 12942 | // Try a stream converter | |||
| 12943 | // NOTE: We treat any type we can convert from as a supported type. If a | |||
| 12944 | // type is not actually supported, the URI loader will detect that and | |||
| 12945 | // return an error, and we'll fallback. | |||
| 12946 | nsCOMPtr<nsIStreamConverterService> convServ = | |||
| 12947 | do_GetService("@mozilla.org/streamConverters;1"); | |||
| 12948 | bool canConvert = false; | |||
| 12949 | if (convServ) { | |||
| 12950 | rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert); | |||
| 12951 | } | |||
| 12952 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert; | |||
| 12953 | } | |||
| 12954 | ||||
| 12955 | /* static */ | |||
| 12956 | uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType( | |||
| 12957 | const nsCString& aMIMEType, bool aIsSandboxed) { | |||
| 12958 | if (aMIMEType.IsEmpty()) { | |||
| 12959 | return nsIObjectLoadingContent::TYPE_FALLBACK; | |||
| 12960 | } | |||
| 12961 | ||||
| 12962 | if (imgLoader::SupportImageWithMimeType(aMIMEType)) { | |||
| 12963 | return nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
| 12964 | } | |||
| 12965 | ||||
| 12966 | // Faking support of the PDF content as a document for EMBED tags when the | |||
| 12967 | // internal PDF viewer or the embedded PDF fallback is enabled. | |||
| 12968 | if (aMIMEType.LowerCaseEqualsLiteral(APPLICATION_PDF"application/pdf") && | |||
| 12969 | (IsPDFJSEnabled() || StaticPrefs::pdfjs_embedFallback())) { | |||
| 12970 | // Sandboxed iframes are just never allowed to display plugins. In the | |||
| 12971 | // modern world, this just means "application/pdf". | |||
| 12972 | return aIsSandboxed ? nsIObjectLoadingContent::TYPE_FALLBACK | |||
| 12973 | : nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
| 12974 | } | |||
| 12975 | ||||
| 12976 | if (HtmlObjectContentSupportsDocument(aMIMEType)) { | |||
| 12977 | return nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
| 12978 | } | |||
| 12979 | ||||
| 12980 | return nsIObjectLoadingContent::TYPE_FALLBACK; | |||
| 12981 | } | |||
| 12982 | ||||
| 12983 | /* static */ | |||
| 12984 | bool nsContentUtils::IsLocalRefURL(const nsAString& aString) { | |||
| 12985 | return !aString.IsEmpty() && aString[0] == '#'; | |||
| 12986 | } | |||
| 12987 | ||||
| 12988 | // We use only 53 bits for the ID so that it can be converted to and from a JS | |||
| 12989 | // value without loss of precision. The upper bits of the ID hold the process | |||
| 12990 | // ID. The lower bits identify the object itself. | |||
| 12991 | static constexpr uint64_t kIdTotalBits = 53; | |||
| 12992 | static constexpr uint64_t kIdProcessBits = 22; | |||
| 12993 | static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits; | |||
| 12994 | ||||
| 12995 | /* static */ | |||
| 12996 | uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) { | |||
| 12997 | uint64_t processId = 0; | |||
| 12998 | if (XRE_IsContentProcess()) { | |||
| 12999 | ContentChild* cc = ContentChild::GetSingleton(); | |||
| 13000 | processId = cc->GetID(); | |||
| 13001 | } | |||
| 13002 | ||||
| 13003 | MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kIdProcessBits))do { static_assert( mozilla::detail::AssertionConditionType< decltype(processId < (uint64_t(1) << kIdProcessBits) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(processId < (uint64_t(1) << kIdProcessBits) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "processId < (uint64_t(1) << kIdProcessBits)", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13003); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)" ")"); do { MOZ_CrashSequence(__null, 13003); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13004 | uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1); | |||
| 13005 | ||||
| 13006 | uint64_t id = aId; | |||
| 13007 | MOZ_RELEASE_ASSERT(id < (uint64_t(1) << kIdBits))do { static_assert( mozilla::detail::AssertionConditionType< decltype(id < (uint64_t(1) << kIdBits))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(id < (uint64_t(1) << kIdBits)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("id < (uint64_t(1) << kIdBits)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13007); AnnotateMozCrashReason ("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)" ")"); do { MOZ_CrashSequence(__null, 13007); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13008 | uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1); | |||
| 13009 | ||||
| 13010 | return (processBits << kIdBits) | bits; | |||
| 13011 | } | |||
| 13012 | ||||
| 13013 | /* static */ | |||
| 13014 | std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId( | |||
| 13015 | uint64_t aId) { | |||
| 13016 | return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)}; | |||
| 13017 | } | |||
| 13018 | ||||
| 13019 | // Next process-local Tab ID. | |||
| 13020 | static uint64_t gNextTabId = 0; | |||
| 13021 | ||||
| 13022 | /* static */ | |||
| 13023 | uint64_t nsContentUtils::GenerateTabId() { | |||
| 13024 | return GenerateProcessSpecificId(++gNextTabId); | |||
| 13025 | } | |||
| 13026 | ||||
| 13027 | // Next process-local Browser ID. | |||
| 13028 | static uint64_t gNextBrowserId = 0; | |||
| 13029 | ||||
| 13030 | /* static */ | |||
| 13031 | uint64_t nsContentUtils::GenerateBrowserId() { | |||
| 13032 | return GenerateProcessSpecificId(++gNextBrowserId); | |||
| 13033 | } | |||
| 13034 | ||||
| 13035 | // Next process-local Browsing Context ID. | |||
| 13036 | static uint64_t gNextBrowsingContextId = 0; | |||
| 13037 | ||||
| 13038 | /* static */ | |||
| 13039 | uint64_t nsContentUtils::GenerateBrowsingContextId() { | |||
| 13040 | return GenerateProcessSpecificId(++gNextBrowsingContextId); | |||
| 13041 | } | |||
| 13042 | ||||
| 13043 | // Next process-local Window ID. | |||
| 13044 | static uint64_t gNextWindowId = 0; | |||
| 13045 | ||||
| 13046 | /* static */ | |||
| 13047 | uint64_t nsContentUtils::GenerateWindowId() { | |||
| 13048 | return GenerateProcessSpecificId(++gNextWindowId); | |||
| 13049 | } | |||
| 13050 | ||||
| 13051 | // Next process-local load. | |||
| 13052 | static Atomic<uint64_t> gNextLoadIdentifier(0); | |||
| 13053 | ||||
| 13054 | /* static */ | |||
| 13055 | uint64_t nsContentUtils::GenerateLoadIdentifier() { | |||
| 13056 | return GenerateProcessSpecificId(++gNextLoadIdentifier); | |||
| 13057 | } | |||
| 13058 | ||||
| 13059 | /* static */ | |||
| 13060 | bool nsContentUtils::GetUserIsInteracting() { | |||
| 13061 | return UserInteractionObserver::sUserActive; | |||
| 13062 | } | |||
| 13063 | ||||
| 13064 | /* static */ | |||
| 13065 | bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, | |||
| 13066 | nsACString& aResult) { | |||
| 13067 | nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult); | |||
| 13068 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
| 13069 | rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult); | |||
| 13070 | } | |||
| 13071 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))); | |||
| 13072 | } | |||
| 13073 | ||||
| 13074 | /* static */ | |||
| 13075 | bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) { | |||
| 13076 | if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) == | |||
| 13077 | mozilla::dom::PBrowser::PBrowserStart) { | |||
| 13078 | switch (aMsg.type()) { | |||
| 13079 | case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID: | |||
| 13080 | case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID: | |||
| 13081 | case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID: | |||
| 13082 | case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID: | |||
| 13083 | case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID: | |||
| 13084 | case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID: | |||
| 13085 | case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID: | |||
| 13086 | case mozilla::dom::PBrowser::Msg_RealDragEvent__ID: | |||
| 13087 | case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID: | |||
| 13088 | return true; | |||
| 13089 | } | |||
| 13090 | } | |||
| 13091 | return false; | |||
| 13092 | } | |||
| 13093 | ||||
| 13094 | /* static */ | |||
| 13095 | bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) { | |||
| 13096 | if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) == | |||
| 13097 | mozilla::dom::PBrowser::PBrowserStart) { | |||
| 13098 | switch (aMsg.type()) { | |||
| 13099 | case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID: | |||
| 13100 | case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID: | |||
| 13101 | case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID: | |||
| 13102 | case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID: | |||
| 13103 | case mozilla::dom::PBrowser::Msg_RealDragEvent__ID: | |||
| 13104 | return true; | |||
| 13105 | } | |||
| 13106 | } | |||
| 13107 | return false; | |||
| 13108 | } | |||
| 13109 | ||||
| 13110 | static const char* kUserInteractionInactive = "user-interaction-inactive"; | |||
| 13111 | static const char* kUserInteractionActive = "user-interaction-active"; | |||
| 13112 | ||||
| 13113 | void nsContentUtils::UserInteractionObserver::Init() { | |||
| 13114 | // Listen for the observer messages from EventStateManager which are telling | |||
| 13115 | // us whether or not the user is interacting. | |||
| 13116 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); | |||
| 13117 | obs->AddObserver(this, kUserInteractionInactive, false); | |||
| 13118 | obs->AddObserver(this, kUserInteractionActive, false); | |||
| 13119 | ||||
| 13120 | // We can't register ourselves as an annotator yet, as the | |||
| 13121 | // BackgroundHangMonitor hasn't started yet. It will have started by the | |||
| 13122 | // time we have the chance to spin the event loop. | |||
| 13123 | RefPtr<UserInteractionObserver> self = this; | |||
| 13124 | NS_DispatchToMainThread(NS_NewRunnableFunction( | |||
| 13125 | "nsContentUtils::UserInteractionObserver::Init", | |||
| 13126 | [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); })); | |||
| 13127 | } | |||
| 13128 | ||||
| 13129 | void nsContentUtils::UserInteractionObserver::Shutdown() { | |||
| 13130 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); | |||
| 13131 | if (obs) { | |||
| 13132 | obs->RemoveObserver(this, kUserInteractionInactive); | |||
| 13133 | obs->RemoveObserver(this, kUserInteractionActive); | |||
| 13134 | } | |||
| 13135 | ||||
| 13136 | BackgroundHangMonitor::UnregisterAnnotator(*this); | |||
| 13137 | } | |||
| 13138 | ||||
| 13139 | /** | |||
| 13140 | * NB: This function is always called by the BackgroundHangMonitor thread. | |||
| 13141 | * Plan accordingly | |||
| 13142 | */ | |||
| 13143 | void nsContentUtils::UserInteractionObserver::AnnotateHang( | |||
| 13144 | BackgroundHangAnnotations& aAnnotations) { | |||
| 13145 | // NOTE: Only annotate the hang report if the user is known to be interacting. | |||
| 13146 | if (sUserActive) { | |||
| 13147 | aAnnotations.AddAnnotation(u"UserInteracting"_ns, true); | |||
| 13148 | } | |||
| 13149 | } | |||
| 13150 | ||||
| 13151 | NS_IMETHODIMPnsresult | |||
| 13152 | nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject, | |||
| 13153 | const char* aTopic, | |||
| 13154 | const char16_t* aData) { | |||
| 13155 | if (!strcmp(aTopic, kUserInteractionInactive)) { | |||
| 13156 | if (sUserActive && XRE_IsParentProcess()) { | |||
| 13157 | glean::RecordPowerMetrics(); | |||
| 13158 | } | |||
| 13159 | sUserActive = false; | |||
| 13160 | } else if (!strcmp(aTopic, kUserInteractionActive)) { | |||
| 13161 | if (!sUserActive && XRE_IsParentProcess()) { | |||
| 13162 | glean::RecordPowerMetrics(); | |||
| 13163 | ||||
| 13164 | nsCOMPtr<nsIUserIdleServiceInternal> idleService = | |||
| 13165 | do_GetService("@mozilla.org/widget/useridleservice;1"); | |||
| 13166 | if (idleService) { | |||
| 13167 | idleService->ResetIdleTimeOut(0); | |||
| 13168 | } | |||
| 13169 | } | |||
| 13170 | ||||
| 13171 | sUserActive = true; | |||
| 13172 | } else { | |||
| 13173 | NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification" , nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13173); | |||
| 13174 | } | |||
| 13175 | return NS_OK; | |||
| 13176 | } | |||
| 13177 | ||||
| 13178 | Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false); | |||
| 13179 | NS_IMPL_ISUPPORTS(nsContentUtils::UserInteractionObserver, nsIObserver)MozExternalRefCountType nsContentUtils::UserInteractionObserver ::AddRef(void) { static_assert(!std::is_destructible_v<nsContentUtils ::UserInteractionObserver>, "Reference-counted class " "nsContentUtils::UserInteractionObserver" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 13179 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsContentUtils::UserInteractionObserver" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("nsContentUtils::UserInteractionObserver" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"nsContentUtils::UserInteractionObserver\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 13179); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsContentUtils::UserInteractionObserver" " not thread-safe" ); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ( "nsContentUtils::UserInteractionObserver"), (uint32_t)(sizeof (*this))); return count; } MozExternalRefCountType nsContentUtils ::UserInteractionObserver::Release(void) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 13179 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsContentUtils::UserInteractionObserver" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("nsContentUtils::UserInteractionObserver" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"nsContentUtils::UserInteractionObserver\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 13179); __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsContentUtils::UserInteractionObserver" " not thread-safe" ); const char* const nametmp = "nsContentUtils::UserInteractionObserver" ; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), ( nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult nsContentUtils::UserInteractionObserver ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13179); MOZ_PretendNoReturn (); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert (1 > 0, "Need more arguments to NS_INTERFACE_TABLE"); static const QITableEntry table[] = { {&mozilla::detail::kImplementedIID <nsContentUtils::UserInteractionObserver, nsIObserver>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((nsContentUtils::UserInteractionObserver*)0x1000)) - reinterpret_cast <char*>((nsContentUtils::UserInteractionObserver*)0x1000 ))}, {&mozilla::detail::kImplementedIID<nsContentUtils ::UserInteractionObserver, nsISupports>, int32_t(reinterpret_cast <char*>(static_cast<nsISupports*>( static_cast< nsIObserver*>((nsContentUtils::UserInteractionObserver*)0x1000 ))) - reinterpret_cast<char*>((nsContentUtils::UserInteractionObserver *)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table ) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } | |||
| 13180 | ||||
| 13181 | /* static */ | |||
| 13182 | bool nsContentUtils::IsSpecialName(const nsAString& aName) { | |||
| 13183 | return aName.LowerCaseEqualsLiteral("_blank") || | |||
| 13184 | aName.LowerCaseEqualsLiteral("_top") || | |||
| 13185 | aName.LowerCaseEqualsLiteral("_parent") || | |||
| 13186 | aName.LowerCaseEqualsLiteral("_self"); | |||
| 13187 | } | |||
| 13188 | ||||
| 13189 | /* static */ | |||
| 13190 | bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) { | |||
| 13191 | return !aName.IsEmpty() && !IsSpecialName(aName); | |||
| 13192 | } | |||
| 13193 | ||||
| 13194 | // Unfortunately, we can't unwrap an IDL object using only a concrete type. | |||
| 13195 | // We need to calculate type data based on the IDL typename. Which means | |||
| 13196 | // wrapping our templated function in a macro. | |||
| 13197 | #define EXTRACT_EXN_VALUES(T, ...) \ | |||
| 13198 | ExtractExceptionValuesImpl<mozilla::dom::prototypes::id::T, \ | |||
| 13199 | T##_Binding::NativeType, T>(__VA_ARGS__) \ | |||
| 13200 | .isOk() | |||
| 13201 | ||||
| 13202 | template <prototypes::ID PrototypeID, class NativeType, typename T> | |||
| 13203 | static Result<Ok, nsresult> ExtractExceptionValuesImpl( | |||
| 13204 | JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename, | |||
| 13205 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
| 13206 | AssertStaticUnwrapOK<PrototypeID>(); | |||
| 13207 | RefPtr<T> exn; | |||
| 13208 | MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult ((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr ))); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0 ))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult .unwrap(); }); | |||
| 13209 | ||||
| 13210 | if (nsCOMPtr<nsIStackFrame> location = exn->GetLocation()) { | |||
| 13211 | location->GetFilename(aCx, aFilename); | |||
| 13212 | *aLineOut = location->GetLineNumber(aCx); | |||
| 13213 | *aColumnOut = location->GetColumnNumber(aCx); | |||
| 13214 | } else { | |||
| 13215 | aFilename.Truncate(); | |||
| 13216 | *aLineOut = 0; | |||
| 13217 | *aColumnOut = 0; | |||
| 13218 | } | |||
| 13219 | ||||
| 13220 | exn->GetName(aMessageOut); | |||
| 13221 | aMessageOut.AppendLiteral(": "); | |||
| 13222 | ||||
| 13223 | nsAutoString message; | |||
| 13224 | exn->GetMessageMoz(message); | |||
| 13225 | aMessageOut.Append(message); | |||
| 13226 | return Ok(); | |||
| 13227 | } | |||
| 13228 | ||||
| 13229 | /* static */ | |||
| 13230 | bool nsContentUtils::ExtractExceptionValues( | |||
| 13231 | JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename, | |||
| 13232 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
| 13233 | return EXTRACT_EXN_VALUES(DOMException, aCx, aObj, aFilename, aLineOut, | |||
| 13234 | aColumnOut, aMessageOut) || | |||
| 13235 | EXTRACT_EXN_VALUES(Exception, aCx, aObj, aFilename, aLineOut, | |||
| 13236 | aColumnOut, aMessageOut); | |||
| 13237 | } | |||
| 13238 | ||||
| 13239 | /* static */ | |||
| 13240 | void nsContentUtils::ExtractErrorValues( | |||
| 13241 | JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut, | |||
| 13242 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
| 13243 | MOZ_ASSERT(aLineOut)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aLineOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aLineOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLineOut", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")" ); do { MOZ_CrashSequence(__null, 13243); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 13244 | MOZ_ASSERT(aColumnOut)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aColumnOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aColumnOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aColumnOut", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut" ")"); do { MOZ_CrashSequence(__null, 13244); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13245 | ||||
| 13246 | if (aValue.isObject()) { | |||
| 13247 | JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); | |||
| 13248 | ||||
| 13249 | // Try to process as an Error object. Use the file/line/column values | |||
| 13250 | // from the Error as they will be more specific to the root cause of | |||
| 13251 | // the problem. | |||
| 13252 | JS::BorrowedErrorReport err(aCx); | |||
| 13253 | if (JS_ErrorFromException(aCx, obj, err)) { | |||
| 13254 | // Use xpc to extract the error message only. We don't actually send | |||
| 13255 | // this report anywhere. | |||
| 13256 | RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport(); | |||
| 13257 | report->Init(err.get(), | |||
| 13258 | nullptr, // toString result | |||
| 13259 | false, // chrome | |||
| 13260 | 0); // window ID | |||
| 13261 | ||||
| 13262 | if (!report->mFileName.IsEmpty()) { | |||
| 13263 | aSourceSpecOut = report->mFileName; | |||
| 13264 | *aLineOut = report->mLineNumber; | |||
| 13265 | *aColumnOut = report->mColumn; | |||
| 13266 | } | |||
| 13267 | aMessageOut.Assign(report->mErrorMsg); | |||
| 13268 | } | |||
| 13269 | ||||
| 13270 | // Next, try to unwrap the rejection value as a (DOM)Exception. | |||
| 13271 | else if (ExtractExceptionValues(aCx, obj, aSourceSpecOut, aLineOut, | |||
| 13272 | aColumnOut, aMessageOut)) { | |||
| 13273 | return; | |||
| 13274 | } | |||
| 13275 | } | |||
| 13276 | ||||
| 13277 | // If we could not unwrap a specific error type, then perform default safe | |||
| 13278 | // string conversions on primitives. Objects will result in "[Object]" | |||
| 13279 | // unfortunately. | |||
| 13280 | if (aMessageOut.IsEmpty()) { | |||
| 13281 | nsAutoJSString jsString; | |||
| 13282 | if (jsString.init(aCx, aValue)) { | |||
| 13283 | aMessageOut = jsString; | |||
| 13284 | } else { | |||
| 13285 | JS_ClearPendingException(aCx); | |||
| 13286 | } | |||
| 13287 | } | |||
| 13288 | } | |||
| 13289 | ||||
| 13290 | #undef EXTRACT_EXN_VALUES | |||
| 13291 | ||||
| 13292 | /* static */ | |||
| 13293 | bool nsContentUtils::ContentIsLink(nsIContent* aContent) { | |||
| 13294 | if (!aContent || !aContent->IsElement()) { | |||
| 13295 | return false; | |||
| 13296 | } | |||
| 13297 | ||||
| 13298 | if (aContent->IsHTMLElement(nsGkAtoms::a)) { | |||
| 13299 | return true; | |||
| 13300 | } | |||
| 13301 | ||||
| 13302 | return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type, | |||
| 13303 | nsGkAtoms::simple, eCaseMatters); | |||
| 13304 | } | |||
| 13305 | ||||
| 13306 | /* static */ | |||
| 13307 | already_AddRefed<ContentFrameMessageManager> | |||
| 13308 | nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) { | |||
| 13309 | RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom); | |||
| 13310 | if (!frameLoaderOwner) { | |||
| 13311 | return nullptr; | |||
| 13312 | } | |||
| 13313 | ||||
| 13314 | RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); | |||
| 13315 | if (!frameLoader) { | |||
| 13316 | return nullptr; | |||
| 13317 | } | |||
| 13318 | ||||
| 13319 | RefPtr<ContentFrameMessageManager> manager = | |||
| 13320 | frameLoader->GetBrowserChildMessageManager(); | |||
| 13321 | return manager.forget(); | |||
| 13322 | } | |||
| 13323 | ||||
| 13324 | /* static */ | |||
| 13325 | Document* nsContentUtils::TryGetDocumentFromWindowGlobal(nsISupports* aFrom) { | |||
| 13326 | nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aFrom); | |||
| 13327 | MOZ_DIAGNOSTIC_ASSERT(window, "Expected a window global")do { static_assert( mozilla::detail::AssertionConditionType< decltype(window)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("window" " (" "Expected a window global" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13327 ); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "window" ") (" "Expected a window global" ")"); do { MOZ_CrashSequence (__null, 13327); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13328 | if (!window) { | |||
| 13329 | return nullptr; | |||
| 13330 | } | |||
| 13331 | return window->GetExtantDoc(); | |||
| 13332 | } | |||
| 13333 | ||||
| 13334 | /* static */ | |||
| 13335 | uint32_t nsContentUtils::InnerOrOuterWindowCreated() { | |||
| 13336 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13336); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 13336); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13337 | ++sInnerOrOuterWindowCount; | |||
| 13338 | return ++sInnerOrOuterWindowSerialCounter; | |||
| 13339 | } | |||
| 13340 | ||||
| 13341 | /* static */ | |||
| 13342 | void nsContentUtils::InnerOrOuterWindowDestroyed() { | |||
| 13343 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13343); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 13343); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13344 | MOZ_ASSERT(sInnerOrOuterWindowCount > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sInnerOrOuterWindowCount > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sInnerOrOuterWindowCount > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sInnerOrOuterWindowCount > 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0" ")"); do { MOZ_CrashSequence(__null, 13344); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13345 | --sInnerOrOuterWindowCount; | |||
| 13346 | } | |||
| 13347 | ||||
| 13348 | static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) { | |||
| 13349 | nsAString* result = static_cast<nsAString*>(aData); | |||
| 13350 | return result->Append(aBuf, aLen, fallible); | |||
| 13351 | } | |||
| 13352 | ||||
| 13353 | /* static */ | |||
| 13354 | bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue, | |||
| 13355 | nsAString& aOutStr, JSONBehavior aBehavior) { | |||
| 13356 | MOZ_ASSERT(aCx)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aCx)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aCx))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aCx", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13356); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")"); do { MOZ_CrashSequence(__null, 13356); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 13357 | switch (aBehavior) { | |||
| 13358 | case UndefinedIsNullStringLiteral: { | |||
| 13359 | aOutStr.Truncate(); | |||
| 13360 | JS::Rooted<JS::Value> value(aCx, aValue); | |||
| 13361 | return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue, | |||
| 13362 | JSONCreator, &aOutStr); | |||
| 13363 | } | |||
| 13364 | case UndefinedIsVoidString: { | |||
| 13365 | aOutStr.SetIsVoid(true); | |||
| 13366 | return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator, | |||
| 13367 | &aOutStr); | |||
| 13368 | } | |||
| 13369 | default: | |||
| 13370 | MOZ_ASSERT_UNREACHABLE("Invalid value for aBehavior")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")" ); do { MOZ_CrashSequence(__null, 13370); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 13371 | return false; | |||
| 13372 | } | |||
| 13373 | } | |||
| 13374 | ||||
| 13375 | /* static */ | |||
| 13376 | bool nsContentUtils:: | |||
| 13377 | HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint( | |||
| 13378 | Document* aDocument) { | |||
| 13379 | MOZ_ASSERT(XRE_IsContentProcess(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()" " (" "This function only makes sense in content processes" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13380); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes" ")"); do { MOZ_CrashSequence(__null, 13380); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 13380 | "This function only makes sense in content processes")do { static_assert( mozilla::detail::AssertionConditionType< decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()" " (" "This function only makes sense in content processes" ")" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13380); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes" ")"); do { MOZ_CrashSequence(__null, 13380); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13381 | ||||
| 13382 | if (aDocument && !aDocument->IsLoadedAsData()) { | |||
| 13383 | if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) { | |||
| 13384 | MOZ_ASSERT(!presContext->IsChrome(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!presContext->IsChrome())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!presContext->IsChrome()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!presContext->IsChrome()" " (" "Should never have a chrome PresContext in a content process" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13385 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()" ") (" "Should never have a chrome PresContext in a content process" ")"); do { MOZ_CrashSequence(__null, 13385); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 13385 | "Should never have a chrome PresContext in a content process")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!presContext->IsChrome())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!presContext->IsChrome()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!presContext->IsChrome()" " (" "Should never have a chrome PresContext in a content process" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13385 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()" ") (" "Should never have a chrome PresContext in a content process" ")"); do { MOZ_CrashSequence(__null, 13385); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13386 | ||||
| 13387 | return !presContext->GetInProcessRootContentDocumentPresContext() | |||
| 13388 | ->HadFirstContentfulPaint() && | |||
| 13389 | nsThreadManager::MainThreadHasPendingHighPriorityEvents(); | |||
| 13390 | } | |||
| 13391 | } | |||
| 13392 | return false; | |||
| 13393 | } | |||
| 13394 | ||||
| 13395 | static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) { | |||
| 13396 | NS_ENSURE_TRUE(aGlobal, nullptr)do { if ((__builtin_expect(!!(!(aGlobal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aGlobal" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13396); return nullptr; } } while (false); | |||
| 13397 | ||||
| 13398 | if (auto* window = aGlobal->GetAsInnerWindow()) { | |||
| 13399 | return nsGlobalWindowInner::Cast(window); | |||
| 13400 | } | |||
| 13401 | ||||
| 13402 | // When Extensions run content scripts inside a sandbox, it uses | |||
| 13403 | // sandboxPrototype to make them appear as though they're running in the | |||
| 13404 | // scope of the page. So when a content script invokes postMessage, it expects | |||
| 13405 | // the |source| of the received message to be the window set as the | |||
| 13406 | // sandboxPrototype. This used to work incidentally for unrelated reasons, but | |||
| 13407 | // now we need to do some special handling to support it. | |||
| 13408 | JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject()); | |||
| 13409 | NS_ENSURE_TRUE(scope, nullptr)do { if ((__builtin_expect(!!(!(scope)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scope" ") failed", nullptr , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13409); return nullptr; } } while (false); | |||
| 13410 | ||||
| 13411 | if (xpc::IsSandbox(scope)) { | |||
| 13412 | AutoJSAPI jsapi; | |||
| 13413 | MOZ_ALWAYS_TRUE(jsapi.Init(scope))do { if ((__builtin_expect(!!(jsapi.Init(scope)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "jsapi.Init(scope)" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13413); AnnotateMozCrashReason ("MOZ_CRASH(" "jsapi.Init(scope)" ")"); do { MOZ_CrashSequence (__null, 13413); __attribute__((nomerge)) ::abort(); } while ( false); } while (false); } } while (false); | |||
| 13414 | JSContext* cx = jsapi.cx(); | |||
| 13415 | // Our current Realm on aCx is the sandbox. Using that for unwrapping | |||
| 13416 | // makes sense: if the sandbox can unwrap the window, we can use it. | |||
| 13417 | return xpc::SandboxWindowOrNull(scope, cx); | |||
| 13418 | } | |||
| 13419 | ||||
| 13420 | // The calling window must be holding a reference, so we can return a weak | |||
| 13421 | // pointer. | |||
| 13422 | return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow()); | |||
| 13423 | } | |||
| 13424 | ||||
| 13425 | /* static */ | |||
| 13426 | nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() { | |||
| 13427 | return GetInnerWindowForGlobal(GetIncumbentGlobal()); | |||
| 13428 | } | |||
| 13429 | ||||
| 13430 | /* static */ | |||
| 13431 | nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() { | |||
| 13432 | return GetInnerWindowForGlobal(GetEntryGlobal()); | |||
| 13433 | } | |||
| 13434 | ||||
| 13435 | /* static */ | |||
| 13436 | bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) { | |||
| 13437 | MOZ_ASSERT(aPrefName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPrefName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPrefName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aPrefName", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName" ")"); do { MOZ_CrashSequence(__null, 13437); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13438 | ||||
| 13439 | nsAutoCString list; | |||
| 13440 | Preferences::GetCString(aPrefName, list); | |||
| 13441 | ToLowerCase(list); | |||
| 13442 | return IsURIInList(aURI, list); | |||
| 13443 | } | |||
| 13444 | ||||
| 13445 | /* static */ | |||
| 13446 | bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) { | |||
| 13447 | #ifdef DEBUG1 | |||
| 13448 | nsAutoCString listLowerCase(aList); | |||
| 13449 | ToLowerCase(listLowerCase); | |||
| 13450 | MOZ_ASSERT(listLowerCase.Equals(aList),do { static_assert( mozilla::detail::AssertionConditionType< decltype(listLowerCase.Equals(aList))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(listLowerCase.Equals(aList)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("listLowerCase.Equals(aList)" " (" "The aList argument should be lower-case" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)" ") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence (__null, 13451); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
| 13451 | "The aList argument should be lower-case")do { static_assert( mozilla::detail::AssertionConditionType< decltype(listLowerCase.Equals(aList))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(listLowerCase.Equals(aList)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("listLowerCase.Equals(aList)" " (" "The aList argument should be lower-case" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)" ") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence (__null, 13451); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13452 | #endif | |||
| 13453 | ||||
| 13454 | if (!aURI) { | |||
| 13455 | return false; | |||
| 13456 | } | |||
| 13457 | ||||
| 13458 | if (aList.IsEmpty()) { | |||
| 13459 | return false; | |||
| 13460 | } | |||
| 13461 | ||||
| 13462 | nsAutoCString scheme; | |||
| 13463 | aURI->GetScheme(scheme); | |||
| 13464 | if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) { | |||
| 13465 | return false; | |||
| 13466 | } | |||
| 13467 | ||||
| 13468 | // The list is comma separated domain list. Each item may start with "*.". | |||
| 13469 | // If starts with "*.", it matches any sub-domains. | |||
| 13470 | ||||
| 13471 | nsCCharSeparatedTokenizer tokenizer(aList, ','); | |||
| 13472 | while (tokenizer.hasMoreTokens()) { | |||
| 13473 | const nsCString token(tokenizer.nextToken()); | |||
| 13474 | ||||
| 13475 | nsAutoCString host; | |||
| 13476 | aURI->GetHost(host); | |||
| 13477 | if (host.IsEmpty()) { | |||
| 13478 | return false; | |||
| 13479 | } | |||
| 13480 | ToLowerCase(host); | |||
| 13481 | ||||
| 13482 | for (;;) { | |||
| 13483 | int32_t index = token.Find(host); | |||
| 13484 | if (index >= 0 && | |||
| 13485 | static_cast<uint32_t>(index) + host.Length() <= token.Length()) { | |||
| 13486 | // If we found a full match, return true. | |||
| 13487 | size_t indexAfterHost = index + host.Length(); | |||
| 13488 | if (index == 0 && indexAfterHost == token.Length()) { | |||
| 13489 | return true; | |||
| 13490 | } | |||
| 13491 | // If next character is '/', we need to check the path too. | |||
| 13492 | // We assume the path in the list means "/foo" + "*". | |||
| 13493 | if (token[indexAfterHost] == '/') { | |||
| 13494 | nsDependentCSubstring pathInList( | |||
| 13495 | token, indexAfterHost, | |||
| 13496 | static_cast<nsDependentCSubstring::size_type>(-1)); | |||
| 13497 | nsAutoCString filePath; | |||
| 13498 | aURI->GetFilePath(filePath); | |||
| 13499 | ToLowerCase(filePath); | |||
| 13500 | if (StringBeginsWith(filePath, pathInList) && | |||
| 13501 | (filePath.Length() == pathInList.Length() || | |||
| 13502 | pathInList.EqualsLiteral("/") || | |||
| 13503 | filePath[pathInList.Length() - 1] == '/' || | |||
| 13504 | filePath[pathInList.Length() - 1] == '?' || | |||
| 13505 | filePath[pathInList.Length() - 1] == '#')) { | |||
| 13506 | return true; | |||
| 13507 | } | |||
| 13508 | } | |||
| 13509 | } | |||
| 13510 | int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0; | |||
| 13511 | int32_t startIndexOfNextLevel = | |||
| 13512 | host.Find(".", startIndexOfCurrentLevel + 1); | |||
| 13513 | if (startIndexOfNextLevel <= 0) { | |||
| 13514 | break; | |||
| 13515 | } | |||
| 13516 | host.ReplaceLiteral(0, startIndexOfNextLevel, "*"); | |||
| 13517 | } | |||
| 13518 | } | |||
| 13519 | ||||
| 13520 | return false; | |||
| 13521 | } | |||
| 13522 | ||||
| 13523 | /* static */ | |||
| 13524 | LayoutDeviceIntMargin nsContentUtils::GetWindowSafeAreaInsets( | |||
| 13525 | nsIScreen* aScreen, const LayoutDeviceIntMargin& aSafeAreaInsets, | |||
| 13526 | const LayoutDeviceIntRect& aWindowRect) { | |||
| 13527 | // This calculates safe area insets of window from screen rectangle, window | |||
| 13528 | // rectangle and safe area insets of screen. | |||
| 13529 | // | |||
| 13530 | // +----------------------------------------+ <-- screen | |||
| 13531 | // | +-------------------------------+ <------- window | |||
| 13532 | // | | window's safe area inset top) | | | |||
| 13533 | // +--+-------------------------------+--+ | | |||
| 13534 | // | | | |<------ safe area rectangle of | |||
| 13535 | // | | | | | screen | |||
| 13536 | // +--+-------------------------------+--+ | | |||
| 13537 | // | |window's safe area inset bottom| | | |||
| 13538 | // | +-------------------------------+ | | |||
| 13539 | // +----------------------------------------+ | |||
| 13540 | // | |||
| 13541 | LayoutDeviceIntMargin windowSafeAreaInsets; | |||
| 13542 | if (windowSafeAreaInsets == aSafeAreaInsets) { | |||
| 13543 | // no safe area insets. | |||
| 13544 | return windowSafeAreaInsets; | |||
| 13545 | } | |||
| 13546 | ||||
| 13547 | const LayoutDeviceIntRect screenRect = aScreen->GetRect(); | |||
| 13548 | LayoutDeviceIntRect safeAreaRect = screenRect; | |||
| 13549 | safeAreaRect.Deflate(aSafeAreaInsets); | |||
| 13550 | ||||
| 13551 | // FIXME(bug 1754323): This can trigger because the screen rect is not | |||
| 13552 | // orientation-aware. | |||
| 13553 | // MOZ_ASSERT(screenRect.Contains(windowRect), | |||
| 13554 | // "Screen doesn't contain window rect? Something seems off"); | |||
| 13555 | ||||
| 13556 | // window's rect of safe area | |||
| 13557 | safeAreaRect = safeAreaRect.Intersect(aWindowRect); | |||
| 13558 | ||||
| 13559 | windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y; | |||
| 13560 | windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x; | |||
| 13561 | windowSafeAreaInsets.right = | |||
| 13562 | aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width); | |||
| 13563 | windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height - | |||
| 13564 | (safeAreaRect.y + safeAreaRect.height); | |||
| 13565 | ||||
| 13566 | windowSafeAreaInsets.EnsureAtLeast(LayoutDeviceIntMargin()); | |||
| 13567 | // This shouldn't be needed, but it wallpapers orientation issues, see bug | |||
| 13568 | // 1754323. | |||
| 13569 | windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets); | |||
| 13570 | ||||
| 13571 | return windowSafeAreaInsets; | |||
| 13572 | } | |||
| 13573 | ||||
| 13574 | /* static */ | |||
| 13575 | nsContentUtils::SubresourceCacheValidationInfo | |||
| 13576 | nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest, | |||
| 13577 | nsIURI* aURI) { | |||
| 13578 | SubresourceCacheValidationInfo info; | |||
| 13579 | if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) { | |||
| 13580 | uint32_t value = 0; | |||
| 13581 | if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime (&value))), 1)))) { | |||
| 13582 | // NOTE: If the cache doesn't expire, the value should be | |||
| 13583 | // nsICacheEntry::NO_EXPIRATION_TIME. | |||
| 13584 | info.mExpirationTime.emplace(CacheExpirationTime::ExpireAt(value)); | |||
| 13585 | } | |||
| 13586 | } | |||
| 13587 | ||||
| 13588 | // Determine whether the cache entry must be revalidated when we try to use | |||
| 13589 | // it. Currently, only HTTP specifies this information... | |||
| 13590 | if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) { | |||
| 13591 | (void)httpChannel->IsNoStoreResponse(&info.mMustRevalidate); | |||
| 13592 | ||||
| 13593 | if (!info.mMustRevalidate) { | |||
| 13594 | (void)httpChannel->IsNoCacheResponse(&info.mMustRevalidate); | |||
| 13595 | } | |||
| 13596 | ||||
| 13597 | if (!info.mMustRevalidate) { | |||
| 13598 | nsAutoCString vary; | |||
| 13599 | (void)httpChannel->GetResponseHeader("vary"_ns, vary); | |||
| 13600 | info.mMustRevalidate = [&] { | |||
| 13601 | for (const nsACString& token : | |||
| 13602 | nsCCharSeparatedTokenizer(vary, ',').ToRange()) { | |||
| 13603 | if (token.EqualsLiteral("*")) { | |||
| 13604 | return true; | |||
| 13605 | } | |||
| 13606 | if (token.EqualsIgnoreCase("cookie")) { | |||
| 13607 | return true; | |||
| 13608 | } | |||
| 13609 | } | |||
| 13610 | return false; | |||
| 13611 | }(); | |||
| 13612 | } | |||
| 13613 | } | |||
| 13614 | ||||
| 13615 | // data: URIs are safe to cache across documents under any circumstance, so we | |||
| 13616 | // special-case them here even though the channel itself doesn't have any | |||
| 13617 | // caching policy. Same for chrome:// uris. | |||
| 13618 | // | |||
| 13619 | // TODO(emilio): Figure out which other schemes that don't have caching | |||
| 13620 | // policies are safe to cache. Blobs should be... | |||
| 13621 | const bool knownCacheable = [&] { | |||
| 13622 | if (!aURI) { | |||
| 13623 | return false; | |||
| 13624 | } | |||
| 13625 | if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") || | |||
| 13626 | aURI->SchemeIs("moz-newtab-wallpaper") || | |||
| 13627 | aURI->SchemeIs("moz-extension")) { | |||
| 13628 | return true; | |||
| 13629 | } | |||
| 13630 | if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) { | |||
| 13631 | return !StaticPrefs::nglayout_debug_disable_xul_cache(); | |||
| 13632 | } | |||
| 13633 | return false; | |||
| 13634 | }(); | |||
| 13635 | ||||
| 13636 | if (knownCacheable) { | |||
| 13637 | MOZ_ASSERT(!info.mExpirationTime)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!info.mExpirationTime)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!info.mExpirationTime))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!info.mExpirationTime" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13637); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!info.mExpirationTime" ")"); do { MOZ_CrashSequence (__null, 13637); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13638 | MOZ_ASSERT(!info.mMustRevalidate)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!info.mMustRevalidate)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!info.mMustRevalidate))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!info.mMustRevalidate" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13638); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!info.mMustRevalidate" ")"); do { MOZ_CrashSequence (__null, 13638); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13639 | info.mExpirationTime = Some(CacheExpirationTime::Never()); | |||
| 13640 | } | |||
| 13641 | ||||
| 13642 | return info; | |||
| 13643 | } | |||
| 13644 | ||||
| 13645 | CacheExpirationTime nsContentUtils::GetSubresourceCacheExpirationTime( | |||
| 13646 | nsIRequest* aRequest, nsIURI* aURI) { | |||
| 13647 | auto info = GetSubresourceCacheValidationInfo(aRequest, aURI); | |||
| 13648 | ||||
| 13649 | // For now, we never cache entries that we have to revalidate, or whose | |||
| 13650 | // channel don't support caching. | |||
| 13651 | if (info.mMustRevalidate || !info.mExpirationTime) { | |||
| 13652 | return CacheExpirationTime::AlreadyExpired(); | |||
| 13653 | } | |||
| 13654 | return *info.mExpirationTime; | |||
| 13655 | } | |||
| 13656 | ||||
| 13657 | /* static */ | |||
| 13658 | bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) { | |||
| 13659 | RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup(); | |||
| 13660 | if (!lg) { | |||
| 13661 | return false; | |||
| 13662 | } | |||
| 13663 | nsLoadFlags flags; | |||
| 13664 | if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags (&flags))), 0)))) { | |||
| 13665 | return false; | |||
| 13666 | } | |||
| 13667 | return flags & (nsIRequest::LOAD_BYPASS_CACHE | | |||
| 13668 | nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE); | |||
| 13669 | } | |||
| 13670 | ||||
| 13671 | nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) { | |||
| 13672 | nsCString spec; | |||
| 13673 | if (aURL) { | |||
| 13674 | aURL->GetSpec(spec); | |||
| 13675 | spec.Truncate(std::min(aMaxLen, spec.Length())); | |||
| 13676 | } | |||
| 13677 | return spec; | |||
| 13678 | } | |||
| 13679 | ||||
| 13680 | /* static */ | |||
| 13681 | nsresult nsContentUtils::AnonymizeId(nsAString& aId, | |||
| 13682 | const nsACString& aOriginKey, | |||
| 13683 | OriginFormat aFormat) { | |||
| 13684 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13684); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence (__null, 13684); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13685 | ||||
| 13686 | nsresult rv; | |||
| 13687 | nsCString rawKey; | |||
| 13688 | if (aFormat == OriginFormat::Base64) { | |||
| 13689 | rv = Base64Decode(aOriginKey, rawKey); | |||
| 13690 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13690); return rv; } } while (false); | |||
| 13691 | } else { | |||
| 13692 | rawKey = aOriginKey; | |||
| 13693 | } | |||
| 13694 | ||||
| 13695 | HMAC hmac; | |||
| 13696 | rv = hmac.Begin( | |||
| 13697 | SEC_OID_SHA256, | |||
| 13698 | Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length())); | |||
| 13699 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13699); return rv; } } while (false); | |||
| 13700 | ||||
| 13701 | NS_ConvertUTF16toUTF8 id(aId); | |||
| 13702 | rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length()); | |||
| 13703 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13703); return rv; } } while (false); | |||
| 13704 | ||||
| 13705 | nsTArray<uint8_t> macBytes; | |||
| 13706 | rv = hmac.End(macBytes); | |||
| 13707 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13707); return rv; } } while (false); | |||
| 13708 | ||||
| 13709 | nsCString macBase64; | |||
| 13710 | rv = Base64Encode( | |||
| 13711 | nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()), | |||
| 13712 | macBytes.Length()), | |||
| 13713 | macBase64); | |||
| 13714 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13714); return rv; } } while (false); | |||
| 13715 | ||||
| 13716 | CopyUTF8toUTF16(macBase64, aId); | |||
| 13717 | return NS_OK; | |||
| 13718 | } | |||
| 13719 | ||||
| 13720 | void nsContentUtils::RequestGeckoTaskBurst() { | |||
| 13721 | nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{0x2d96b3df, 0xc051, 0x11d1, {0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a , 0x28, 0xc9}}); | |||
| 13722 | if (appShell) { | |||
| 13723 | appShell->GeckoTaskBurst(); | |||
| 13724 | } | |||
| 13725 | } | |||
| 13726 | ||||
| 13727 | nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) { | |||
| 13728 | for (nsIContent* content = aContent; content; | |||
| 13729 | content = content->GetFlattenedTreeParent()) { | |||
| 13730 | if (nsContentUtils::IsDraggableLink(content)) { | |||
| 13731 | return content; | |||
| 13732 | } | |||
| 13733 | } | |||
| 13734 | return nullptr; | |||
| 13735 | } | |||
| 13736 | ||||
| 13737 | template <TreeKind aKind> | |||
| 13738 | MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) { | |||
| 13739 | if constexpr (aKind == TreeKind::DOM) { | |||
| 13740 | return aNode->GetParentNode(); | |||
| 13741 | } else if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 13742 | return aNode->GetParentOrShadowHostNode(); | |||
| 13743 | } else if constexpr (aKind == TreeKind::FlatForSelection) { | |||
| 13744 | return aNode->GetFlattenedTreeParentNodeForSelection(); | |||
| 13745 | } else if constexpr (aKind == TreeKind::Flat) { | |||
| 13746 | return aNode->GetFlattenedTreeParentNode(); | |||
| 13747 | } else { | |||
| 13748 | MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Handle the new TreeKind value")do { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Handle the new TreeKind value" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Handle the new TreeKind value" ")" ); do { MOZ_CrashSequence(__null, 13748); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); __builtin_unreachable (); } while (false); | |||
| 13749 | } | |||
| 13750 | } | |||
| 13751 | ||||
| 13752 | template <TreeKind aKind> | |||
| 13753 | Maybe<int32_t> nsContentUtils::GetIndexInParent( | |||
| 13754 | const nsINode* aParent, const nsIContent* aPossibleChild) { | |||
| 13755 | const Maybe<uint32_t> idx = [&]() { | |||
| 13756 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 13757 | return aParent->ComputeIndexOf(aPossibleChild); | |||
| 13758 | } else { | |||
| 13759 | return aParent->ComputeIndexOf<aKind>(aPossibleChild); | |||
| 13760 | } | |||
| 13761 | }(); | |||
| 13762 | if (idx) { | |||
| 13763 | return idx.map([](auto i) { return AssertedCast<int32_t>(i); }); | |||
| 13764 | } | |||
| 13765 | ||||
| 13766 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 13767 | if (const auto* sr = ShadowRoot::FromNode(aPossibleChild)) { | |||
| 13768 | return sr->GetHost() == aParent ? Some(-1) : Nothing(); | |||
| 13769 | } | |||
| 13770 | } | |||
| 13771 | ||||
| 13772 | // Handle pseudo-element and anonymous node ordering: | |||
| 13773 | // ::backdrop -> ::marker -> ::checkmark -> ::before -> regular siblings -> | |||
| 13774 | // all other NAC -> ::after -> ::picker-icon | |||
| 13775 | // This matches the order of AllChildrenIterator. | |||
| 13776 | if (NS_WARN_IF(!aPossibleChild->IsRootOfNativeAnonymousSubtree())NS_warn_if_impl(!aPossibleChild->IsRootOfNativeAnonymousSubtree (), "!aPossibleChild->IsRootOfNativeAnonymousSubtree()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13776)) { | |||
| 13777 | // If aNode is mid unbind, we can reach this. | |||
| 13778 | return Nothing(); | |||
| 13779 | } | |||
| 13780 | ||||
| 13781 | if (NS_WARN_IF(aPossibleChild->GetParentNode() != aParent)NS_warn_if_impl(aPossibleChild->GetParentNode() != aParent , "aPossibleChild->GetParentNode() != aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13781)) { | |||
| 13782 | // We can't be an anon child if not correctly parented. | |||
| 13783 | return Nothing(); | |||
| 13784 | } | |||
| 13785 | ||||
| 13786 | if (aPossibleChild->IsGeneratedContentContainerForBackdrop()) { | |||
| 13787 | return Some(-5); | |||
| 13788 | } | |||
| 13789 | ||||
| 13790 | if (aPossibleChild->IsGeneratedContentContainerForMarker()) { | |||
| 13791 | return Some(-4); | |||
| 13792 | } | |||
| 13793 | ||||
| 13794 | if (aPossibleChild->IsGeneratedContentContainerForCheckmark()) { | |||
| 13795 | return Some(-3); | |||
| 13796 | } | |||
| 13797 | ||||
| 13798 | if (aPossibleChild->IsGeneratedContentContainerForBefore()) { | |||
| 13799 | return Some(-2); | |||
| 13800 | } | |||
| 13801 | ||||
| 13802 | AutoTArray<nsIContent*, 8> anonKids; | |||
| 13803 | ||||
| 13804 | // Regular children are indexed via ComputeIndexOf (range [0, GetChildCount)) | |||
| 13805 | // for both DOM and ShadowIncludingDOM above; only the flat tree indexes them | |||
| 13806 | // via the flattened iterator. Trailing NAC must be based at the matching | |||
| 13807 | // count so it lands after the regular children in the same index space. | |||
| 13808 | const int32_t siblingCount = [&]() -> uint32_t { | |||
| 13809 | if constexpr (aKind == TreeKind::ShadowIncludingDOM) { | |||
| 13810 | return aParent->GetChildCount(); | |||
| 13811 | } else { | |||
| 13812 | return aParent->GetChildCount<aKind>(); | |||
| 13813 | } | |||
| 13814 | }(); | |||
| 13815 | ||||
| 13816 | MOZ_ASSERT(aParent->MayHaveAnonymousChildren())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent->MayHaveAnonymousChildren())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aParent->MayHaveAnonymousChildren()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParent->MayHaveAnonymousChildren()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13816); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aParent->MayHaveAnonymousChildren()" ")" ); do { MOZ_CrashSequence(__null, 13816); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
| 13817 | MOZ_ASSERT(aParent->IsContent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParent->IsContent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParent->IsContent()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aParent->IsContent()" , "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13817); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aParent->IsContent()" ")"); do { MOZ_CrashSequence (__null, 13817); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13818 | nsContentUtils::AppendNativeAnonymousChildren(aParent->AsContent(), anonKids, | |||
| 13819 | nsIContent::eAllChildren); | |||
| 13820 | ||||
| 13821 | if (aPossibleChild->IsGeneratedContentContainerForAfter()) { | |||
| 13822 | return Some(int32_t(siblingCount + anonKids.Length())); | |||
| 13823 | } | |||
| 13824 | ||||
| 13825 | if (aPossibleChild->IsGeneratedContentContainerForPickerIcon()) { | |||
| 13826 | return Some(int32_t(siblingCount + anonKids.Length()) + 1); | |||
| 13827 | } | |||
| 13828 | ||||
| 13829 | auto index = anonKids.IndexOf(aPossibleChild); | |||
| 13830 | if (index == decltype(anonKids)::NoIndex) { | |||
| 13831 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13833 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")"); do { MOZ_CrashSequence(__null, 13833); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 13832 | "Missing parent -> child link somehow?"do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13833 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")"); do { MOZ_CrashSequence(__null, 13833); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
| 13833 | "Potentially unstable ordering")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13833 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Missing parent -> child link somehow?" "Potentially unstable ordering" ")"); do { MOZ_CrashSequence(__null, 13833); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13834 | return Nothing(); | |||
| 13835 | } | |||
| 13836 | return Some(siblingCount + int32_t(index)); | |||
| 13837 | } | |||
| 13838 | ||||
| 13839 | template <TreeKind aTreeKind> | |||
| 13840 | int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1, | |||
| 13841 | const nsINode* aNode2, | |||
| 13842 | const nsINode* aCommonAncestor, | |||
| 13843 | NodeIndexCache* aCache) { | |||
| 13844 | MOZ_ASSERT(aNode1, "aNode1 must not be null")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode1)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode1" " (" "aNode1 must not be null" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13844 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") (" "aNode1 must not be null" ")"); do { MOZ_CrashSequence(__null, 13844); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13845 | MOZ_ASSERT(aNode2, "aNode2 must not be null")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode2)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode2" " (" "aNode2 must not be null" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13845 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") (" "aNode2 must not be null" ")"); do { MOZ_CrashSequence(__null, 13845); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13846 | ||||
| 13847 | if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13847)) { | |||
| 13848 | return 0; | |||
| 13849 | } | |||
| 13850 | ||||
| 13851 | // TODO: Maybe handle flat tree too or other common cases? | |||
| 13852 | if constexpr (aTreeKind == TreeKind::DOM || | |||
| 13853 | aTreeKind == TreeKind::ShadowIncludingDOM) { | |||
| 13854 | if (aNode1->GetNextSibling() == aNode2) { | |||
| 13855 | return -1; | |||
| 13856 | } | |||
| 13857 | if (aNode1->GetPreviousSibling() == aNode2) { | |||
| 13858 | return 1; | |||
| 13859 | } | |||
| 13860 | } | |||
| 13861 | ||||
| 13862 | AutoTArray<const nsINode*, 32> node1Ancestors; | |||
| 13863 | const nsINode* c1; | |||
| 13864 | for (c1 = aNode1; c1 && c1 != aCommonAncestor; | |||
| 13865 | c1 = GetParent<aTreeKind>(c1)) { | |||
| 13866 | node1Ancestors.AppendElement(c1); | |||
| 13867 | } | |||
| 13868 | if (!c1 && aCommonAncestor) { | |||
| 13869 | // So, it turns out aCommonAncestor was not an ancestor of c1. Oops. | |||
| 13870 | // Never mind. We can continue as if aCommonAncestor was null. | |||
| 13871 | aCommonAncestor = nullptr; | |||
| 13872 | } | |||
| 13873 | ||||
| 13874 | AutoTArray<const nsINode*, 32> node2Ancestors; | |||
| 13875 | const nsINode* c2; | |||
| 13876 | for (c2 = aNode2; c2 && c2 != aCommonAncestor; | |||
| 13877 | c2 = GetParent<aTreeKind>(c2)) { | |||
| 13878 | node2Ancestors.AppendElement(c2); | |||
| 13879 | } | |||
| 13880 | if (!c2 && aCommonAncestor) { | |||
| 13881 | // So, it turns out aCommonAncestor was not an ancestor of c2. | |||
| 13882 | // We need to retry with no common ancestor hint. | |||
| 13883 | return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr, aCache); | |||
| 13884 | } | |||
| 13885 | ||||
| 13886 | // FIXME: Looks like that some of this can be rewritten with CommonAncestors. | |||
| 13887 | int last1 = node1Ancestors.Length() - 1; | |||
| 13888 | int last2 = node2Ancestors.Length() - 1; | |||
| 13889 | const nsINode* node1Ancestor = nullptr; | |||
| 13890 | const nsINode* node2Ancestor = nullptr; | |||
| 13891 | while (last1 >= 0 && last2 >= 0 && | |||
| 13892 | ((node1Ancestor = node1Ancestors.ElementAt(last1)) == | |||
| 13893 | (node2Ancestor = node2Ancestors.ElementAt(last2)))) { | |||
| 13894 | last1--; | |||
| 13895 | last2--; | |||
| 13896 | } | |||
| 13897 | ||||
| 13898 | if (last1 < 0) { | |||
| 13899 | if (last2 < 0) { | |||
| 13900 | NS_ASSERTION(aNode1 == aNode2, "internal error?")do { if (!(aNode1 == aNode2)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "internal error?", "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13900); MOZ_PretendNoReturn(); } } while (0); | |||
| 13901 | return 0; | |||
| 13902 | } | |||
| 13903 | // aContent1 is an ancestor of aContent2 | |||
| 13904 | return -1; | |||
| 13905 | } | |||
| 13906 | ||||
| 13907 | if (last2 < 0) { | |||
| 13908 | // aContent2 is an ancestor of aContent1 | |||
| 13909 | return 1; | |||
| 13910 | } | |||
| 13911 | // node1Ancestor != node2Ancestor, so they must be siblings with the | |||
| 13912 | // same parent | |||
| 13913 | const nsINode* parent = GetParent<aTreeKind>(node1Ancestor); | |||
| 13914 | if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13914)) { // different documents?? | |||
| 13915 | return 0; | |||
| 13916 | } | |||
| 13917 | MOZ_ASSERT(node1Ancestor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(node1Ancestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node1Ancestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node1Ancestor", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13917); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "node1Ancestor" ")"); do { MOZ_CrashSequence (__null, 13917); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13918 | MOZ_ASSERT(node2Ancestor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(node2Ancestor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node2Ancestor))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node2Ancestor", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13918); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "node2Ancestor" ")"); do { MOZ_CrashSequence (__null, 13918); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
| 13919 | Maybe<int32_t> index1; | |||
| 13920 | Maybe<int32_t> index2; | |||
| 13921 | // node1Ancestor and node2Ancestor must be children of parent so that they | |||
| 13922 | // must be content nodes if we can get the indices. | |||
| 13923 | MOZ_DIAGNOSTIC_ASSERT(node1Ancestor->IsContent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node1Ancestor->IsContent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node1Ancestor->IsContent( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node1Ancestor->IsContent()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13923); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node1Ancestor->IsContent()" ")"); do { MOZ_CrashSequence(__null, 13923); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13924 | MOZ_DIAGNOSTIC_ASSERT(node2Ancestor->IsContent())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node2Ancestor->IsContent())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node2Ancestor->IsContent( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node2Ancestor->IsContent()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13924); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node2Ancestor->IsContent()" ")"); do { MOZ_CrashSequence(__null, 13924); __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
| 13925 | if (aCache) { | |||
| 13926 | aCache->ComputeIndicesOf<aTreeKind>(parent, node1Ancestor->AsContent(), | |||
| 13927 | node2Ancestor->AsContent(), index1, | |||
| 13928 | index2); | |||
| 13929 | } else { | |||
| 13930 | index1 = GetIndexInParent<aTreeKind>(parent, node1Ancestor->AsContent()); | |||
| 13931 | index2 = GetIndexInParent<aTreeKind>(parent, node2Ancestor->AsContent()); | |||
| 13932 | } | |||
| 13933 | if (NS_WARN_IF(index1.isNothing())NS_warn_if_impl(index1.isNothing(), "index1.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13933) || NS_WARN_IF(index2.isNothing())NS_warn_if_impl(index2.isNothing(), "index2.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp" , 13933)) { | |||
| 13934 | // This should generally never happen, but can happen mid-unbind or in other | |||
| 13935 | // edge cases, deal with it somewhat reasonably. | |||
| 13936 | return 0; | |||
| 13937 | } | |||
| 13938 | return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2); | |||
| 13939 | } | |||
| 13940 | ||||
| 13941 | nsIContent* nsContentUtils::AttachDeclarativeShadowRoot( | |||
| 13942 | nsIContent* aHost, ShadowRootMode aMode, bool aIsClonable, | |||
| 13943 | bool aIsSerializable, bool aDelegatesFocus, bool aCustomElementRegistry, | |||
| 13944 | SlotAssignmentMode aSlotAssignment, const nsAString& aReferenceTarget) { | |||
| 13945 | RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost); | |||
| 13946 | if (!host || host->GetShadowRoot()) { | |||
| 13947 | // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host | |||
| 13948 | return nullptr; | |||
| 13949 | } | |||
| 13950 | ||||
| 13951 | ShadowRootInit init; | |||
| 13952 | init.mMode = aMode; | |||
| 13953 | init.mDelegatesFocus = aDelegatesFocus; | |||
| 13954 | init.mSlotAssignment = aSlotAssignment; | |||
| 13955 | init.mClonable = aIsClonable; | |||
| 13956 | init.mSerializable = aIsSerializable; | |||
| 13957 | // https://html.spec.whatwg.org/#current-template-insertion-mode | |||
| 13958 | // "Let registry be null if templateStartTag has a | |||
| 13959 | // shadowrootcustomelementregistry attribute; otherwise | |||
| 13960 | // declarativeShadowHostElement's node document's custom element registry." | |||
| 13961 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) { | |||
| 13962 | if (aCustomElementRegistry) { | |||
| 13963 | init.mCustomElementRegistry.Construct(nullptr); | |||
| 13964 | } else { | |||
| 13965 | init.mCustomElementRegistry.Construct( | |||
| 13966 | host->OwnerDoc()->GetCustomElementRegistry()); | |||
| 13967 | } | |||
| 13968 | } | |||
| 13969 | ||||
| 13970 | RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors()); | |||
| 13971 | if (shadowRoot) { | |||
| 13972 | shadowRoot->SetIsDeclarative( | |||
| 13973 | nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes); | |||
| 13974 | // https://html.spec.whatwg.org/#parsing-main-inhead | |||
| 13975 | // 7. If templateStartTag has a shadowrootcustomelementregistry attribute, | |||
| 13976 | // set shadow's keep custom element registry null to true. | |||
| 13977 | if (StaticPrefs::dom_scoped_custom_element_registries_enabled() && | |||
| 13978 | aCustomElementRegistry) { | |||
| 13979 | shadowRoot->SetKeepCustomElementRegistryNull(); | |||
| 13980 | } | |||
| 13981 | // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals | |||
| 13982 | shadowRoot->SetAvailableToElementInternals(); | |||
| 13983 | shadowRoot->SetReferenceTarget(aReferenceTarget); | |||
| 13984 | } | |||
| 13985 | return shadowRoot; | |||
| 13986 | } | |||
| 13987 | ||||
| 13988 | // https://html.spec.whatwg.org/#the-navigation-must-be-a-replace | |||
| 13989 | /* static */ bool nsContentUtils::NavigationMustBeAReplace( | |||
| 13990 | nsIURI& aURI, const Document& aDocument) { | |||
| 13991 | // The navigation must be a replace, given a URL url and a Document document, | |||
| 13992 | // if any of the following are true: | |||
| 13993 | // - url's scheme is "javascript"; or | |||
| 13994 | // - document's is initial about:blank is true. | |||
| 13995 | return aURI.SchemeIs("javascript") || | |||
| 13996 | (NS_IsAboutBlank(aDocument.GetDocumentURI()) && | |||
| 13997 | aDocument.IsInitialDocument()); | |||
| 13998 | } | |||
| 13999 | ||||
| 14000 | template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>( | |||
| 14001 | const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*); | |||
| 14002 | template int32_t | |||
| 14003 | nsContentUtils::CompareTreePosition<TreeKind::ShadowIncludingDOM>( | |||
| 14004 | const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*); | |||
| 14005 | template int32_t | |||
| 14006 | nsContentUtils::CompareTreePosition<TreeKind::FlatForSelection>( | |||
| 14007 | const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*); | |||
| 14008 | template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>( | |||
| 14009 | const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*); |