File: | var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp |
Warning: | line 10286, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |||
2 | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ | |||
3 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
6 | ||||
7 | /* A namespace class for static layout utilities. */ | |||
8 | ||||
9 | #include "nsContentUtils.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 | #include "BrowserChild.h" | |||
20 | #include "DecoderTraits.h" | |||
21 | #include "ErrorList.h" | |||
22 | #include "HTMLSplitOnSpacesTokenizer.h" | |||
23 | #include "ImageOps.h" | |||
24 | #include "InProcessBrowserChildMessageManager.h" | |||
25 | #include "MainThreadUtils.h" | |||
26 | #include "PLDHashTable.h" | |||
27 | #include "ReferrerInfo.h" | |||
28 | #include "ScopedNSSTypes.h" | |||
29 | #include "ThirdPartyUtil.h" | |||
30 | #include "Units.h" | |||
31 | #include "chrome/common/ipc_message.h" | |||
32 | #include "gfxDrawable.h" | |||
33 | #include "harfbuzz/hb.h" | |||
34 | #include "imgICache.h" | |||
35 | #include "imgIContainer.h" | |||
36 | #include "imgILoader.h" | |||
37 | #include "imgIRequest.h" | |||
38 | #include "imgLoader.h" | |||
39 | #include "js/Array.h" | |||
40 | #include "js/ArrayBuffer.h" | |||
41 | #include "js/BuildId.h" | |||
42 | #include "js/GCAPI.h" | |||
43 | #include "js/Id.h" | |||
44 | #include "js/JSON.h" | |||
45 | #include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty | |||
46 | #include "js/PropertyDescriptor.h" | |||
47 | #include "js/Realm.h" | |||
48 | #include "js/RegExp.h" | |||
49 | #include "js/RegExpFlags.h" | |||
50 | #include "js/RootingAPI.h" | |||
51 | #include "js/TypeDecls.h" | |||
52 | #include "js/Value.h" | |||
53 | #include "js/Wrapper.h" | |||
54 | #include "jsapi.h" | |||
55 | #include "jsfriendapi.h" | |||
56 | #include "mozAutoDocUpdate.h" | |||
57 | #include "mozIDOMWindow.h" | |||
58 | #include "nsIOService.h" | |||
59 | #include "nsObjectLoadingContent.h" | |||
60 | #include "mozilla/AlreadyAddRefed.h" | |||
61 | #include "mozilla/ArrayIterator.h" | |||
62 | #include "mozilla/ArrayUtils.h" | |||
63 | #include "mozilla/AsyncEventDispatcher.h" | |||
64 | #include "mozilla/AtomArray.h" | |||
65 | #include "mozilla/Atomics.h" | |||
66 | #include "mozilla/Attributes.h" | |||
67 | #include "mozilla/AutoRestore.h" | |||
68 | #include "mozilla/BackgroundHangMonitor.h" | |||
69 | #include "mozilla/Base64.h" | |||
70 | #include "mozilla/BasePrincipal.h" | |||
71 | #include "mozilla/BasicEvents.h" | |||
72 | #include "mozilla/BloomFilter.h" | |||
73 | #include "mozilla/CORSMode.h" | |||
74 | #include "mozilla/CallState.h" | |||
75 | #include "mozilla/CheckedInt.h" | |||
76 | #include "mozilla/ClearOnShutdown.h" | |||
77 | #include "mozilla/Components.h" | |||
78 | #include "mozilla/ContentBlockingAllowList.h" | |||
79 | #include "mozilla/CycleCollectedJSContext.h" | |||
80 | #include "mozilla/DOMEventTargetHelper.h" | |||
81 | #include "mozilla/DebugOnly.h" | |||
82 | #include "mozilla/ErrorResult.h" | |||
83 | #include "mozilla/EventDispatcher.h" | |||
84 | #include "mozilla/EventListenerManager.h" | |||
85 | #include "mozilla/EventQueue.h" | |||
86 | #include "mozilla/EventStateManager.h" | |||
87 | #include "mozilla/FlushType.h" | |||
88 | #include "mozilla/FOGIPC.h" | |||
89 | #include "mozilla/HTMLEditor.h" | |||
90 | #include "mozilla/HangAnnotations.h" | |||
91 | #include "mozilla/IMEStateManager.h" | |||
92 | #include "mozilla/InputEventOptions.h" | |||
93 | #include "mozilla/InternalMutationEvent.h" | |||
94 | #include "mozilla/Latin1.h" | |||
95 | #include "mozilla/Likely.h" | |||
96 | #include "mozilla/LoadInfo.h" | |||
97 | #include "mozilla/Logging.h" | |||
98 | #include "mozilla/MacroForEach.h" | |||
99 | #include "mozilla/ManualNAC.h" | |||
100 | #include "mozilla/Maybe.h" | |||
101 | #include "mozilla/MediaFeatureChange.h" | |||
102 | #include "mozilla/MouseEvents.h" | |||
103 | #include "mozilla/NotNull.h" | |||
104 | #include "mozilla/NullPrincipal.h" | |||
105 | #include "mozilla/OriginAttributes.h" | |||
106 | #include "mozilla/Preferences.h" | |||
107 | #include "mozilla/PresShell.h" | |||
108 | #include "mozilla/ProfilerRunnable.h" | |||
109 | #include "mozilla/RangeBoundary.h" | |||
110 | #include "mozilla/RefPtr.h" | |||
111 | #include "mozilla/Result.h" | |||
112 | #include "mozilla/ResultExtensions.h" | |||
113 | #include "mozilla/ScrollbarPreferences.h" | |||
114 | #include "mozilla/ScrollContainerFrame.h" | |||
115 | #include "mozilla/ShutdownPhase.h" | |||
116 | #include "mozilla/Span.h" | |||
117 | #include "mozilla/StaticAnalysisFunctions.h" | |||
118 | #include "mozilla/StaticPrefs_browser.h" | |||
119 | #include "mozilla/StaticPrefs_dom.h" | |||
120 | #ifdef FUZZING | |||
121 | # include "mozilla/StaticPrefs_fuzzing.h" | |||
122 | #endif | |||
123 | #include "mozilla/StaticPrefs_nglayout.h" | |||
124 | #include "mozilla/StaticPrefs_privacy.h" | |||
125 | #include "mozilla/StaticPrefs_test.h" | |||
126 | #include "mozilla/StaticPrefs_ui.h" | |||
127 | #include "mozilla/StaticPtr.h" | |||
128 | #include "mozilla/TextControlState.h" | |||
129 | #include "mozilla/TextEditor.h" | |||
130 | #include "mozilla/TextEvents.h" | |||
131 | #include "mozilla/UniquePtr.h" | |||
132 | #include "mozilla/Unused.h" | |||
133 | #include "mozilla/Variant.h" | |||
134 | #include "mozilla/ViewportUtils.h" | |||
135 | #include "mozilla/dom/AncestorIterator.h" | |||
136 | #include "mozilla/dom/AutoEntryScript.h" | |||
137 | #include "mozilla/dom/AutocompleteInfoBinding.h" | |||
138 | #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h" | |||
139 | #include "mozilla/dom/BindingDeclarations.h" | |||
140 | #include "mozilla/dom/BindingUtils.h" | |||
141 | #include "mozilla/dom/BlobImpl.h" | |||
142 | #include "mozilla/dom/BlobURLProtocolHandler.h" | |||
143 | #include "mozilla/dom/BorrowedAttrInfo.h" | |||
144 | #include "mozilla/dom/BrowserBridgeParent.h" | |||
145 | #include "mozilla/dom/BrowserParent.h" | |||
146 | #include "mozilla/dom/BrowsingContext.h" | |||
147 | #include "mozilla/dom/BrowsingContextGroup.h" | |||
148 | #include "mozilla/dom/CallbackFunction.h" | |||
149 | #include "mozilla/dom/CallbackObject.h" | |||
150 | #include "mozilla/dom/ChromeMessageBroadcaster.h" | |||
151 | #include "mozilla/dom/ContentChild.h" | |||
152 | #include "mozilla/dom/ContentFrameMessageManager.h" | |||
153 | #include "mozilla/dom/ContentParent.h" | |||
154 | #include "mozilla/dom/CustomElementRegistry.h" | |||
155 | #include "mozilla/dom/CustomElementRegistryBinding.h" | |||
156 | #include "mozilla/dom/CustomElementTypes.h" | |||
157 | #include "mozilla/dom/DOMArena.h" | |||
158 | #include "mozilla/dom/DOMException.h" | |||
159 | #include "mozilla/dom/DOMExceptionBinding.h" | |||
160 | #include "mozilla/dom/DOMSecurityMonitor.h" | |||
161 | #include "mozilla/dom/DOMTypes.h" | |||
162 | #include "mozilla/dom/DataTransfer.h" | |||
163 | #include "mozilla/dom/DocGroup.h" | |||
164 | #include "mozilla/dom/Document.h" | |||
165 | #include "mozilla/dom/DocumentFragment.h" | |||
166 | #include "mozilla/dom/DocumentInlines.h" | |||
167 | #include "mozilla/dom/Element.h" | |||
168 | #include "mozilla/dom/ElementBinding.h" | |||
169 | #include "mozilla/dom/ElementInlines.h" | |||
170 | #include "mozilla/dom/Event.h" | |||
171 | #include "mozilla/dom/EventTarget.h" | |||
172 | #include "mozilla/dom/FileBlobImpl.h" | |||
173 | #include "mozilla/dom/FileSystemSecurity.h" | |||
174 | #include "mozilla/dom/FilteredNodeIterator.h" | |||
175 | #include "mozilla/dom/FormData.h" | |||
176 | #include "mozilla/dom/FragmentOrElement.h" | |||
177 | #include "mozilla/dom/FromParser.h" | |||
178 | #include "mozilla/dom/HTMLElement.h" | |||
179 | #include "mozilla/dom/HTMLFormElement.h" | |||
180 | #include "mozilla/dom/HTMLImageElement.h" | |||
181 | #include "mozilla/dom/HTMLInputElement.h" | |||
182 | #include "mozilla/dom/HTMLTemplateElement.h" | |||
183 | #include "mozilla/dom/HTMLTextAreaElement.h" | |||
184 | #include "mozilla/dom/IPCBlob.h" | |||
185 | #include "mozilla/dom/IPCBlobUtils.h" | |||
186 | #include "mozilla/dom/MessageBroadcaster.h" | |||
187 | #include "mozilla/dom/MessageListenerManager.h" | |||
188 | #include "mozilla/dom/MessagePort.h" | |||
189 | #include "mozilla/dom/MouseEventBinding.h" | |||
190 | #include "mozilla/dom/NameSpaceConstants.h" | |||
191 | #include "mozilla/dom/NodeBinding.h" | |||
192 | #include "mozilla/dom/NodeInfo.h" | |||
193 | #include "mozilla/dom/PBrowser.h" | |||
194 | #include "mozilla/dom/PContentChild.h" | |||
195 | #include "mozilla/dom/PrototypeList.h" | |||
196 | #include "mozilla/dom/ReferrerPolicyBinding.h" | |||
197 | #include "mozilla/dom/ScriptSettings.h" | |||
198 | #include "mozilla/dom/Selection.h" | |||
199 | #include "mozilla/dom/ShadowRoot.h" | |||
200 | #include "mozilla/dom/Text.h" | |||
201 | #include "mozilla/dom/UserActivation.h" | |||
202 | #include "mozilla/dom/WindowContext.h" | |||
203 | #include "mozilla/dom/WorkerCommon.h" | |||
204 | #include "mozilla/dom/WorkerPrivate.h" | |||
205 | #include "mozilla/dom/WorkerRunnable.h" | |||
206 | #include "mozilla/dom/XULCommandEvent.h" | |||
207 | #include "mozilla/glean/GleanPings.h" | |||
208 | #include "mozilla/fallible.h" | |||
209 | #include "mozilla/gfx/2D.h" | |||
210 | #include "mozilla/gfx/BaseMargin.h" | |||
211 | #include "mozilla/gfx/BasePoint.h" | |||
212 | #include "mozilla/gfx/BaseSize.h" | |||
213 | #include "mozilla/gfx/DataSurfaceHelpers.h" | |||
214 | #include "mozilla/gfx/Point.h" | |||
215 | #include "mozilla/gfx/Rect.h" | |||
216 | #include "mozilla/gfx/Types.h" | |||
217 | #include "mozilla/ipc/ProtocolUtils.h" | |||
218 | #include "mozilla/ipc/SharedMemory.h" | |||
219 | #include "mozilla/net/UrlClassifierCommon.h" | |||
220 | #include "mozilla/Tokenizer.h" | |||
221 | #include "mozilla/widget/IMEData.h" | |||
222 | #include "nsAboutProtocolUtils.h" | |||
223 | #include "nsAlgorithm.h" | |||
224 | #include "nsArrayUtils.h" | |||
225 | #include "nsAtomHashKeys.h" | |||
226 | #include "nsAttrName.h" | |||
227 | #include "nsAttrValue.h" | |||
228 | #include "nsAttrValueInlines.h" | |||
229 | #include "nsBaseHashtable.h" | |||
230 | #include "nsCCUncollectableMarker.h" | |||
231 | #include "nsCOMPtr.h" | |||
232 | #include "nsCRT.h" | |||
233 | #include "nsCRTGlue.h" | |||
234 | #include "nsCanvasFrame.h" | |||
235 | #include "nsCaseTreatment.h" | |||
236 | #include "nsCharSeparatedTokenizer.h" | |||
237 | #include "nsCharTraits.h" | |||
238 | #include "nsCompatibility.h" | |||
239 | #include "nsComponentManagerUtils.h" | |||
240 | #include "nsContainerFrame.h" | |||
241 | #include "nsContentCreatorFunctions.h" | |||
242 | #include "nsContentDLF.h" | |||
243 | #include "nsContentList.h" | |||
244 | #include "nsContentListDeclarations.h" | |||
245 | #include "nsContentPolicyUtils.h" | |||
246 | #include "nsCoord.h" | |||
247 | #include "nsCycleCollectionNoteChild.h" | |||
248 | #include "nsDOMMutationObserver.h" | |||
249 | #include "nsDOMString.h" | |||
250 | #include "nsTHashMap.h" | |||
251 | #include "nsDebug.h" | |||
252 | #include "nsDocShell.h" | |||
253 | #include "nsDocShellCID.h" | |||
254 | #include "nsError.h" | |||
255 | #include "nsFocusManager.h" | |||
256 | #include "nsFrameList.h" | |||
257 | #include "nsFrameLoader.h" | |||
258 | #include "nsFrameLoaderOwner.h" | |||
259 | #include "nsGenericHTMLElement.h" | |||
260 | #include "nsGkAtoms.h" | |||
261 | #include "nsGlobalWindowInner.h" | |||
262 | #include "nsGlobalWindowOuter.h" | |||
263 | #include "nsHTMLDocument.h" | |||
264 | #include "nsHTMLTags.h" | |||
265 | #include "nsHashKeys.h" | |||
266 | #include "nsHtml5StringParser.h" | |||
267 | #include "nsIAboutModule.h" | |||
268 | #include "nsIAnonymousContentCreator.h" | |||
269 | #include "nsIAppShell.h" | |||
270 | #include "nsIArray.h" | |||
271 | #include "nsIAsyncVerifyRedirectCallback.h" | |||
272 | #include "nsIBidiKeyboard.h" | |||
273 | #include "nsIBrowser.h" | |||
274 | #include "nsICacheInfoChannel.h" | |||
275 | #include "nsICachingChannel.h" | |||
276 | #include "nsICategoryManager.h" | |||
277 | #include "nsIChannel.h" | |||
278 | #include "nsIChannelEventSink.h" | |||
279 | #include "nsIClassifiedChannel.h" | |||
280 | #include "nsIConsoleService.h" | |||
281 | #include "nsIContent.h" | |||
282 | #include "nsIContentInlines.h" | |||
283 | #include "nsIContentPolicy.h" | |||
284 | #include "nsIContentSecurityPolicy.h" | |||
285 | #include "nsIContentSink.h" | |||
286 | #include "nsIDOMWindowUtils.h" | |||
287 | #include "nsIDocShell.h" | |||
288 | #include "nsIDocShellTreeItem.h" | |||
289 | #include "nsIDocumentEncoder.h" | |||
290 | #include "nsIDocumentLoaderFactory.h" | |||
291 | #include "nsIDocumentViewer.h" | |||
292 | #include "nsIDragService.h" | |||
293 | #include "nsIDragSession.h" | |||
294 | #include "nsIFile.h" | |||
295 | #include "nsIFocusManager.h" | |||
296 | #include "nsIFormControl.h" | |||
297 | #include "nsIFragmentContentSink.h" | |||
298 | #include "nsIFrame.h" | |||
299 | #include "nsIGlobalObject.h" | |||
300 | #include "nsIHttpChannel.h" | |||
301 | #include "nsIHttpChannelInternal.h" | |||
302 | #include "nsIIOService.h" | |||
303 | #include "nsIImageLoadingContent.h" | |||
304 | #include "nsIInputStream.h" | |||
305 | #include "nsIInterfaceRequestor.h" | |||
306 | #include "nsIInterfaceRequestorUtils.h" | |||
307 | #include "nsILoadContext.h" | |||
308 | #include "nsILoadGroup.h" | |||
309 | #include "nsILoadInfo.h" | |||
310 | #include "nsIMIMEService.h" | |||
311 | #include "nsIMemoryReporter.h" | |||
312 | #include "nsINetUtil.h" | |||
313 | #include "nsINode.h" | |||
314 | #include "nsIObjectLoadingContent.h" | |||
315 | #include "nsIObserver.h" | |||
316 | #include "nsIObserverService.h" | |||
317 | #include "nsIParserUtils.h" | |||
318 | #include "nsIPermissionManager.h" | |||
319 | #include "nsIPrincipal.h" | |||
320 | #include "nsIProperties.h" | |||
321 | #include "nsIProtocolHandler.h" | |||
322 | #include "nsIRequest.h" | |||
323 | #include "nsIRunnable.h" | |||
324 | #include "nsIScreen.h" | |||
325 | #include "nsIScriptError.h" | |||
326 | #include "nsIScriptGlobalObject.h" | |||
327 | #include "nsIScriptObjectPrincipal.h" | |||
328 | #include "nsIScriptSecurityManager.h" | |||
329 | #include "nsISerialEventTarget.h" | |||
330 | #include "nsIStreamConverter.h" | |||
331 | #include "nsIStreamConverterService.h" | |||
332 | #include "nsIStringBundle.h" | |||
333 | #include "nsISupports.h" | |||
334 | #include "nsISupportsPrimitives.h" | |||
335 | #include "nsISupportsUtils.h" | |||
336 | #include "nsITransferable.h" | |||
337 | #include "nsIURI.h" | |||
338 | #include "nsIURIMutator.h" | |||
339 | #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) | |||
340 | # include "nsIURIWithSpecialOrigin.h" | |||
341 | #endif | |||
342 | #include "nsIUserIdleServiceInternal.h" | |||
343 | #include "nsIWeakReferenceUtils.h" | |||
344 | #include "nsIWebNavigation.h" | |||
345 | #include "nsIWebNavigationInfo.h" | |||
346 | #include "nsIWidget.h" | |||
347 | #include "nsIWindowMediator.h" | |||
348 | #include "nsIXPConnect.h" | |||
349 | #include "nsJSPrincipals.h" | |||
350 | #include "nsJSUtils.h" | |||
351 | #include "nsLayoutUtils.h" | |||
352 | #include "nsLiteralString.h" | |||
353 | #include "nsMargin.h" | |||
354 | #include "nsMimeTypes.h" | |||
355 | #include "nsNameSpaceManager.h" | |||
356 | #include "nsNetCID.h" | |||
357 | #include "nsNetUtil.h" | |||
358 | #include "nsNodeInfoManager.h" | |||
359 | #include "nsPIDOMWindow.h" | |||
360 | #include "nsPIDOMWindowInlines.h" | |||
361 | #include "nsParser.h" | |||
362 | #include "nsParserConstants.h" | |||
363 | #include "nsPoint.h" | |||
364 | #include "nsPointerHashKeys.h" | |||
365 | #include "nsPresContext.h" | |||
366 | #include "nsQueryFrame.h" | |||
367 | #include "nsQueryObject.h" | |||
368 | #include "nsRange.h" | |||
369 | #include "nsRefPtrHashtable.h" | |||
370 | #include "nsSandboxFlags.h" | |||
371 | #include "nsScriptSecurityManager.h" | |||
372 | #include "nsServiceManagerUtils.h" | |||
373 | #include "nsStreamUtils.h" | |||
374 | #include "nsString.h" | |||
375 | #include "nsStringBundle.h" | |||
376 | #include "nsStringFlags.h" | |||
377 | #include "nsStringFwd.h" | |||
378 | #include "nsStringIterator.h" | |||
379 | #include "nsStringStream.h" | |||
380 | #include "nsTArray.h" | |||
381 | #include "nsTLiteralString.h" | |||
382 | #include "nsTPromiseFlatString.h" | |||
383 | #include "nsTStringRepr.h" | |||
384 | #include "nsTextFragment.h" | |||
385 | #include "nsTextNode.h" | |||
386 | #include "nsThreadManager.h" | |||
387 | #include "nsThreadUtils.h" | |||
388 | #include "nsTreeSanitizer.h" | |||
389 | #include "nsUGenCategory.h" | |||
390 | #include "nsURLHelper.h" | |||
391 | #include "nsUnicodeProperties.h" | |||
392 | #include "nsVariant.h" | |||
393 | #include "nsWidgetsCID.h" | |||
394 | #include "nsView.h" | |||
395 | #include "nsViewManager.h" | |||
396 | #include "nsXPCOM.h" | |||
397 | #include "nsXPCOMCID.h" | |||
398 | #include "nsXULAppAPI.h" | |||
399 | #include "nsXULElement.h" | |||
400 | #include "nsXULPopupManager.h" | |||
401 | #include "nscore.h" | |||
402 | #include "prinrval.h" | |||
403 | #include "xpcprivate.h" | |||
404 | #include "xpcpublic.h" | |||
405 | ||||
406 | #if defined(XP_WIN) | |||
407 | // Undefine LoadImage to prevent naming conflict with Windows. | |||
408 | # undef LoadImage | |||
409 | #endif | |||
410 | ||||
411 | extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end, | |||
412 | const char** next, char16_t* result); | |||
413 | extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware, | |||
414 | const char** colon); | |||
415 | ||||
416 | using namespace mozilla::dom; | |||
417 | using namespace mozilla::ipc; | |||
418 | using namespace mozilla::gfx; | |||
419 | using namespace mozilla::layers; | |||
420 | using namespace mozilla::widget; | |||
421 | using namespace mozilla; | |||
422 | ||||
423 | const char kLoadAsData[] = "loadAsData"; | |||
424 | ||||
425 | nsIXPConnect* nsContentUtils::sXPConnect; | |||
426 | nsIScriptSecurityManager* nsContentUtils::sSecurityManager; | |||
427 | nsIPrincipal* nsContentUtils::sSystemPrincipal; | |||
428 | nsIPrincipal* nsContentUtils::sNullSubjectPrincipal; | |||
429 | nsIConsoleService* nsContentUtils::sConsoleService; | |||
430 | ||||
431 | static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable; | |||
432 | static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable; | |||
433 | static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents; | |||
434 | nsIStringBundleService* nsContentUtils::sStringBundleService; | |||
435 | ||||
436 | static StaticRefPtr<nsIStringBundle> | |||
437 | sStringBundles[nsContentUtils::PropertiesFile_COUNT]; | |||
438 | ||||
439 | nsIContentPolicy* nsContentUtils::sContentPolicyService; | |||
440 | bool nsContentUtils::sTriedToGetContentPolicy = false; | |||
441 | StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard; | |||
442 | uint32_t nsContentUtils::sScriptBlockerCount = 0; | |||
443 | uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0; | |||
444 | AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = | |||
445 | nullptr; | |||
446 | uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0; | |||
447 | nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr; | |||
448 | ||||
449 | bool nsContentUtils::sIsHandlingKeyBoardEvent = false; | |||
450 | ||||
451 | nsString* nsContentUtils::sShiftText = nullptr; | |||
452 | nsString* nsContentUtils::sControlText = nullptr; | |||
453 | nsString* nsContentUtils::sCommandOrWinText = nullptr; | |||
454 | nsString* nsContentUtils::sAltText = nullptr; | |||
455 | nsString* nsContentUtils::sModifierSeparator = nullptr; | |||
456 | ||||
457 | bool nsContentUtils::sInitialized = false; | |||
458 | #ifndef RELEASE_OR_BETA | |||
459 | bool nsContentUtils::sBypassCSSOMOriginCheck = false; | |||
460 | #endif | |||
461 | ||||
462 | nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr; | |||
463 | nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr; | |||
464 | ||||
465 | nsContentUtils::UserInteractionObserver* | |||
466 | nsContentUtils::sUserInteractionObserver = nullptr; | |||
467 | ||||
468 | nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr; | |||
469 | nsParser* nsContentUtils::sXMLFragmentParser = nullptr; | |||
470 | nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr; | |||
471 | bool nsContentUtils::sFragmentParsingActive = false; | |||
472 | ||||
473 | bool nsContentUtils::sMayHaveFormCheckboxStateChangeListeners = false; | |||
474 | bool nsContentUtils::sMayHaveFormRadioStateChangeListeners = false; | |||
475 | ||||
476 | mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog( | |||
477 | "nsResistFingerprinting"); | |||
478 | mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump"); | |||
479 | ||||
480 | int32_t nsContentUtils::sInnerOrOuterWindowCount = 0; | |||
481 | uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0; | |||
482 | ||||
483 | template Maybe<int32_t> nsContentUtils::ComparePoints( | |||
484 | const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary); | |||
485 | template Maybe<int32_t> nsContentUtils::ComparePoints( | |||
486 | const RangeBoundary& aFirstBoundary, | |||
487 | const RawRangeBoundary& aSecondBoundary); | |||
488 | template Maybe<int32_t> nsContentUtils::ComparePoints( | |||
489 | const RawRangeBoundary& aFirstBoundary, | |||
490 | const RangeBoundary& aSecondBoundary); | |||
491 | template Maybe<int32_t> nsContentUtils::ComparePoints( | |||
492 | const RawRangeBoundary& aFirstBoundary, | |||
493 | const RawRangeBoundary& aSecondBoundary); | |||
494 | ||||
495 | template int32_t nsContentUtils::ComparePoints_Deprecated( | |||
496 | const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary, | |||
497 | bool* aDisconnected); | |||
498 | template int32_t nsContentUtils::ComparePoints_Deprecated( | |||
499 | const RangeBoundary& aFirstBoundary, | |||
500 | const RawRangeBoundary& aSecondBoundary, bool* aDisconnected); | |||
501 | template int32_t nsContentUtils::ComparePoints_Deprecated( | |||
502 | const RawRangeBoundary& aFirstBoundary, | |||
503 | const RangeBoundary& aSecondBoundary, bool* aDisconnected); | |||
504 | template int32_t nsContentUtils::ComparePoints_Deprecated( | |||
505 | const RawRangeBoundary& aFirstBoundary, | |||
506 | const RawRangeBoundary& aSecondBoundary, bool* aDisconnected); | |||
507 | ||||
508 | // Subset of | |||
509 | // http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name | |||
510 | enum AutocompleteUnsupportedFieldName : uint8_t { | |||
511 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ | |||
512 | eAutocompleteUnsupportedFieldName_##name_, | |||
513 | #include "AutocompleteFieldList.h" | |||
514 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME | |||
515 | }; | |||
516 | ||||
517 | enum AutocompleteNoPersistFieldName : uint8_t { | |||
518 | #define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ | |||
519 | eAutocompleteNoPersistFieldName_##name_, | |||
520 | #include "AutocompleteFieldList.h" | |||
521 | #undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME | |||
522 | }; | |||
523 | ||||
524 | enum AutocompleteUnsupportFieldContactHint : uint8_t { | |||
525 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ | |||
526 | eAutocompleteUnsupportedFieldContactHint_##name_, | |||
527 | #include "AutocompleteFieldList.h" | |||
528 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT | |||
529 | }; | |||
530 | ||||
531 | enum AutocompleteFieldName : uint8_t { | |||
532 | #define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_, | |||
533 | #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ | |||
534 | AUTOCOMPLETE_FIELD_NAME(name_, value_) | |||
535 | #include "AutocompleteFieldList.h" | |||
536 | #undef AUTOCOMPLETE_FIELD_NAME | |||
537 | #undef AUTOCOMPLETE_CONTACT_FIELD_NAME | |||
538 | }; | |||
539 | ||||
540 | enum AutocompleteFieldHint : uint8_t { | |||
541 | #define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_, | |||
542 | #include "AutocompleteFieldList.h" | |||
543 | #undef AUTOCOMPLETE_FIELD_HINT | |||
544 | }; | |||
545 | ||||
546 | enum AutocompleteFieldContactHint : uint8_t { | |||
547 | #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ | |||
548 | eAutocompleteFieldContactHint_##name_, | |||
549 | #include "AutocompleteFieldList.h" | |||
550 | #undef AUTOCOMPLETE_FIELD_CONTACT_HINT | |||
551 | }; | |||
552 | ||||
553 | enum AutocompleteCredentialType : uint8_t { | |||
554 | #define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ | |||
555 | eAutocompleteCredentialType_##name_, | |||
556 | #include "AutocompleteFieldList.h" | |||
557 | #undef AUTOCOMPLETE_CREDENTIAL_TYPE | |||
558 | }; | |||
559 | ||||
560 | enum AutocompleteCategory { | |||
561 | #define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_, | |||
562 | #include "AutocompleteFieldList.h" | |||
563 | #undef AUTOCOMPLETE_CATEGORY | |||
564 | }; | |||
565 | ||||
566 | static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = { | |||
567 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \ | |||
568 | {value_, eAutocompleteUnsupportedFieldName_##name_}, | |||
569 | #include "AutocompleteFieldList.h" | |||
570 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME | |||
571 | {nullptr, 0}}; | |||
572 | ||||
573 | static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = { | |||
574 | #define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \ | |||
575 | {value_, eAutocompleteNoPersistFieldName_##name_}, | |||
576 | #include "AutocompleteFieldList.h" | |||
577 | #undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME | |||
578 | {nullptr, 0}}; | |||
579 | ||||
580 | static const nsAttrValue::EnumTable | |||
581 | kAutocompleteUnsupportedContactFieldHintTable[] = { | |||
582 | #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \ | |||
583 | {value_, eAutocompleteUnsupportedFieldContactHint_##name_}, | |||
584 | #include "AutocompleteFieldList.h" | |||
585 | #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT | |||
586 | {nullptr, 0}}; | |||
587 | ||||
588 | static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = { | |||
589 | #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \ | |||
590 | {value_, eAutocompleteFieldName_##name_}, | |||
591 | #include "AutocompleteFieldList.h" | |||
592 | #undef AUTOCOMPLETE_FIELD_NAME | |||
593 | {nullptr, 0}}; | |||
594 | ||||
595 | static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = { | |||
596 | #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \ | |||
597 | {value_, eAutocompleteFieldName_##name_}, | |||
598 | #include "AutocompleteFieldList.h" | |||
599 | #undef AUTOCOMPLETE_CONTACT_FIELD_NAME | |||
600 | {nullptr, 0}}; | |||
601 | ||||
602 | static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = { | |||
603 | #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \ | |||
604 | {value_, eAutocompleteFieldHint_##name_}, | |||
605 | #include "AutocompleteFieldList.h" | |||
606 | #undef AUTOCOMPLETE_FIELD_HINT | |||
607 | {nullptr, 0}}; | |||
608 | ||||
609 | static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = { | |||
610 | #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \ | |||
611 | {value_, eAutocompleteFieldContactHint_##name_}, | |||
612 | #include "AutocompleteFieldList.h" | |||
613 | #undef AUTOCOMPLETE_FIELD_CONTACT_HINT | |||
614 | {nullptr, 0}}; | |||
615 | ||||
616 | static const nsAttrValue::EnumTable kAutocompleteCredentialTypeTable[] = { | |||
617 | #define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \ | |||
618 | {value_, eAutocompleteCredentialType_##name_}, | |||
619 | #include "AutocompleteFieldList.h" | |||
620 | #undef AUTOCOMPLETE_CREDENTIAL_TYPE | |||
621 | {nullptr, 0}}; | |||
622 | ||||
623 | namespace { | |||
624 | ||||
625 | static PLDHashTable* sEventListenerManagersHash; | |||
626 | ||||
627 | // A global hashtable to for keeping the arena alive for cross docGroup node | |||
628 | // adoption. | |||
629 | static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>* | |||
630 | sDOMArenaHashtable; | |||
631 | ||||
632 | class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter { | |||
633 | MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)static size_t MallocSizeOf(const void* aPtr) { mozilla::dmd:: Report(aPtr); return moz_malloc_size_of(aPtr); } | |||
634 | ||||
635 | ~DOMEventListenerManagersHashReporter() = default; | |||
636 | ||||
637 | public: | |||
638 | 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: | |||
639 | ||||
640 | NS_IMETHODvirtual nsresult CollectReports(nsIHandleReportCallback* aHandleReport, | |||
641 | nsISupports* aData, bool aAnonymize) override { | |||
642 | // We don't measure the |EventListenerManager| objects pointed to by the | |||
643 | // entries because those references are non-owning. | |||
644 | int64_t amount = | |||
645 | sEventListenerManagersHash | |||
646 | ? sEventListenerManagersHash->ShallowSizeOfIncludingThis( | |||
647 | MallocSizeOf) | |||
648 | : 0; | |||
649 | ||||
650 | MOZ_COLLECT_REPORT((void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table." ), aData) | |||
651 | "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table." ), aData) | |||
652 | amount, "Memory used by the event listener manager's hash table.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/dom/event-listener-managers-hash" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by the event listener manager's hash table." ), aData); | |||
653 | ||||
654 | return NS_OK; | |||
655 | } | |||
656 | }; | |||
657 | ||||
658 | NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)MozExternalRefCountType DOMEventListenerManagersHashReporter:: AddRef(void) { static_assert(!std::is_destructible_v<DOMEventListenerManagersHashReporter >, "Reference-counted class " "DOMEventListenerManagersHashReporter" " 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 658; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("DOMEventListenerManagersHashReporter" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("DOMEventListenerManagersHashReporter" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"DOMEventListenerManagersHashReporter\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 658; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("DOMEventListenerManagersHashReporter" " not thread-safe" ); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ( "DOMEventListenerManagersHashReporter"), (uint32_t)(sizeof(*this ))); return count; } MozExternalRefCountType DOMEventListenerManagersHashReporter ::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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 658 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("DOMEventListenerManagersHashReporter" != nullptr )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!("DOMEventListenerManagersHashReporter" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"DOMEventListenerManagersHashReporter\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"DOMEventListenerManagersHashReporter\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 658; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("DOMEventListenerManagersHashReporter" " not thread-safe" ); const char* const nametmp = "DOMEventListenerManagersHashReporter" ; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), ( nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult DOMEventListenerManagersHashReporter ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 658); 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<DOMEventListenerManagersHashReporter, nsIMemoryReporter >, int32_t( reinterpret_cast<char*>(static_cast<nsIMemoryReporter *>((DOMEventListenerManagersHashReporter*)0x1000)) - reinterpret_cast <char*>((DOMEventListenerManagersHashReporter*)0x1000)) }, {&mozilla::detail::kImplementedIID<DOMEventListenerManagersHashReporter , nsISupports>, int32_t(reinterpret_cast<char*>(static_cast <nsISupports*>( static_cast<nsIMemoryReporter*>(( DOMEventListenerManagersHashReporter*)0x1000))) - reinterpret_cast <char*>((DOMEventListenerManagersHashReporter*)0x1000)) }, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table [0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } | |||
659 | ||||
660 | class EventListenerManagerMapEntry : public PLDHashEntryHdr { | |||
661 | public: | |||
662 | explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {} | |||
663 | ||||
664 | ~EventListenerManagerMapEntry() { | |||
665 | NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM")do { if (!(!mListenerManager)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "caller must release and disconnect ELM", "!mListenerManager" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 665); MOZ_PretendNoReturn(); } } while (0); | |||
666 | } | |||
667 | ||||
668 | protected: // declared protected to silence clang warnings | |||
669 | const void* mKey; // must be first, to look like PLDHashEntryStub | |||
670 | ||||
671 | public: | |||
672 | RefPtr<EventListenerManager> mListenerManager; | |||
673 | }; | |||
674 | ||||
675 | static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry, | |||
676 | const void* key) { | |||
677 | // Initialize the entry with placement new | |||
678 | new (entry) EventListenerManagerMapEntry(key); | |||
679 | } | |||
680 | ||||
681 | static void EventListenerManagerHashClearEntry(PLDHashTable* table, | |||
682 | PLDHashEntryHdr* entry) { | |||
683 | EventListenerManagerMapEntry* lm = | |||
684 | static_cast<EventListenerManagerMapEntry*>(entry); | |||
685 | ||||
686 | // Let the EventListenerManagerMapEntry clean itself up... | |||
687 | lm->~EventListenerManagerMapEntry(); | |||
688 | } | |||
689 | ||||
690 | class SameOriginCheckerImpl final : public nsIChannelEventSink, | |||
691 | public nsIInterfaceRequestor { | |||
692 | ~SameOriginCheckerImpl() = default; | |||
693 | ||||
694 | 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: | |||
695 | NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel , nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback *callback) override; | |||
696 | NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * * result) override; | |||
697 | }; | |||
698 | ||||
699 | } // namespace | |||
700 | ||||
701 | void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) { | |||
702 | // Note: Document::SuppressEventHandling will also automatically suppress | |||
703 | // event handling for any in-process sub-documents. However, since we need | |||
704 | // to deal with cases where remote BrowsingContexts may be interleaved | |||
705 | // with in-process ones, we still need to walk the entire tree ourselves. | |||
706 | // This may be slightly redundant in some cases, but since event handling | |||
707 | // suppressions maintain a count of current blockers, it does not cause | |||
708 | // any problems. | |||
709 | aDoc->SuppressEventHandling(); | |||
710 | } | |||
711 | ||||
712 | void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) { | |||
713 | aDoc->UnsuppressEventHandlingAndFireEvents(true); | |||
714 | } | |||
715 | ||||
716 | AutoSuppressEventHandling::~AutoSuppressEventHandling() { | |||
717 | UnsuppressDocuments(); | |||
718 | } | |||
719 | ||||
720 | void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) { | |||
721 | AutoSuppressEventHandling::SuppressDocument(aDoc); | |||
722 | if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) { | |||
723 | win->Suspend(); | |||
724 | mWindows.AppendElement(win); | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() { | |||
729 | for (const auto& win : mWindows) { | |||
730 | win->Resume(); | |||
731 | } | |||
732 | } | |||
733 | ||||
734 | /** | |||
735 | * This class is used to determine whether or not the user is currently | |||
736 | * interacting with the browser. It listens to observer events to toggle the | |||
737 | * value of the sUserActive static. | |||
738 | * | |||
739 | * This class is an internal implementation detail. | |||
740 | * nsContentUtils::GetUserIsInteracting() should be used to access current | |||
741 | * user interaction status. | |||
742 | */ | |||
743 | class nsContentUtils::UserInteractionObserver final | |||
744 | : public nsIObserver, | |||
745 | public BackgroundHangAnnotator { | |||
746 | public: | |||
747 | 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: | |||
748 | NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic , const char16_t * aData) override; | |||
749 | ||||
750 | void Init(); | |||
751 | void Shutdown(); | |||
752 | void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override; | |||
753 | ||||
754 | static Atomic<bool> sUserActive; | |||
755 | ||||
756 | private: | |||
757 | ~UserInteractionObserver() = default; | |||
758 | }; | |||
759 | ||||
760 | static constexpr nsLiteralCString kRfpPrefs[] = { | |||
761 | "privacy.resistFingerprinting"_ns, | |||
762 | "privacy.resistFingerprinting.pbmode"_ns, | |||
763 | "privacy.fingerprintingProtection"_ns, | |||
764 | "privacy.fingerprintingProtection.pbmode"_ns, | |||
765 | "privacy.fingerprintingProtection.overrides"_ns, | |||
766 | }; | |||
767 | ||||
768 | static void RecomputeResistFingerprintingAllDocs(const char*, void*) { | |||
769 | AutoTArray<RefPtr<BrowsingContextGroup>, 5> bcGroups; | |||
770 | BrowsingContextGroup::GetAllGroups(bcGroups); | |||
771 | for (auto& bcGroup : bcGroups) { | |||
772 | AutoTArray<DocGroup*, 5> docGroups; | |||
773 | bcGroup->GetDocGroups(docGroups); | |||
774 | for (auto* docGroup : docGroups) { | |||
775 | for (Document* doc : *docGroup) { | |||
776 | if (doc->RecomputeResistFingerprinting()) { | |||
777 | if (auto* pc = doc->GetPresContext()) { | |||
778 | pc->MediaFeatureValuesChanged( | |||
779 | {MediaFeatureChangeReason::PreferenceChange}, | |||
780 | MediaFeatureChangePropagation::JustThisDocument); | |||
781 | } | |||
782 | } | |||
783 | } | |||
784 | } | |||
785 | } | |||
786 | } | |||
787 | ||||
788 | // static | |||
789 | nsresult nsContentUtils::Init() { | |||
790 | if (sInitialized) { | |||
791 | NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 791); | |||
792 | ||||
793 | return NS_OK; | |||
794 | } | |||
795 | ||||
796 | nsHTMLTags::AddRefTable(); | |||
797 | ||||
798 | sXPConnect = nsXPConnect::XPConnect(); | |||
799 | // We hold a strong ref to sXPConnect to ensure that it does not go away until | |||
800 | // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be | |||
801 | // triggered by xpcModuleDtor late in shutdown and cause crashes due to | |||
802 | // various stuff already being torn down by then. Note that this means that | |||
803 | // we are effectively making sure that if we leak nsLayoutStatics then we also | |||
804 | // leak nsXPConnect. | |||
805 | NS_ADDREF(sXPConnect)(sXPConnect)->AddRef(); | |||
806 | ||||
807 | sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager(); | |||
808 | if (!sSecurityManager) return NS_ERROR_FAILURE; | |||
809 | NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef(); | |||
810 | ||||
811 | sSecurityManager->GetSystemPrincipal(&sSystemPrincipal); | |||
812 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSystemPrincipal" ")"); do { *((volatile int*)__null) = 812; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
813 | ||||
814 | RefPtr<NullPrincipal> nullPrincipal = | |||
815 | NullPrincipal::CreateWithoutOriginAttributes(); | |||
816 | if (!nullPrincipal) { | |||
817 | return NS_ERROR_FAILURE; | |||
818 | } | |||
819 | ||||
820 | nullPrincipal.forget(&sNullSubjectPrincipal); | |||
821 | ||||
822 | if (!InitializeEventTable()) return NS_ERROR_FAILURE; | |||
823 | ||||
824 | if (!sEventListenerManagersHash) { | |||
825 | static const PLDHashTableOps hash_table_ops = { | |||
826 | PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub, | |||
827 | PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry, | |||
828 | EventListenerManagerHashInitEntry}; | |||
829 | ||||
830 | sEventListenerManagersHash = | |||
831 | new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry)); | |||
832 | ||||
833 | RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter()); | |||
834 | } | |||
835 | ||||
836 | sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>; | |||
837 | ||||
838 | #ifndef RELEASE_OR_BETA | |||
839 | sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK"); | |||
840 | #endif | |||
841 | ||||
842 | Element::InitCCCallbacks(); | |||
843 | ||||
844 | RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate(); | |||
845 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService" ")" ); do { *((volatile int*)__null) = 845; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
846 | ||||
847 | if (XRE_IsParentProcess()) { | |||
848 | AsyncPrecreateStringBundles(); | |||
849 | ||||
850 | #if defined(MOZ_WIDGET_ANDROID) | |||
851 | // On Android, at-shutdown ping submission isn't reliable | |||
852 | // (( because, on Android, we usually get killed, not shut down )). | |||
853 | // To have a chance at submitting the ping, aim for idle after startup. | |||
854 | nsresult rv = NS_DispatchToCurrentThreadQueue( | |||
855 | NS_NewRunnableFunction( | |||
856 | "AndroidUseCounterPingSubmitter", | |||
857 | []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }), | |||
858 | EventQueuePriority::Idle); | |||
859 | // This is mostly best-effort, so if it goes awry, just log. | |||
860 | Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 860); | |||
861 | #endif // defined(MOZ_WIDGET_ANDROID) | |||
862 | ||||
863 | RunOnShutdown( | |||
864 | [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); }, | |||
865 | ShutdownPhase::AppShutdownConfirmed); | |||
866 | } | |||
867 | ||||
868 | RefPtr<UserInteractionObserver> uio = new UserInteractionObserver(); | |||
869 | uio->Init(); | |||
870 | uio.forget(&sUserInteractionObserver); | |||
871 | ||||
872 | for (const auto& pref : kRfpPrefs) { | |||
873 | Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref); | |||
874 | } | |||
875 | ||||
876 | sInitialized = true; | |||
877 | ||||
878 | return NS_OK; | |||
879 | } | |||
880 | ||||
881 | bool nsContentUtils::InitJSBytecodeMimeType() { | |||
882 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
883 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType" ")"); do { *((volatile int*)__null) = 883; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
884 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType" ")"); do { *((volatile int*)__null) = 884; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
885 | ||||
886 | JS::BuildIdCharVector jsBuildId; | |||
887 | if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) { | |||
888 | return false; | |||
889 | } | |||
890 | ||||
891 | nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length()); | |||
892 | sJSScriptBytecodeMimeType = | |||
893 | new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr); | |||
894 | sJSModuleBytecodeMimeType = | |||
895 | new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr); | |||
896 | return true; | |||
897 | } | |||
898 | ||||
899 | void nsContentUtils::GetShiftText(nsAString& text) { | |||
900 | if (!sShiftText) InitializeModifierStrings(); | |||
901 | text.Assign(*sShiftText); | |||
902 | } | |||
903 | ||||
904 | void nsContentUtils::GetControlText(nsAString& text) { | |||
905 | if (!sControlText) InitializeModifierStrings(); | |||
906 | text.Assign(*sControlText); | |||
907 | } | |||
908 | ||||
909 | void nsContentUtils::GetCommandOrWinText(nsAString& text) { | |||
910 | if (!sCommandOrWinText) { | |||
911 | InitializeModifierStrings(); | |||
912 | } | |||
913 | text.Assign(*sCommandOrWinText); | |||
914 | } | |||
915 | ||||
916 | void nsContentUtils::GetAltText(nsAString& text) { | |||
917 | if (!sAltText) InitializeModifierStrings(); | |||
918 | text.Assign(*sAltText); | |||
919 | } | |||
920 | ||||
921 | void nsContentUtils::GetModifierSeparatorText(nsAString& text) { | |||
922 | if (!sModifierSeparator) InitializeModifierStrings(); | |||
923 | text.Assign(*sModifierSeparator); | |||
924 | } | |||
925 | ||||
926 | void nsContentUtils::InitializeModifierStrings() { | |||
927 | // load the display strings for the keyboard accelerators | |||
928 | nsCOMPtr<nsIStringBundleService> bundleService = | |||
929 | mozilla::components::StringBundle::Service(); | |||
930 | nsCOMPtr<nsIStringBundle> bundle; | |||
931 | DebugOnly<nsresult> rv = NS_OK; | |||
932 | if (bundleService) { | |||
933 | rv = bundleService->CreateBundle( | |||
934 | "chrome://global-platform/locale/platformKeys.properties", | |||
935 | getter_AddRefs(bundle)); | |||
936 | } | |||
937 | ||||
938 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 940); MOZ_PretendNoReturn(); } } while (0) | |||
939 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 940); MOZ_PretendNoReturn(); } } while (0) | |||
940 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 940); MOZ_PretendNoReturn(); } } while (0); | |||
941 | nsAutoString shiftModifier; | |||
942 | nsAutoString commandOrWinModifier; | |||
943 | nsAutoString altModifier; | |||
944 | nsAutoString controlModifier; | |||
945 | nsAutoString modifierSeparator; | |||
946 | if (bundle) { | |||
947 | // macs use symbols for each modifier key, so fetch each from the bundle, | |||
948 | // which also covers i18n | |||
949 | bundle->GetStringFromName("VK_SHIFT", shiftModifier); | |||
950 | bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier); | |||
951 | bundle->GetStringFromName("VK_ALT", altModifier); | |||
952 | bundle->GetStringFromName("VK_CONTROL", controlModifier); | |||
953 | bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator); | |||
954 | } | |||
955 | // if any of these don't exist, we get an empty string | |||
956 | sShiftText = new nsString(shiftModifier); | |||
957 | sCommandOrWinText = new nsString(commandOrWinModifier); | |||
958 | sAltText = new nsString(altModifier); | |||
959 | sControlText = new nsString(controlModifier); | |||
960 | sModifierSeparator = new nsString(modifierSeparator); | |||
961 | } | |||
962 | ||||
963 | mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage( | |||
964 | EventMessage aEventMessage) { | |||
965 | switch (aEventMessage) { | |||
966 | #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ | |||
967 | case message_: \ | |||
968 | return struct_; | |||
969 | #include "mozilla/EventNameList.h" | |||
970 | #undef MESSAGE_TO_EVENT | |||
971 | default: | |||
972 | 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do { *((volatile int*)__null) = 972; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
973 | return eBasicEventClass; | |||
974 | } | |||
975 | } | |||
976 | ||||
977 | bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) { | |||
978 | bool doesNotReturnData = false; | |||
979 | nsresult rv = NS_URIChainHasFlags( | |||
980 | aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData); | |||
981 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData; | |||
982 | } | |||
983 | ||||
984 | /* static */ | |||
985 | nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) { | |||
986 | switch (aEventMessage) { | |||
987 | #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \ | |||
988 | case message_: \ | |||
989 | return nsGkAtoms::on##name_; | |||
990 | #include "mozilla/EventNameList.h" | |||
991 | #undef MESSAGE_TO_EVENT | |||
992 | default: | |||
993 | return nullptr; | |||
994 | } | |||
995 | } | |||
996 | ||||
997 | bool nsContentUtils::InitializeEventTable() { | |||
998 | NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!")do { if (!(!sAtomEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "EventTable already initialized!", "!sAtomEventTable", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 998); MOZ_PretendNoReturn(); } } while (0); | |||
999 | NS_ASSERTION(!sStringEventTable, "EventTable already initialized!")do { if (!(!sStringEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "EventTable already initialized!", "!sStringEventTable", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 999); MOZ_PretendNoReturn(); } } while (0); | |||
1000 | ||||
1001 | static const EventNameMapping eventArray[] = { | |||
1002 | #define EVENT(name_, _message, _type, _class) \ | |||
1003 | {nsGkAtoms::on##name_, _type, _message, _class}, | |||
1004 | #define WINDOW_ONLY_EVENT EVENT | |||
1005 | #define DOCUMENT_ONLY_EVENTEVENT EVENT | |||
1006 | #define NON_IDL_EVENT EVENT | |||
1007 | #include "mozilla/EventNameList.h" | |||
1008 | #undef WINDOW_ONLY_EVENT | |||
1009 | #undef NON_IDL_EVENT | |||
1010 | #undef EVENT | |||
1011 | {nullptr}}; | |||
1012 | ||||
1013 | sAtomEventTable = | |||
1014 | new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(ArrayLength(eventArray)); | |||
1015 | sStringEventTable = new nsTHashMap<nsStringHashKey, EventNameMapping>( | |||
1016 | ArrayLength(eventArray)); | |||
1017 | sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64); | |||
1018 | ||||
1019 | // Subtract one from the length because of the trailing null | |||
1020 | for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) { | |||
1021 | 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.h" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)" ") (" "Double-defining event name; fix your EventNameList.h" ")"); do { *((volatile int*)__null) = 1022; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
1022 | "Double-defining event name; fix your EventNameList.h")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.h" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)" ") (" "Double-defining event name; fix your EventNameList.h" ")"); do { *((volatile int*)__null) = 1022; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1023 | sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]); | |||
1024 | sStringEventTable->InsertOrUpdate( | |||
1025 | Substring(nsDependentAtomString(eventArray[i].mAtom), 2), | |||
1026 | eventArray[i]); | |||
1027 | } | |||
1028 | ||||
1029 | return true; | |||
1030 | } | |||
1031 | ||||
1032 | void nsContentUtils::InitializeTouchEventTable() { | |||
1033 | static bool sEventTableInitialized = false; | |||
1034 | if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) { | |||
1035 | sEventTableInitialized = true; | |||
1036 | static const EventNameMapping touchEventArray[] = { | |||
1037 | #define EVENT(name_, _message, _type, _class) | |||
1038 | #define TOUCH_EVENT(name_, _message, _type, _class) \ | |||
1039 | {nsGkAtoms::on##name_, _type, _message, _class}, | |||
1040 | #include "mozilla/EventNameList.h" | |||
1041 | #undef TOUCH_EVENT | |||
1042 | #undef EVENT | |||
1043 | {nullptr}}; | |||
1044 | // Subtract one from the length because of the trailing null | |||
1045 | for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) { | |||
1046 | sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom, | |||
1047 | touchEventArray[i]); | |||
1048 | sStringEventTable->InsertOrUpdate( | |||
1049 | Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2), | |||
1050 | touchEventArray[i]); | |||
1051 | } | |||
1052 | } | |||
1053 | } | |||
1054 | ||||
1055 | static bool Is8bit(const nsAString& aString) { | |||
1056 | static const char16_t EIGHT_BIT = char16_t(~0x00FF); | |||
1057 | ||||
1058 | for (nsAString::const_char_iterator start = aString.BeginReading(), | |||
1059 | end = aString.EndReading(); | |||
1060 | start != end; ++start) { | |||
1061 | if (*start & EIGHT_BIT) { | |||
1062 | return false; | |||
1063 | } | |||
1064 | } | |||
1065 | ||||
1066 | return true; | |||
1067 | } | |||
1068 | ||||
1069 | nsresult nsContentUtils::Btoa(const nsAString& aBinaryData, | |||
1070 | nsAString& aAsciiBase64String) { | |||
1071 | if (!Is8bit(aBinaryData)) { | |||
1072 | aAsciiBase64String.Truncate(); | |||
1073 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
1074 | } | |||
1075 | ||||
1076 | return Base64Encode(aBinaryData, aAsciiBase64String); | |||
1077 | } | |||
1078 | ||||
1079 | nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String, | |||
1080 | nsAString& aBinaryData) { | |||
1081 | if (!Is8bit(aAsciiBase64String)) { | |||
1082 | aBinaryData.Truncate(); | |||
1083 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
1084 | } | |||
1085 | ||||
1086 | const char16_t* start = aAsciiBase64String.BeginReading(); | |||
1087 | const char16_t* cur = start; | |||
1088 | const char16_t* end = aAsciiBase64String.EndReading(); | |||
1089 | bool hasWhitespace = false; | |||
1090 | ||||
1091 | while (cur < end) { | |||
1092 | if (nsContentUtils::IsHTMLWhitespace(*cur)) { | |||
1093 | hasWhitespace = true; | |||
1094 | break; | |||
1095 | } | |||
1096 | cur++; | |||
1097 | } | |||
1098 | ||||
1099 | nsresult rv; | |||
1100 | ||||
1101 | if (hasWhitespace) { | |||
1102 | nsString trimmedString; | |||
1103 | ||||
1104 | if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) { | |||
1105 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
1106 | } | |||
1107 | ||||
1108 | trimmedString.Append(start, cur - start); | |||
1109 | ||||
1110 | while (cur < end) { | |||
1111 | if (!nsContentUtils::IsHTMLWhitespace(*cur)) { | |||
1112 | trimmedString.Append(*cur); | |||
1113 | } | |||
1114 | cur++; | |||
1115 | } | |||
1116 | rv = Base64Decode(trimmedString, aBinaryData); | |||
1117 | } else { | |||
1118 | rv = Base64Decode(aAsciiBase64String, aBinaryData); | |||
1119 | } | |||
1120 | ||||
1121 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) { | |||
1122 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
1123 | } | |||
1124 | return rv; | |||
1125 | } | |||
1126 | ||||
1127 | bool nsContentUtils::IsAutocompleteEnabled( | |||
1128 | mozilla::dom::HTMLInputElement* aInput) { | |||
1129 | MOZ_ASSERT(aInput, "aInput should not be null!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aInput)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aInput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aInput" " (" "aInput should not be null!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInput" ") (" "aInput should not be null!" ")"); do { *((volatile int*)__null ) = 1129; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
1130 | ||||
1131 | nsAutoString autocomplete; | |||
1132 | aInput->GetAutocomplete(autocomplete); | |||
1133 | ||||
1134 | if (autocomplete.IsEmpty()) { | |||
1135 | auto* form = aInput->GetForm(); | |||
1136 | if (!form) { | |||
1137 | return true; | |||
1138 | } | |||
1139 | ||||
1140 | form->GetAutocomplete(autocomplete); | |||
1141 | } | |||
1142 | ||||
1143 | return !autocomplete.EqualsLiteral("off"); | |||
1144 | } | |||
1145 | ||||
1146 | nsContentUtils::AutocompleteAttrState | |||
1147 | nsContentUtils::SerializeAutocompleteAttribute( | |||
1148 | const nsAttrValue* aAttr, nsAString& aResult, | |||
1149 | AutocompleteAttrState aCachedState) { | |||
1150 | if (!aAttr || | |||
1151 | aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { | |||
1152 | return aCachedState; | |||
1153 | } | |||
1154 | ||||
1155 | if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) { | |||
1156 | uint32_t atomCount = aAttr->GetAtomCount(); | |||
1157 | for (uint32_t i = 0; i < atomCount; i++) { | |||
1158 | if (i != 0) { | |||
1159 | aResult.Append(' '); | |||
1160 | } | |||
1161 | aResult.Append(nsDependentAtomString(aAttr->AtomAt(i))); | |||
1162 | } | |||
1163 | nsContentUtils::ASCIIToLower(aResult); | |||
1164 | return aCachedState; | |||
1165 | } | |||
1166 | ||||
1167 | aResult.Truncate(); | |||
1168 | ||||
1169 | mozilla::dom::AutocompleteInfo info; | |||
1170 | AutocompleteAttrState state = | |||
1171 | InternalSerializeAutocompleteAttribute(aAttr, info); | |||
1172 | if (state == eAutocompleteAttrState_Valid) { | |||
1173 | // Concatenate the info fields. | |||
1174 | aResult = info.mSection; | |||
1175 | ||||
1176 | if (!info.mAddressType.IsEmpty()) { | |||
1177 | if (!aResult.IsEmpty()) { | |||
1178 | aResult += ' '; | |||
1179 | } | |||
1180 | aResult += info.mAddressType; | |||
1181 | } | |||
1182 | ||||
1183 | if (!info.mContactType.IsEmpty()) { | |||
1184 | if (!aResult.IsEmpty()) { | |||
1185 | aResult += ' '; | |||
1186 | } | |||
1187 | aResult += info.mContactType; | |||
1188 | } | |||
1189 | ||||
1190 | if (!info.mFieldName.IsEmpty()) { | |||
1191 | if (!aResult.IsEmpty()) { | |||
1192 | aResult += ' '; | |||
1193 | } | |||
1194 | aResult += info.mFieldName; | |||
1195 | } | |||
1196 | ||||
1197 | // The autocomplete attribute value "webauthn" is interpreted as both a | |||
1198 | // field name and a credential type. The corresponding IDL-exposed autofill | |||
1199 | // value is "webauthn", not "webauthn webauthn". | |||
1200 | if (!info.mCredentialType.IsEmpty() && | |||
1201 | !(info.mCredentialType.Equals(u"webauthn"_ns) && | |||
1202 | info.mCredentialType.Equals(aResult))) { | |||
1203 | if (!aResult.IsEmpty()) { | |||
1204 | aResult += ' '; | |||
1205 | } | |||
1206 | aResult += info.mCredentialType; | |||
1207 | } | |||
1208 | } | |||
1209 | ||||
1210 | return state; | |||
1211 | } | |||
1212 | ||||
1213 | nsContentUtils::AutocompleteAttrState | |||
1214 | nsContentUtils::SerializeAutocompleteAttribute( | |||
1215 | const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo, | |||
1216 | AutocompleteAttrState aCachedState, bool aGrantAllValidValue) { | |||
1217 | if (!aAttr || | |||
1218 | aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { | |||
1219 | return aCachedState; | |||
1220 | } | |||
1221 | ||||
1222 | return InternalSerializeAutocompleteAttribute(aAttr, aInfo, | |||
1223 | aGrantAllValidValue); | |||
1224 | } | |||
1225 | ||||
1226 | /** | |||
1227 | * Helper to validate the @autocomplete tokens. | |||
1228 | * | |||
1229 | * @return {AutocompleteAttrState} The state of the attribute (invalid/valid). | |||
1230 | */ | |||
1231 | nsContentUtils::AutocompleteAttrState | |||
1232 | nsContentUtils::InternalSerializeAutocompleteAttribute( | |||
1233 | const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo, | |||
1234 | bool aGrantAllValidValue) { | |||
1235 | // No autocomplete attribute so we are done | |||
1236 | if (!aAttrVal) { | |||
1237 | return eAutocompleteAttrState_Invalid; | |||
1238 | } | |||
1239 | ||||
1240 | uint32_t numTokens = aAttrVal->GetAtomCount(); | |||
1241 | if (!numTokens || numTokens > INT32_MAX(2147483647)) { | |||
1242 | return eAutocompleteAttrState_Invalid; | |||
1243 | } | |||
1244 | ||||
1245 | uint32_t index = numTokens - 1; | |||
1246 | nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
1247 | AutocompleteCategory category; | |||
1248 | nsAttrValue enumValue; | |||
1249 | nsAutoString credentialTypeStr; | |||
1250 | ||||
1251 | bool result = enumValue.ParseEnumValue( | |||
1252 | tokenString, kAutocompleteCredentialTypeTable, false); | |||
1253 | if (result) { | |||
1254 | if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) { | |||
1255 | return eAutocompleteAttrState_Invalid; | |||
1256 | } | |||
1257 | enumValue.ToString(credentialTypeStr); | |||
1258 | ASCIIToLower(credentialTypeStr); | |||
1259 | // category is Credential and the indexth token is "webauthn" | |||
1260 | if (index == 0) { | |||
1261 | aInfo.mFieldName.Assign(credentialTypeStr); | |||
1262 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
1263 | return eAutocompleteAttrState_Valid; | |||
1264 | } | |||
1265 | ||||
1266 | --index; | |||
1267 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
1268 | ||||
1269 | // Only the Normal and Contact categories are allowed with webauthn | |||
1270 | // - disallow Credential | |||
1271 | if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable, | |||
1272 | false)) { | |||
1273 | return eAutocompleteAttrState_Invalid; | |||
1274 | } | |||
1275 | // - disallow Off and Automatic | |||
1276 | if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, | |||
1277 | false)) { | |||
1278 | if (enumValue.Equals(u"off"_ns, eIgnoreCase) || | |||
1279 | enumValue.Equals(u"on"_ns, eIgnoreCase)) { | |||
1280 | return eAutocompleteAttrState_Invalid; | |||
1281 | } | |||
1282 | } | |||
1283 | ||||
1284 | // Proceed to process the remaining tokens as if "webauthn" was not present. | |||
1285 | // We need to decrement numTokens to enforce the correct per-category limits | |||
1286 | // on the maximum number of tokens. | |||
1287 | --numTokens; | |||
1288 | } | |||
1289 | ||||
1290 | bool unsupported = false; | |||
1291 | if (!aGrantAllValidValue) { | |||
1292 | unsupported = enumValue.ParseEnumValue( | |||
1293 | tokenString, kAutocompleteUnsupportedFieldNameTable, false); | |||
1294 | if (unsupported) { | |||
1295 | return eAutocompleteAttrState_Invalid; | |||
1296 | } | |||
1297 | } | |||
1298 | ||||
1299 | nsAutoString fieldNameStr; | |||
1300 | result = | |||
1301 | enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false); | |||
1302 | ||||
1303 | if (result) { | |||
1304 | // Off/Automatic/Normal categories. | |||
1305 | if (enumValue.Equals(u"off"_ns, eIgnoreCase) || | |||
1306 | enumValue.Equals(u"on"_ns, eIgnoreCase)) { | |||
1307 | if (numTokens > 1) { | |||
1308 | return eAutocompleteAttrState_Invalid; | |||
1309 | } | |||
1310 | enumValue.ToString(fieldNameStr); | |||
1311 | ASCIIToLower(fieldNameStr); | |||
1312 | aInfo.mFieldName.Assign(fieldNameStr); | |||
1313 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
1314 | aInfo.mCanAutomaticallyPersist = | |||
1315 | !enumValue.Equals(u"off"_ns, eIgnoreCase); | |||
1316 | return eAutocompleteAttrState_Valid; | |||
1317 | } | |||
1318 | ||||
1319 | // Only allow on/off if form autofill @autocomplete values aren't enabled | |||
1320 | // and it doesn't grant all valid values. | |||
1321 | if (!StaticPrefs::dom_forms_autocomplete_formautofill() && | |||
1322 | !aGrantAllValidValue) { | |||
1323 | return eAutocompleteAttrState_Invalid; | |||
1324 | } | |||
1325 | ||||
1326 | // Normal category | |||
1327 | if (numTokens > 3) { | |||
1328 | return eAutocompleteAttrState_Invalid; | |||
1329 | } | |||
1330 | category = eAutocompleteCategory_NORMAL; | |||
1331 | } else { // Check if the last token is of the contact category instead. | |||
1332 | // Only allow on/off if form autofill @autocomplete values aren't enabled | |||
1333 | // and it doesn't grant all valid values. | |||
1334 | if (!StaticPrefs::dom_forms_autocomplete_formautofill() && | |||
1335 | !aGrantAllValidValue) { | |||
1336 | return eAutocompleteAttrState_Invalid; | |||
1337 | } | |||
1338 | ||||
1339 | result = enumValue.ParseEnumValue( | |||
1340 | tokenString, kAutocompleteContactFieldNameTable, false); | |||
1341 | if (!result || numTokens > 4) { | |||
1342 | return eAutocompleteAttrState_Invalid; | |||
1343 | } | |||
1344 | ||||
1345 | category = eAutocompleteCategory_CONTACT; | |||
1346 | } | |||
1347 | ||||
1348 | enumValue.ToString(fieldNameStr); | |||
1349 | ASCIIToLower(fieldNameStr); | |||
1350 | ||||
1351 | aInfo.mFieldName.Assign(fieldNameStr); | |||
1352 | aInfo.mCredentialType.Assign(credentialTypeStr); | |||
1353 | aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue( | |||
1354 | tokenString, kAutocompleteNoPersistFieldNameTable, false); | |||
1355 | ||||
1356 | // We are done if this was the only token. | |||
1357 | if (numTokens == 1) { | |||
1358 | return eAutocompleteAttrState_Valid; | |||
1359 | } | |||
1360 | ||||
1361 | --index; | |||
1362 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
1363 | ||||
1364 | if (category == eAutocompleteCategory_CONTACT) { | |||
1365 | if (!aGrantAllValidValue) { | |||
1366 | unsupported = enumValue.ParseEnumValue( | |||
1367 | tokenString, kAutocompleteUnsupportedContactFieldHintTable, false); | |||
1368 | if (unsupported) { | |||
1369 | return eAutocompleteAttrState_Invalid; | |||
1370 | } | |||
1371 | } | |||
1372 | ||||
1373 | nsAttrValue contactFieldHint; | |||
1374 | result = contactFieldHint.ParseEnumValue( | |||
1375 | tokenString, kAutocompleteContactFieldHintTable, false); | |||
1376 | if (result) { | |||
1377 | nsAutoString contactFieldHintString; | |||
1378 | contactFieldHint.ToString(contactFieldHintString); | |||
1379 | ASCIIToLower(contactFieldHintString); | |||
1380 | aInfo.mContactType.Assign(contactFieldHintString); | |||
1381 | if (index == 0) { | |||
1382 | return eAutocompleteAttrState_Valid; | |||
1383 | } | |||
1384 | --index; | |||
1385 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
1386 | } | |||
1387 | } | |||
1388 | ||||
1389 | // Check for billing/shipping tokens | |||
1390 | nsAttrValue fieldHint; | |||
1391 | if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, | |||
1392 | false)) { | |||
1393 | nsString fieldHintString; | |||
1394 | fieldHint.ToString(fieldHintString); | |||
1395 | ASCIIToLower(fieldHintString); | |||
1396 | aInfo.mAddressType.Assign(fieldHintString); | |||
1397 | if (index == 0) { | |||
1398 | return eAutocompleteAttrState_Valid; | |||
1399 | } | |||
1400 | --index; | |||
1401 | tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); | |||
1402 | } | |||
1403 | ||||
1404 | // Check for section-* token | |||
1405 | const nsDependentSubstring& section = Substring(tokenString, 0, 8); | |||
1406 | if (section.LowerCaseEqualsASCII("section-")) { | |||
1407 | ASCIIToLower(tokenString); | |||
1408 | aInfo.mSection.Assign(tokenString); | |||
1409 | if (index == 0) { | |||
1410 | return eAutocompleteAttrState_Valid; | |||
1411 | } | |||
1412 | } | |||
1413 | ||||
1414 | // Clear the fields as the autocomplete attribute is invalid. | |||
1415 | aInfo.mSection.Truncate(); | |||
1416 | aInfo.mAddressType.Truncate(); | |||
1417 | aInfo.mContactType.Truncate(); | |||
1418 | aInfo.mFieldName.Truncate(); | |||
1419 | aInfo.mCredentialType.Truncate(); | |||
1420 | ||||
1421 | return eAutocompleteAttrState_Invalid; | |||
1422 | } | |||
1423 | ||||
1424 | // Parse an integer according to HTML spec | |||
1425 | template <class CharT> | |||
1426 | int32_t nsContentUtils::ParseHTMLIntegerImpl( | |||
1427 | const CharT* aStart, const CharT* aEnd, | |||
1428 | ParseHTMLIntegerResultFlags* aResult) { | |||
1429 | int result = eParseHTMLInteger_NoFlags; | |||
1430 | ||||
1431 | const CharT* iter = aStart; | |||
1432 | ||||
1433 | while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) { | |||
1434 | result |= eParseHTMLInteger_NonStandard; | |||
1435 | ++iter; | |||
1436 | } | |||
1437 | ||||
1438 | if (iter == aEnd) { | |||
1439 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; | |||
1440 | *aResult = (ParseHTMLIntegerResultFlags)result; | |||
1441 | return 0; | |||
1442 | } | |||
1443 | ||||
1444 | int sign = 1; | |||
1445 | if (*iter == CharT('-')) { | |||
1446 | sign = -1; | |||
1447 | result |= eParseHTMLInteger_Negative; | |||
1448 | ++iter; | |||
1449 | } else if (*iter == CharT('+')) { | |||
1450 | result |= eParseHTMLInteger_NonStandard; | |||
1451 | ++iter; | |||
1452 | } | |||
1453 | ||||
1454 | bool foundValue = false; | |||
1455 | CheckedInt32 value = 0; | |||
1456 | ||||
1457 | // Check for leading zeros first. | |||
1458 | uint64_t leadingZeros = 0; | |||
1459 | while (iter != aEnd) { | |||
1460 | if (*iter != CharT('0')) { | |||
1461 | break; | |||
1462 | } | |||
1463 | ||||
1464 | ++leadingZeros; | |||
1465 | foundValue = true; | |||
1466 | ++iter; | |||
1467 | } | |||
1468 | ||||
1469 | while (iter != aEnd) { | |||
1470 | if (*iter >= CharT('0') && *iter <= CharT('9')) { | |||
1471 | value = (value * 10) + (*iter - CharT('0')) * sign; | |||
1472 | ++iter; | |||
1473 | if (!value.isValid()) { | |||
1474 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow; | |||
1475 | break; | |||
1476 | } | |||
1477 | foundValue = true; | |||
1478 | } else { | |||
1479 | break; | |||
1480 | } | |||
1481 | } | |||
1482 | ||||
1483 | if (!foundValue) { | |||
1484 | result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue; | |||
1485 | } | |||
1486 | ||||
1487 | if (value.isValid() && | |||
1488 | ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) || | |||
1489 | (sign == -1 && value == 0))) { | |||
1490 | result |= eParseHTMLInteger_NonStandard; | |||
1491 | } | |||
1492 | ||||
1493 | if (iter != aEnd) { | |||
1494 | result |= eParseHTMLInteger_DidNotConsumeAllInput; | |||
1495 | } | |||
1496 | ||||
1497 | *aResult = (ParseHTMLIntegerResultFlags)result; | |||
1498 | return value.isValid() ? value.value() : 0; | |||
1499 | } | |||
1500 | ||||
1501 | // Parse an integer according to HTML spec | |||
1502 | int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart, | |||
1503 | const char16_t* aEnd, | |||
1504 | ParseHTMLIntegerResultFlags* aResult) { | |||
1505 | return ParseHTMLIntegerImpl(aStart, aEnd, aResult); | |||
1506 | } | |||
1507 | ||||
1508 | int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd, | |||
1509 | ParseHTMLIntegerResultFlags* aResult) { | |||
1510 | return ParseHTMLIntegerImpl(aStart, aEnd, aResult); | |||
1511 | } | |||
1512 | ||||
1513 | #define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*( iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res ); } \ | |||
1514 | while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \ | |||
1515 | ++(iter); \ | |||
1516 | } \ | |||
1517 | if ((iter) == (end_iter)) { \ | |||
1518 | return (end_res); \ | |||
1519 | } | |||
1520 | ||||
1521 | #define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(* (iter)) && *(iter) != '=') { ++(iter); } \ | |||
1522 | while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \ | |||
1523 | *(iter) != '=') { \ | |||
1524 | ++(iter); \ | |||
1525 | } | |||
1526 | ||||
1527 | bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, | |||
1528 | nsAtom* aName, nsAString& aValue) { | |||
1529 | aValue.Truncate(); | |||
1530 | ||||
1531 | const char16_t* start = aSource.get(); | |||
1532 | const char16_t* end = start + aSource.Length(); | |||
1533 | const char16_t* iter; | |||
1534 | ||||
1535 | while (start != end) { | |||
1536 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
1537 | iter = start; | |||
1538 | SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter )) && *(iter) != '=') { ++(iter); } | |||
1539 | ||||
1540 | if (start == iter) { | |||
1541 | return false; | |||
1542 | } | |||
1543 | ||||
1544 | // Remember the attr name. | |||
1545 | const nsDependentSubstring& attrName = Substring(start, iter); | |||
1546 | ||||
1547 | // Now check whether this is a valid name="value" pair. | |||
1548 | start = iter; | |||
1549 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
1550 | if (*start != '=') { | |||
1551 | // No '=', so this is not a name="value" pair. We don't know | |||
1552 | // what it is, and we have no way to handle it. | |||
1553 | return false; | |||
1554 | } | |||
1555 | ||||
1556 | // Have to skip the value. | |||
1557 | ++start; | |||
1558 | SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start ))) { ++(start); } if ((start) == (end)) { return (false); } | |||
1559 | char16_t q = *start; | |||
1560 | if (q != kQuote && q != kApostrophe) { | |||
1561 | // Not a valid quoted value, so bail. | |||
1562 | return false; | |||
1563 | } | |||
1564 | ||||
1565 | ++start; // Point to the first char of the value. | |||
1566 | iter = start; | |||
1567 | ||||
1568 | while (iter != end && *iter != q) { | |||
1569 | ++iter; | |||
1570 | } | |||
1571 | ||||
1572 | if (iter == end) { | |||
1573 | // Oops, unterminated quoted string. | |||
1574 | return false; | |||
1575 | } | |||
1576 | ||||
1577 | // At this point attrName holds the name of the "attribute" and | |||
1578 | // the value is between start and iter. | |||
1579 | ||||
1580 | if (aName->Equals(attrName)) { | |||
1581 | // We'll accumulate as many characters as possible (until we hit either | |||
1582 | // the end of the string or the beginning of an entity). Chunks will be | |||
1583 | // delimited by start and chunkEnd. | |||
1584 | const char16_t* chunkEnd = start; | |||
1585 | while (chunkEnd != iter) { | |||
1586 | if (*chunkEnd == kLessThan) { | |||
1587 | aValue.Truncate(); | |||
1588 | ||||
1589 | return false; | |||
1590 | } | |||
1591 | ||||
1592 | if (*chunkEnd == kAmpersand) { | |||
1593 | aValue.Append(start, chunkEnd - start); | |||
1594 | ||||
1595 | const char16_t* afterEntity = nullptr; | |||
1596 | char16_t result[2]; | |||
1597 | uint32_t count = MOZ_XMLTranslateEntity( | |||
1598 | reinterpret_cast<const char*>(chunkEnd), | |||
1599 | reinterpret_cast<const char*>(iter), | |||
1600 | reinterpret_cast<const char**>(&afterEntity), result); | |||
1601 | if (count == 0) { | |||
1602 | aValue.Truncate(); | |||
1603 | ||||
1604 | return false; | |||
1605 | } | |||
1606 | ||||
1607 | aValue.Append(result, count); | |||
1608 | ||||
1609 | // Advance to after the entity and begin a new chunk. | |||
1610 | start = chunkEnd = afterEntity; | |||
1611 | } else { | |||
1612 | ++chunkEnd; | |||
1613 | } | |||
1614 | } | |||
1615 | ||||
1616 | // Append remainder. | |||
1617 | aValue.Append(start, iter - start); | |||
1618 | ||||
1619 | return true; | |||
1620 | } | |||
1621 | ||||
1622 | // Resume scanning after the end of the attribute value (past the quote | |||
1623 | // char). | |||
1624 | start = iter + 1; | |||
1625 | } | |||
1626 | ||||
1627 | return false; | |||
1628 | } | |||
1629 | ||||
1630 | bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) { | |||
1631 | // Create MIME type as "text/" + given input | |||
1632 | nsAutoString mimeType(u"text/"); | |||
1633 | mimeType.Append(aName); | |||
1634 | ||||
1635 | return IsJavascriptMIMEType(mimeType); | |||
1636 | } | |||
1637 | ||||
1638 | void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType, | |||
1639 | nsString& aParams) { | |||
1640 | aType.Truncate(); | |||
1641 | aParams.Truncate(); | |||
1642 | int32_t semiIndex = aValue.FindChar(char16_t(';')); | |||
1643 | if (-1 != semiIndex) { | |||
1644 | aType = Substring(aValue, 0, semiIndex); | |||
1645 | aParams = | |||
1646 | Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1)); | |||
1647 | aParams.StripWhitespace(); | |||
1648 | } else { | |||
1649 | aType = aValue; | |||
1650 | } | |||
1651 | aType.StripWhitespace(); | |||
1652 | } | |||
1653 | ||||
1654 | /** | |||
1655 | * A helper function that parses a sandbox attribute (of an <iframe> or a CSP | |||
1656 | * directive) and converts it to the set of flags used internally. | |||
1657 | * | |||
1658 | * @param aSandboxAttr the sandbox attribute | |||
1659 | * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is | |||
1660 | * null) | |||
1661 | */ | |||
1662 | uint32_t nsContentUtils::ParseSandboxAttributeToFlags( | |||
1663 | const nsAttrValue* aSandboxAttr) { | |||
1664 | if (!aSandboxAttr) { | |||
1665 | return SANDBOXED_NONE; | |||
1666 | } | |||
1667 | ||||
1668 | uint32_t out = SANDBOX_ALL_FLAGS; | |||
1669 | ||||
1670 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
1671 | if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \ | |||
1672 | out &= ~(flags); \ | |||
1673 | } | |||
1674 | #include "IframeSandboxKeywordList.h" | |||
1675 | #undef SANDBOX_KEYWORD | |||
1676 | ||||
1677 | return out; | |||
1678 | } | |||
1679 | ||||
1680 | /** | |||
1681 | * A helper function that checks if a string matches a valid sandbox flag. | |||
1682 | * | |||
1683 | * @param aFlag the potential sandbox flag. | |||
1684 | * @return true if the flag is a sandbox flag. | |||
1685 | */ | |||
1686 | bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) { | |||
1687 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
1688 | if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \ | |||
1689 | return true; \ | |||
1690 | } | |||
1691 | #include "IframeSandboxKeywordList.h" | |||
1692 | #undef SANDBOX_KEYWORD | |||
1693 | return false; | |||
1694 | } | |||
1695 | ||||
1696 | /** | |||
1697 | * A helper function that returns a string attribute corresponding to the | |||
1698 | * sandbox flags. | |||
1699 | * | |||
1700 | * @param aFlags the sandbox flags | |||
1701 | * @param aString the attribute corresponding to the flags (null if aFlags | |||
1702 | * is zero) | |||
1703 | */ | |||
1704 | void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) { | |||
1705 | if (!aFlags) { | |||
1706 | SetDOMStringToNull(aString); | |||
1707 | return; | |||
1708 | } | |||
1709 | ||||
1710 | aString.Truncate(); | |||
1711 | ||||
1712 | #define SANDBOX_KEYWORD(string, atom, flags) \ | |||
1713 | if (!(aFlags & (flags))) { \ | |||
1714 | if (!aString.IsEmpty()) { \ | |||
1715 | aString.AppendLiteral(u" "); \ | |||
1716 | } \ | |||
1717 | aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \ | |||
1718 | } | |||
1719 | #include "IframeSandboxKeywordList.h" | |||
1720 | #undef SANDBOX_KEYWORD | |||
1721 | } | |||
1722 | ||||
1723 | nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() { | |||
1724 | if (!sBidiKeyboard) { | |||
1725 | sBidiKeyboard = nsIWidget::CreateBidiKeyboard(); | |||
1726 | } | |||
1727 | return sBidiKeyboard; | |||
1728 | } | |||
1729 | ||||
1730 | /** | |||
1731 | * This is used to determine whether a character is in one of the classes | |||
1732 | * which CSS says should be part of the first-letter. Currently, that is | |||
1733 | * all punctuation classes (P*). Note that this is a change from CSS2 | |||
1734 | * which excluded Pc and Pd. | |||
1735 | * | |||
1736 | * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo | |||
1737 | * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode | |||
1738 | * general category [UAX44]) [...]" | |||
1739 | */ | |||
1740 | ||||
1741 | // static | |||
1742 | bool nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar) { | |||
1743 | switch (mozilla::unicode::GetGeneralCategory(aChar)) { | |||
1744 | case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */ | |||
1745 | case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */ | |||
1746 | case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */ | |||
1747 | case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */ | |||
1748 | case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */ | |||
1749 | case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */ | |||
1750 | case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */ | |||
1751 | return true; | |||
1752 | default: | |||
1753 | return false; | |||
1754 | } | |||
1755 | } | |||
1756 | ||||
1757 | // static | |||
1758 | bool nsContentUtils::IsAlphanumeric(uint32_t aChar) { | |||
1759 | nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar); | |||
1760 | ||||
1761 | return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber); | |||
1762 | } | |||
1763 | ||||
1764 | // static | |||
1765 | bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) { | |||
1766 | nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar); | |||
1767 | ||||
1768 | return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber || | |||
1769 | cat == nsUGenCategory::kSymbol; | |||
1770 | } | |||
1771 | ||||
1772 | // static | |||
1773 | bool nsContentUtils::IsHyphen(uint32_t aChar) { | |||
1774 | // Characters treated as hyphens for the purpose of "emergency" breaking | |||
1775 | // when the content would otherwise overflow. | |||
1776 | return aChar == uint32_t('-') || // HYPHEN-MINUS | |||
1777 | aChar == 0x2010 || // HYPHEN | |||
1778 | aChar == 0x2012 || // FIGURE DASH | |||
1779 | aChar == 0x2013 || // EN DASH | |||
1780 | aChar == 0x058A; // ARMENIAN HYPHEN | |||
1781 | } | |||
1782 | ||||
1783 | /* static */ | |||
1784 | bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) { | |||
1785 | return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) || | |||
1786 | aChar == char16_t(0x000C) || aChar == char16_t(0x000D) || | |||
1787 | aChar == char16_t(0x0020); | |||
1788 | } | |||
1789 | ||||
1790 | /* static */ | |||
1791 | bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) { | |||
1792 | return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0); | |||
1793 | } | |||
1794 | ||||
1795 | /* static */ | |||
1796 | bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) { | |||
1797 | return aContent->IsAnyOfHTMLElements( | |||
1798 | nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside, | |||
1799 | nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div, | |||
1800 | nsGkAtoms::dl, // XXX why not dt and dd? | |||
1801 | nsGkAtoms::fieldset, | |||
1802 | nsGkAtoms::figure, // XXX shouldn't figcaption be on this list | |||
1803 | nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2, | |||
1804 | nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, | |||
1805 | nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li, | |||
1806 | nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol, | |||
1807 | nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table, | |||
1808 | nsGkAtoms::ul, nsGkAtoms::xmp); | |||
1809 | } | |||
1810 | ||||
1811 | /* static */ | |||
1812 | bool nsContentUtils::ParseIntMarginValue(const nsAString& aString, | |||
1813 | nsIntMargin& result) { | |||
1814 | nsAutoString marginStr(aString); | |||
1815 | marginStr.CompressWhitespace(true, true); | |||
1816 | if (marginStr.IsEmpty()) { | |||
1817 | return false; | |||
1818 | } | |||
1819 | ||||
1820 | int32_t start = 0, end = 0; | |||
1821 | for (int count = 0; count < 4; count++) { | |||
1822 | if ((uint32_t)end >= marginStr.Length()) return false; | |||
1823 | ||||
1824 | // top, right, bottom, left | |||
1825 | if (count < 3) | |||
1826 | end = Substring(marginStr, start).FindChar(','); | |||
1827 | else | |||
1828 | end = Substring(marginStr, start).Length(); | |||
1829 | ||||
1830 | if (end <= 0) return false; | |||
1831 | ||||
1832 | nsresult ec; | |||
1833 | int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec); | |||
1834 | if (NS_FAILED(ec)((bool)(__builtin_expect(!!(NS_FAILED_impl(ec)), 0)))) return false; | |||
1835 | ||||
1836 | switch (count) { | |||
1837 | case 0: | |||
1838 | result.top = val; | |||
1839 | break; | |||
1840 | case 1: | |||
1841 | result.right = val; | |||
1842 | break; | |||
1843 | case 2: | |||
1844 | result.bottom = val; | |||
1845 | break; | |||
1846 | case 3: | |||
1847 | result.left = val; | |||
1848 | break; | |||
1849 | } | |||
1850 | start += end + 1; | |||
1851 | } | |||
1852 | return true; | |||
1853 | } | |||
1854 | ||||
1855 | // static | |||
1856 | int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) { | |||
1857 | nsAString::const_iterator iter, end; | |||
1858 | aValue.BeginReading(iter); | |||
1859 | aValue.EndReading(end); | |||
1860 | ||||
1861 | while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { | |||
1862 | ++iter; | |||
1863 | } | |||
1864 | ||||
1865 | if (iter == end) { | |||
1866 | return 0; | |||
1867 | } | |||
1868 | ||||
1869 | bool relative = false; | |||
1870 | bool negate = false; | |||
1871 | if (*iter == char16_t('-')) { | |||
1872 | relative = true; | |||
1873 | negate = true; | |||
1874 | ++iter; | |||
1875 | } else if (*iter == char16_t('+')) { | |||
1876 | relative = true; | |||
1877 | ++iter; | |||
1878 | } | |||
1879 | ||||
1880 | if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) { | |||
1881 | return 0; | |||
1882 | } | |||
1883 | ||||
1884 | // We don't have to worry about overflow, since we can bail out as soon as | |||
1885 | // we're bigger than 7. | |||
1886 | int32_t value = 0; | |||
1887 | while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) { | |||
1888 | value = 10 * value + (*iter - char16_t('0')); | |||
1889 | if (value >= 7) { | |||
1890 | break; | |||
1891 | } | |||
1892 | ++iter; | |||
1893 | } | |||
1894 | ||||
1895 | if (relative) { | |||
1896 | if (negate) { | |||
1897 | value = 3 - value; | |||
1898 | } else { | |||
1899 | value = 3 + value; | |||
1900 | } | |||
1901 | } | |||
1902 | ||||
1903 | return clamped(value, 1, 7); | |||
1904 | } | |||
1905 | ||||
1906 | /* static */ | |||
1907 | void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) { | |||
1908 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1908; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1909 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { *((volatile int*)__null) = 1909; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1910 | *aURI = nullptr; | |||
1911 | ||||
1912 | if (aDocument->GetController().isSome()) { | |||
1913 | return; | |||
1914 | } | |||
1915 | ||||
1916 | Element* docElement = aDocument->GetRootElement(); | |||
1917 | if (!docElement) { | |||
1918 | return; | |||
1919 | } | |||
1920 | ||||
1921 | nsAutoString manifestSpec; | |||
1922 | docElement->GetAttr(nsGkAtoms::manifest, manifestSpec); | |||
1923 | ||||
1924 | // Manifest URIs can't have fragment identifiers. | |||
1925 | if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) { | |||
1926 | return; | |||
1927 | } | |||
1928 | ||||
1929 | nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument, | |||
1930 | aDocument->GetDocBaseURI()); | |||
1931 | } | |||
1932 | ||||
1933 | /* static */ | |||
1934 | bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; } | |||
1935 | ||||
1936 | /* static */ | |||
1937 | bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) { | |||
1938 | return false; | |||
1939 | } | |||
1940 | // Static | |||
1941 | bool nsContentUtils::IsErrorPage(nsIURI* aURI) { | |||
1942 | if (!aURI) { | |||
1943 | return false; | |||
1944 | } | |||
1945 | ||||
1946 | if (!aURI->SchemeIs("about")) { | |||
1947 | return false; | |||
1948 | } | |||
1949 | ||||
1950 | nsAutoCString name; | |||
1951 | nsresult rv = NS_GetAboutModuleName(aURI, name); | |||
1952 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1952); return false; } } while (false); | |||
1953 | ||||
1954 | return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") || | |||
1955 | name.EqualsLiteral("blocked"); | |||
1956 | } | |||
1957 | ||||
1958 | // static | |||
1959 | void nsContentUtils::Shutdown() { | |||
1960 | sInitialized = false; | |||
1961 | ||||
1962 | nsHTMLTags::ReleaseTable(); | |||
1963 | ||||
1964 | NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)-> Release(); (sContentPolicyService) = 0; } } while (0); | |||
1965 | sTriedToGetContentPolicy = false; | |||
1966 | for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) { | |||
1967 | bundle = nullptr; | |||
1968 | } | |||
1969 | ||||
1970 | NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release (); (sStringBundleService) = 0; } } while (0); | |||
1971 | NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); ( sConsoleService) = 0; } } while (0); | |||
1972 | NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect ) = 0; } } while (0); | |||
1973 | NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release() ; (sSecurityManager) = 0; } } while (0); | |||
1974 | NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release() ; (sSystemPrincipal) = 0; } } while (0); | |||
1975 | NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)-> Release(); (sNullSubjectPrincipal) = 0; } } while (0); | |||
1976 | ||||
1977 | sBidiKeyboard = nullptr; | |||
1978 | ||||
1979 | delete sAtomEventTable; | |||
1980 | sAtomEventTable = nullptr; | |||
1981 | delete sStringEventTable; | |||
1982 | sStringEventTable = nullptr; | |||
1983 | delete sUserDefinedEvents; | |||
1984 | sUserDefinedEvents = nullptr; | |||
1985 | ||||
1986 | if (sEventListenerManagersHash) { | |||
1987 | NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0,do { if (!(sEventListenerManagersHash->EntryCount() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Event listener manager hash not empty at shutdown!" , "sEventListenerManagersHash->EntryCount() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1988); MOZ_PretendNoReturn(); } } while (0) | |||
1988 | "Event listener manager hash not empty at shutdown!")do { if (!(sEventListenerManagersHash->EntryCount() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Event listener manager hash not empty at shutdown!" , "sEventListenerManagersHash->EntryCount() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 1988); MOZ_PretendNoReturn(); } } while (0); | |||
1989 | ||||
1990 | // See comment above. | |||
1991 | ||||
1992 | // However, we have to handle this table differently. If it still | |||
1993 | // has entries, we want to leak it too, so that we can keep it alive | |||
1994 | // in case any elements are destroyed. Because if they are, we need | |||
1995 | // their event listener managers to be destroyed too, or otherwise | |||
1996 | // it could leave dangling references in DOMClassInfo's preserved | |||
1997 | // wrapper table. | |||
1998 | ||||
1999 | if (sEventListenerManagersHash->EntryCount() == 0) { | |||
2000 | delete sEventListenerManagersHash; | |||
2001 | sEventListenerManagersHash = nullptr; | |||
2002 | } | |||
2003 | } | |||
2004 | ||||
2005 | if (sDOMArenaHashtable) { | |||
2006 | MOZ_ASSERT(sDOMArenaHashtable->Count() == 0)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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0" ")"); do { *((volatile int*)__null) = 2006; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2007 | MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType< decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()" ")"); do { *((volatile int*)__null) = 2007; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2008 | delete sDOMArenaHashtable; | |||
2009 | sDOMArenaHashtable = nullptr; | |||
2010 | } | |||
2011 | ||||
2012 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2013); MOZ_PretendNoReturn(); } } while (0) | |||
2013 | "How'd this happen?")do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners-> Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?" , "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2013); MOZ_PretendNoReturn(); } } while (0); | |||
2014 | delete sBlockedScriptRunners; | |||
2015 | sBlockedScriptRunners = nullptr; | |||
2016 | ||||
2017 | delete sShiftText; | |||
2018 | sShiftText = nullptr; | |||
2019 | delete sControlText; | |||
2020 | sControlText = nullptr; | |||
2021 | delete sCommandOrWinText; | |||
2022 | sCommandOrWinText = nullptr; | |||
2023 | delete sAltText; | |||
2024 | sAltText = nullptr; | |||
2025 | delete sModifierSeparator; | |||
2026 | sModifierSeparator = nullptr; | |||
2027 | ||||
2028 | delete sJSScriptBytecodeMimeType; | |||
2029 | sJSScriptBytecodeMimeType = nullptr; | |||
2030 | ||||
2031 | delete sJSModuleBytecodeMimeType; | |||
2032 | sJSModuleBytecodeMimeType = nullptr; | |||
2033 | ||||
2034 | NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release (); (sSameOriginChecker) = 0; } } while (0); | |||
2035 | ||||
2036 | if (sUserInteractionObserver) { | |||
2037 | sUserInteractionObserver->Shutdown(); | |||
2038 | NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver ) = 0; } while (0); | |||
2039 | } | |||
2040 | ||||
2041 | for (const auto& pref : kRfpPrefs) { | |||
2042 | Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref); | |||
2043 | } | |||
2044 | ||||
2045 | TextControlState::Shutdown(); | |||
2046 | } | |||
2047 | ||||
2048 | /** | |||
2049 | * Checks whether two nodes come from the same origin. aTrustedNode is | |||
2050 | * considered 'safe' in that a user can operate on it. | |||
2051 | */ | |||
2052 | // static | |||
2053 | nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode, | |||
2054 | const nsINode* unTrustedNode) { | |||
2055 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode" ")"); do { *((volatile int*)__null) = 2055; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2056 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "unTrustedNode" ")"); do { *((volatile int*)__null) = 2056; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2057 | ||||
2058 | /* | |||
2059 | * Get hold of each node's principal | |||
2060 | */ | |||
2061 | ||||
2062 | nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal(); | |||
2063 | nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal(); | |||
2064 | ||||
2065 | if (trustedPrincipal == unTrustedPrincipal) { | |||
2066 | return NS_OK; | |||
2067 | } | |||
2068 | ||||
2069 | bool equal; | |||
2070 | // XXXbz should we actually have a Subsumes() check here instead? Or perhaps | |||
2071 | // a separate method for that, with callers using one or the other? | |||
2072 | if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal-> Equals(unTrustedPrincipal, &equal))), 0))) || | |||
2073 | !equal) { | |||
2074 | return NS_ERROR_DOM_PROP_ACCESS_DENIED; | |||
2075 | } | |||
2076 | ||||
2077 | return NS_OK; | |||
2078 | } | |||
2079 | ||||
2080 | // static | |||
2081 | bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal, | |||
2082 | nsIPrincipal* aPrincipal) { | |||
2083 | bool subsumes; | |||
2084 | nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes); | |||
2085 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2085); return false; } } while (false); | |||
2086 | ||||
2087 | if (subsumes) { | |||
2088 | return true; | |||
2089 | } | |||
2090 | ||||
2091 | // The subject doesn't subsume aPrincipal. Allow access only if the subject | |||
2092 | // is chrome. | |||
2093 | return IsCallerChrome(); | |||
2094 | } | |||
2095 | ||||
2096 | // static | |||
2097 | bool nsContentUtils::CanCallerAccess(const nsINode* aNode) { | |||
2098 | nsIPrincipal* subject = SubjectPrincipal(); | |||
2099 | if (subject->IsSystemPrincipal()) { | |||
2100 | return true; | |||
2101 | } | |||
2102 | ||||
2103 | if (aNode->ChromeOnlyAccess()) { | |||
2104 | return false; | |||
2105 | } | |||
2106 | ||||
2107 | return CanCallerAccess(subject, aNode->NodePrincipal()); | |||
2108 | } | |||
2109 | ||||
2110 | // static | |||
2111 | bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) { | |||
2112 | nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow); | |||
2113 | NS_ENSURE_TRUE(scriptObject, false)do { if ((__builtin_expect(!!(!(scriptObject)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptObject" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2113); return false; } } while (false); | |||
2114 | ||||
2115 | return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal()); | |||
2116 | } | |||
2117 | ||||
2118 | // static | |||
2119 | bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal, | |||
2120 | const nsAtom* aPerm) { | |||
2121 | // Chrome gets access by default. | |||
2122 | if (aPrincipal.IsSystemPrincipal()) { | |||
2123 | return true; | |||
2124 | } | |||
2125 | ||||
2126 | // Otherwise, only allow if caller is an addon with the permission. | |||
2127 | return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm); | |||
2128 | } | |||
2129 | ||||
2130 | // static | |||
2131 | bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) { | |||
2132 | return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm); | |||
2133 | } | |||
2134 | ||||
2135 | // static | |||
2136 | nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal( | |||
2137 | nsIContent* aContent, const nsAString& aAttrValue, | |||
2138 | nsIPrincipal* aSubjectPrincipal) { | |||
2139 | nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr; | |||
2140 | ||||
2141 | // If the subject principal is the same as the content principal, or no | |||
2142 | // explicit subject principal was provided, we don't need to do any further | |||
2143 | // checks. Just return the content principal. | |||
2144 | if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) { | |||
2145 | return contentPrin; | |||
2146 | } | |||
2147 | ||||
2148 | // Only use the subject principal if the URL string we are going to end up | |||
2149 | // fetching is under the control of that principal, which is never the case | |||
2150 | // for relative URLs. | |||
2151 | if (aAttrValue.IsEmpty() || | |||
2152 | !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) { | |||
2153 | return contentPrin; | |||
2154 | } | |||
2155 | ||||
2156 | // Only use the subject principal as the attr triggering principal if it | |||
2157 | // should override the CSP of the node's principal. | |||
2158 | if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) { | |||
2159 | return aSubjectPrincipal; | |||
2160 | } | |||
2161 | ||||
2162 | return contentPrin; | |||
2163 | } | |||
2164 | ||||
2165 | // static | |||
2166 | bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) { | |||
2167 | nsAutoCString scheme; | |||
2168 | if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme (aURL, scheme))), 0)))) { | |||
2169 | // If we can't extract a scheme, it's not an absolute URL. | |||
2170 | return false; | |||
2171 | } | |||
2172 | ||||
2173 | // If it parses as an absolute StandardURL, it's definitely an absolute URL, | |||
2174 | // so no need to check with the IO service. | |||
2175 | if (net_IsAbsoluteURL(aURL)) { | |||
2176 | return true; | |||
2177 | } | |||
2178 | ||||
2179 | nsresult rv = NS_OK; | |||
2180 | nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv); | |||
2181 | 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2181); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2181; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2182 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
2183 | return false; | |||
2184 | } | |||
2185 | ||||
2186 | uint32_t flags; | |||
2187 | if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags (scheme.get(), &flags))), 1)))) { | |||
2188 | return flags & nsIProtocolHandler::URI_NORELATIVE; | |||
2189 | } | |||
2190 | ||||
2191 | return false; | |||
2192 | } | |||
2193 | ||||
2194 | // static | |||
2195 | bool nsContentUtils::InProlog(nsINode* aNode) { | |||
2196 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "missing node to nsContentUtils::InProlog" ")"); do { *((volatile int*)__null) = 2196; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2197 | ||||
2198 | nsINode* parent = aNode->GetParentNode(); | |||
2199 | if (!parent || !parent->IsDocument()) { | |||
2200 | return false; | |||
2201 | } | |||
2202 | ||||
2203 | const Document* doc = parent->AsDocument(); | |||
2204 | const nsIContent* root = doc->GetRootElement(); | |||
2205 | if (!root) { | |||
2206 | return true; | |||
2207 | } | |||
2208 | const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode); | |||
2209 | const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root); | |||
2210 | if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot .isSome()), 1))) { | |||
2211 | return *indexOfNode < *indexOfRoot; | |||
2212 | } | |||
2213 | // XXX Keep the odd traditional behavior for now. | |||
2214 | return indexOfNode.isNothing() && indexOfRoot.isSome(); | |||
2215 | } | |||
2216 | ||||
2217 | bool nsContentUtils::IsCallerChrome() { | |||
2218 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2218; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2219 | return SubjectPrincipal() == sSystemPrincipal; | |||
2220 | } | |||
2221 | ||||
2222 | #ifdef FUZZING | |||
2223 | bool nsContentUtils::IsFuzzingEnabled() { | |||
2224 | return StaticPrefs::fuzzing_enabled(); | |||
2225 | } | |||
2226 | #endif | |||
2227 | ||||
2228 | /* static */ | |||
2229 | bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled( | |||
2230 | JSContext* aCx, JSObject*) { | |||
2231 | return ThreadsafeIsSystemCaller(aCx) || | |||
2232 | StaticPrefs::dom_element_transform_getters_enabled(); | |||
2233 | } | |||
2234 | ||||
2235 | // Older Should RFP Functions ---------------------------------- | |||
2236 | ||||
2237 | /* static */ | |||
2238 | bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode, | |||
2239 | RFPTarget aTarget) { | |||
2240 | return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing()); | |||
2241 | } | |||
2242 | ||||
2243 | /* static */ | |||
2244 | bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject, | |||
2245 | RFPTarget aTarget) { | |||
2246 | if (!aGlobalObject) { | |||
2247 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
2248 | } | |||
2249 | return aGlobalObject->ShouldResistFingerprinting(aTarget); | |||
2250 | } | |||
2251 | ||||
2252 | // Newer Should RFP Functions ---------------------------------- | |||
2253 | // Utilities --------------------------------------------------- | |||
2254 | ||||
2255 | inline void LogDomainAndPrefList(const char* urlType, | |||
2256 | const char* exemptedDomainsPrefName, | |||
2257 | nsAutoCString& url, bool isExemptDomain) { | |||
2258 | nsAutoCString list; | |||
2259 | Preferences::GetCString(exemptedDomainsPrefName, list); | |||
2260 | 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) | |||
2261 | ("%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) | |||
2262 | 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) | |||
2263 | 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); | |||
2264 | } | |||
2265 | ||||
2266 | inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings( | |||
2267 | nsILoadInfo* aLoadInfo) { | |||
2268 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings; | |||
2269 | nsresult rv = | |||
2270 | aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); | |||
2271 | if (rv == NS_ERROR_NOT_IMPLEMENTED) { | |||
2272 | // The TRRLoadInfo in particular does not implement this method | |||
2273 | // In that instance. We will return false and let other code decide if | |||
2274 | // we shouldRFP for this connection | |||
2275 | return nullptr; | |||
2276 | } | |||
2277 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2277)) { | |||
2278 | 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) | |||
2279 | ("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) | |||
2280 | "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); | |||
2281 | return nullptr; | |||
2282 | } | |||
2283 | ||||
2284 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cookieJarSettings" ")"); do { *((volatile int*)__null) = 2284; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2285 | return cookieJarSettings.forget(); | |||
2286 | } | |||
2287 | ||||
2288 | bool ETPSaysShouldNotResistFingerprinting(nsIChannel* aChannel, | |||
2289 | nsILoadInfo* aLoadInfo) { | |||
2290 | // A positive return from this function should always be obeyed. | |||
2291 | // A negative return means we should keep checking things. | |||
2292 | ||||
2293 | bool isPBM = NS_UsePrivateBrowsing(aChannel); | |||
2294 | // We do not want this check to apply to RFP, only to FPP | |||
2295 | // There is one problematic combination of prefs; however: | |||
2296 | // If RFP is enabled in PBMode only and FPP is enabled globally | |||
2297 | // (so, in non-PBM mode) - we need to know if we're in PBMode or not. | |||
2298 | // But that's kind of expensive and we'd like to avoid it if we | |||
2299 | // don't have to, so special-case that scenario | |||
2300 | if (StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly() && | |||
2301 | !StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() && | |||
2302 | StaticPrefs::privacy_resistFingerprinting_pbmode_DoNotUseDirectly()) { | |||
2303 | if (isPBM) { | |||
2304 | // In PBM (where RFP is enabled) do not exempt based on the ETP toggle | |||
2305 | return false; | |||
2306 | } | |||
2307 | } else if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() || | |||
2308 | (isPBM && | |||
2309 | StaticPrefs:: | |||
2310 | privacy_resistFingerprinting_pbmode_DoNotUseDirectly())) { | |||
2311 | // In RFP, never use the ETP toggle to exempt. | |||
2312 | // We can safely return false here even if we are not in PBM mode | |||
2313 | // and RFP_pbmode is enabled because we will later see that and | |||
2314 | // return false from the ShouldRFP function entirely. | |||
2315 | return false; | |||
2316 | } | |||
2317 | ||||
2318 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
2319 | GetCookieJarSettings(aLoadInfo); | |||
2320 | if (!cookieJarSettings) { | |||
2321 | return false; | |||
2322 | } | |||
2323 | ||||
2324 | return ContentBlockingAllowList::Check(cookieJarSettings); | |||
2325 | } | |||
2326 | ||||
2327 | inline bool CookieJarSettingsSaysShouldResistFingerprinting( | |||
2328 | nsILoadInfo* aLoadInfo) { | |||
2329 | // A positive return from this function should always be obeyed. | |||
2330 | // A negative return means we should keep checking things. | |||
2331 | ||||
2332 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
2333 | GetCookieJarSettings(aLoadInfo); | |||
2334 | if (!cookieJarSettings) { | |||
2335 | return false; | |||
2336 | } | |||
2337 | return cookieJarSettings->GetShouldResistFingerprinting(); | |||
2338 | } | |||
2339 | ||||
2340 | inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) { | |||
2341 | return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") || | |||
2342 | aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") || | |||
2343 | (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI)); | |||
2344 | } | |||
2345 | ||||
2346 | inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) { | |||
2347 | if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") || | |||
2348 | aPrincipal->SchemeIs("view-source") || | |||
2349 | aPrincipal->SchemeIs("moz-extension")) { | |||
2350 | return true; | |||
2351 | } | |||
2352 | ||||
2353 | if (!aPrincipal->SchemeIs("about")) { | |||
2354 | return false; | |||
2355 | } | |||
2356 | ||||
2357 | bool isContentAccessibleAboutURI; | |||
2358 | Unused << aPrincipal->IsContentAccessibleAboutURI( | |||
2359 | &isContentAccessibleAboutURI); | |||
2360 | return !isContentAccessibleAboutURI; | |||
2361 | } | |||
2362 | ||||
2363 | const char* kExemptedDomainsPrefName = | |||
2364 | "privacy.resistFingerprinting.exemptedDomains"; | |||
2365 | ||||
2366 | inline bool PartionKeyIsAlsoExempted( | |||
2367 | const mozilla::OriginAttributes& aOriginAttributes) { | |||
2368 | // If we've gotten here we have (probably) passed the CookieJarSettings | |||
2369 | // check that would tell us that if we _are_ a subdocument, then we are on | |||
2370 | // an exempted top-level domain and we should see if we ourselves are | |||
2371 | // exempted. But we may have gotten here because we directly called the | |||
2372 | // _dangerous function and we haven't done that check, but we _were_ | |||
2373 | // instatiated from a state where we could have been partitioned. | |||
2374 | // So perform this last-ditch check for that scenario. | |||
2375 | // We arbitrarily use https as the scheme, but it doesn't matter. | |||
2376 | nsresult rv = NS_ERROR_NOT_INITIALIZED; | |||
2377 | nsCOMPtr<nsIURI> uri; | |||
2378 | if (StaticPrefs::privacy_firstparty_isolate() && | |||
2379 | !aOriginAttributes.mFirstPartyDomain.IsEmpty()) { | |||
2380 | rv = NS_NewURI(getter_AddRefs(uri), | |||
2381 | u"https://"_ns + aOriginAttributes.mFirstPartyDomain); | |||
2382 | } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) { | |||
2383 | rv = NS_NewURI(getter_AddRefs(uri), | |||
2384 | u"https://"_ns + aOriginAttributes.mPartitionKey); | |||
2385 | } | |||
2386 | ||||
2387 | if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
2388 | bool isExemptPartitionKey = | |||
2389 | nsContentUtils::IsURIInPrefList(uri, kExemptedDomainsPrefName); | |||
2390 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
2391 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
2392 | nsAutoCString url; | |||
2393 | uri->GetHost(url); | |||
2394 | LogDomainAndPrefList("Partition Key", kExemptedDomainsPrefName, url, | |||
2395 | isExemptPartitionKey); | |||
2396 | } | |||
2397 | return isExemptPartitionKey; | |||
2398 | } | |||
2399 | return true; | |||
2400 | } | |||
2401 | ||||
2402 | // Functions --------------------------------------------------- | |||
2403 | ||||
2404 | /* static */ | |||
2405 | bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification, | |||
2406 | RFPTarget aTarget) { | |||
2407 | // See comment in header file for information about usage | |||
2408 | // We hardcode PBM to true to be the more restrictive option. | |||
2409 | return nsContentUtils::ShouldResistFingerprinting(true, aTarget); | |||
2410 | } | |||
2411 | ||||
2412 | namespace { | |||
2413 | ||||
2414 | // This function is only called within this file for Positive Return Checks | |||
2415 | bool ShouldResistFingerprinting_(const char* aJustification, | |||
2416 | bool aIsPrivateMode, RFPTarget aTarget) { | |||
2417 | // See comment in header file for information about usage | |||
2418 | return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget); | |||
2419 | } | |||
2420 | ||||
2421 | } // namespace | |||
2422 | ||||
2423 | /* static */ | |||
2424 | bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType, | |||
2425 | nsIGlobalObject* aGlobalObject, | |||
2426 | RFPTarget aTarget) { | |||
2427 | if (aCallerType == CallerType::System) { | |||
2428 | return false; | |||
2429 | } | |||
2430 | return ShouldResistFingerprinting(aGlobalObject, aTarget); | |||
2431 | } | |||
2432 | ||||
2433 | bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell, | |||
2434 | RFPTarget aTarget) { | |||
2435 | if (!aDocShell) { | |||
2436 | 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) | |||
2437 | ("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) | |||
2438 | "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); | |||
2439 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
2440 | } | |||
2441 | Document* doc = aDocShell->GetDocument(); | |||
2442 | if (!doc) { | |||
2443 | 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 doc"); } } while (0) | |||
2444 | ("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 doc"); } } while (0) | |||
2445 | "with NULL doc"))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 doc"); } } while (0); | |||
2446 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
2447 | } | |||
2448 | return doc->ShouldResistFingerprinting(aTarget); | |||
2449 | } | |||
2450 | ||||
2451 | /* static */ | |||
2452 | bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel, | |||
2453 | RFPTarget aTarget) { | |||
2454 | if (!aChannel) { | |||
2455 | 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) | |||
2456 | ("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) | |||
2457 | "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); | |||
2458 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
2459 | } | |||
2460 | ||||
2461 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
2462 | if (!loadInfo) { | |||
2463 | 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) | |||
2464 | ("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) | |||
2465 | "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); | |||
2466 | return ShouldResistFingerprinting("Null Object", aTarget); | |||
2467 | } | |||
2468 | ||||
2469 | // With this check, we can ensure that the prefs and target say yes, so only | |||
2470 | // an exemption would cause us to return false. | |||
2471 | bool isPBM = NS_UsePrivateBrowsing(aChannel); | |||
2472 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
2473 | 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) | |||
2474 | ("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) | |||
2475 | " 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) | |||
2476 | 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); | |||
2477 | return false; | |||
2478 | } | |||
2479 | ||||
2480 | if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) { | |||
2481 | 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) | |||
2482 | ("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) | |||
2483 | " 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); | |||
2484 | return false; | |||
2485 | } | |||
2486 | ||||
2487 | if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) { | |||
2488 | 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) | |||
2489 | ("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) | |||
2490 | " 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); | |||
2491 | return true; | |||
2492 | } | |||
2493 | ||||
2494 | // Document types have no loading principal. Subdocument types do have a | |||
2495 | // loading principal, but it is the loading principal of the parent | |||
2496 | // document; not the subdocument. | |||
2497 | auto contentType = loadInfo->GetExternalContentPolicyType(); | |||
2498 | // Case 1: Document or Subdocument load | |||
2499 | if (contentType == ExtContentPolicy::TYPE_DOCUMENT || | |||
2500 | contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) { | |||
2501 | nsCOMPtr<nsIURI> channelURI; | |||
2502 | nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
2503 | 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)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
2504 | 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)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
2505 | "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)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
2506 | "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)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)" ")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2507 | // this check is to ensure that we do not crash in non-debug builds. | |||
2508 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
2509 | return true; | |||
2510 | } | |||
2511 | ||||
2512 | #if 0 | |||
2513 | if (loadInfo->GetExternalContentPolicyType() == ExtContentPolicy::TYPE_SUBDOCUMENT) { | |||
2514 | nsCOMPtr<nsIURI> channelURI; | |||
2515 | nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
2516 | nsAutoCString channelSpec; | |||
2517 | channelURI->GetSpec(channelSpec); | |||
2518 | ||||
2519 | if (!loadInfo->GetLoadingPrincipal()) { | |||
2520 | 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, "Sub Document Type. FinalChannelURI is %s, Loading Principal is NULL\n" , channelSpec.get()); } } while (0) | |||
2521 | ("Sub Document Type. FinalChannelURI is %s, Loading Principal is NULL\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 is NULL\n" , channelSpec.get()); } } while (0) | |||
2522 | 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 is NULL\n" , channelSpec.get()); } } while (0); | |||
2523 | ||||
2524 | } else { | |||
2525 | nsAutoCString loadingPrincipalSpec; | |||
2526 | loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec); | |||
2527 | ||||
2528 | 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, "Sub Document Type. FinalChannelURI is %s, Loading Principal Origin is %s\n" , channelSpec.get(), loadingPrincipalSpec.get()); } } while ( 0) | |||
2529 | ("Sub Document Type. FinalChannelURI is %s, Loading Principal Origin is %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 Origin is %s\n" , channelSpec.get(), loadingPrincipalSpec.get()); } } while ( 0) | |||
2530 | channelSpec.get(), loadingPrincipalSpec.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 Origin is %s\n" , channelSpec.get(), loadingPrincipalSpec.get()); } } while ( 0); | |||
2531 | } | |||
2532 | } | |||
2533 | ||||
2534 | #endif | |||
2535 | ||||
2536 | return ShouldResistFingerprinting_dangerous( | |||
2537 | channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget); | |||
2538 | } | |||
2539 | ||||
2540 | // Case 2: Subresource Load | |||
2541 | // Because this code is only used for subresource loads, this | |||
2542 | // will check the parent's principal | |||
2543 | nsIPrincipal* principal = loadInfo->GetLoadingPrincipal(); | |||
2544 | ||||
2545 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
2546 | !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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
2547 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
2548 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()" ")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
2549 | return ShouldResistFingerprinting_dangerous(principal, "Internal Call", | |||
2550 | aTarget); | |||
2551 | } | |||
2552 | ||||
2553 | /* static */ | |||
2554 | bool nsContentUtils::ShouldResistFingerprinting_dangerous( | |||
2555 | nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes, | |||
2556 | const char* aJustification, RFPTarget aTarget) { | |||
2557 | // With this check, we can ensure that the prefs and target say yes, so only | |||
2558 | // an exemption would cause us to return false. | |||
2559 | bool isPBM = aOriginAttributes.IsPrivateBrowsing(); | |||
2560 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
2561 | 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) | |||
2562 | ("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) | |||
2563 | " 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) | |||
2564 | 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); | |||
2565 | return false; | |||
2566 | } | |||
2567 | ||||
2568 | 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) | |||
2569 | ("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) | |||
2570 | " 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) | |||
2571 | 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); | |||
2572 | ||||
2573 | if (!StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() && | |||
2574 | !StaticPrefs::privacy_fingerprintingProtection_DoNotUseDirectly()) { | |||
2575 | // If neither of the 'regular' RFP prefs are set, then one (or both) | |||
2576 | // of the PBM-Only prefs are set (or we would have failed the | |||
2577 | // Positive return check.) Therefore, if we are not in PBM, return false | |||
2578 | if (!aOriginAttributes.IsPrivateBrowsing()) { | |||
2579 | 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) OA PBM Check said false" ); } } while (0) | |||
2580 | ("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) OA PBM Check said false" ); } } while (0) | |||
2581 | " OriginAttributes) OA PBM Check 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_dangerous(nsIURI*," " OriginAttributes) OA PBM Check said false" ); } } while (0); | |||
2582 | return false; | |||
2583 | } | |||
2584 | } | |||
2585 | ||||
2586 | // Exclude internal schemes and web extensions | |||
2587 | if (SchemeSaysShouldNotResistFingerprinting(aURI)) { | |||
2588 | 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) | |||
2589 | ("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) | |||
2590 | " 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); | |||
2591 | return false; | |||
2592 | } | |||
2593 | ||||
2594 | bool isExemptDomain = false; | |||
2595 | nsAutoCString list; | |||
2596 | Preferences::GetCString(kExemptedDomainsPrefName, list); | |||
2597 | ToLowerCase(list); | |||
2598 | isExemptDomain = IsURIInList(aURI, list); | |||
2599 | ||||
2600 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
2601 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
2602 | nsAutoCString url; | |||
2603 | aURI->GetHost(url); | |||
2604 | LogDomainAndPrefList("URI", kExemptedDomainsPrefName, url, isExemptDomain); | |||
2605 | } | |||
2606 | ||||
2607 | if (isExemptDomain) { | |||
2608 | isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes); | |||
2609 | } | |||
2610 | ||||
2611 | return !isExemptDomain; | |||
2612 | } | |||
2613 | ||||
2614 | /* static */ | |||
2615 | bool nsContentUtils::ShouldResistFingerprinting_dangerous( | |||
2616 | nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) { | |||
2617 | if (!aPrincipal) { | |||
2618 | 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) | |||
2619 | ("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) | |||
2620 | "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); | |||
2621 | return ShouldResistFingerprinting("Null object", aTarget); | |||
2622 | } | |||
2623 | ||||
2624 | auto originAttributes = | |||
2625 | BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(); | |||
2626 | // With this check, we can ensure that the prefs and target say yes, so only | |||
2627 | // an exemption would cause us to return false. | |||
2628 | bool isPBM = originAttributes.IsPrivateBrowsing(); | |||
2629 | if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) { | |||
2630 | 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) | |||
2631 | ("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) | |||
2632 | "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) | |||
2633 | 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); | |||
2634 | return false; | |||
2635 | } | |||
2636 | ||||
2637 | if (aPrincipal->IsSystemPrincipal()) { | |||
2638 | 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) | |||
2639 | ("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) | |||
2640 | "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); | |||
2641 | return false; | |||
2642 | } | |||
2643 | ||||
2644 | // Exclude internal schemes and web extensions | |||
2645 | if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) { | |||
2646 | 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) | |||
2647 | ("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) | |||
2648 | " 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); | |||
2649 | return false; | |||
2650 | } | |||
2651 | ||||
2652 | // Web extension principals are also excluded | |||
2653 | if (BasePrincipal::Cast(aPrincipal)->AddonPolicy()) { | |||
2654 | 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) | |||
2655 | ("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) | |||
2656 | " 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); | |||
2657 | return false; | |||
2658 | } | |||
2659 | ||||
2660 | bool isExemptDomain = false; | |||
2661 | aPrincipal->IsURIInPrefList(kExemptedDomainsPrefName, &isExemptDomain); | |||
2662 | ||||
2663 | if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0)) | |||
2664 | mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils ::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))) { | |||
2665 | nsAutoCString origin; | |||
2666 | aPrincipal->GetOrigin(origin); | |||
2667 | LogDomainAndPrefList("URI", kExemptedDomainsPrefName, origin, | |||
2668 | isExemptDomain); | |||
2669 | } | |||
2670 | ||||
2671 | if (isExemptDomain) { | |||
2672 | isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes); | |||
2673 | } | |||
2674 | ||||
2675 | return !isExemptDomain; | |||
2676 | } | |||
2677 | ||||
2678 | // -------------------------------------------------------------------- | |||
2679 | ||||
2680 | /* static */ | |||
2681 | void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting( | |||
2682 | int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth, | |||
2683 | int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight, | |||
2684 | bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth, | |||
2685 | int32_t* aOutputHeight) { | |||
2686 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth" ")"); do { *((volatile int*)__null) = 2686; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2687 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputHeight" ")"); do { *((volatile int*)__null) = 2687; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2688 | ||||
2689 | int32_t availContentWidth = 0; | |||
2690 | int32_t availContentHeight = 0; | |||
2691 | ||||
2692 | availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(), | |||
2693 | aScreenWidth - aChromeWidth); | |||
2694 | #ifdef MOZ_WIDGET_GTK1 | |||
2695 | // In the GTK window, it will not report outside system decorations | |||
2696 | // when we get available window size, see Bug 581863. So, we leave a | |||
2697 | // 40 pixels space for them when calculating the available content | |||
2698 | // height. It is not necessary for the width since the content width | |||
2699 | // is usually pretty much the same as the chrome width. | |||
2700 | availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(), | |||
2701 | (-40 + aScreenHeight) - aChromeHeight); | |||
2702 | #else | |||
2703 | availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(), | |||
2704 | aScreenHeight - aChromeHeight); | |||
2705 | #endif | |||
2706 | ||||
2707 | // Ideally, we'd like to round window size to 1000x1000, but the | |||
2708 | // screen space could be too small to accommodate this size in some | |||
2709 | // cases. If it happens, we would round the window size to the nearest | |||
2710 | // 200x100. | |||
2711 | availContentWidth = availContentWidth - (availContentWidth % 200); | |||
2712 | availContentHeight = availContentHeight - (availContentHeight % 100); | |||
2713 | ||||
2714 | // If aIsOuter is true, we are setting the outer window. So we | |||
2715 | // have to consider the chrome UI. | |||
2716 | int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0; | |||
2717 | int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0; | |||
2718 | int32_t resultWidth = 0, resultHeight = 0; | |||
2719 | ||||
2720 | // if the original size is greater than the maximum available size, we set | |||
2721 | // it to the maximum size. And if the original value is less than the | |||
2722 | // minimum rounded size, we set it to the minimum 200x100. | |||
2723 | if (aInputWidth > (availContentWidth + chromeOffsetWidth)) { | |||
2724 | resultWidth = availContentWidth + chromeOffsetWidth; | |||
2725 | } else if (aInputWidth < (200 + chromeOffsetWidth)) { | |||
2726 | resultWidth = 200 + chromeOffsetWidth; | |||
2727 | } else { | |||
2728 | // Otherwise, we round the window to the nearest upper rounded 200x100. | |||
2729 | resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 + | |||
2730 | chromeOffsetWidth; | |||
2731 | } | |||
2732 | ||||
2733 | if (aInputHeight > (availContentHeight + chromeOffsetHeight)) { | |||
2734 | resultHeight = availContentHeight + chromeOffsetHeight; | |||
2735 | } else if (aInputHeight < (100 + chromeOffsetHeight)) { | |||
2736 | resultHeight = 100 + chromeOffsetHeight; | |||
2737 | } else { | |||
2738 | resultHeight = | |||
2739 | NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 + | |||
2740 | chromeOffsetHeight; | |||
2741 | } | |||
2742 | ||||
2743 | *aOutputWidth = resultWidth; | |||
2744 | *aOutputHeight = resultHeight; | |||
2745 | } | |||
2746 | ||||
2747 | bool nsContentUtils::ThreadsafeIsCallerChrome() { | |||
2748 | return NS_IsMainThread() ? IsCallerChrome() | |||
2749 | : IsCurrentThreadRunningChromeWorker(); | |||
2750 | } | |||
2751 | ||||
2752 | bool nsContentUtils::IsCallerUAWidget() { | |||
2753 | JSContext* cx = GetCurrentJSContext(); | |||
2754 | if (!cx) { | |||
2755 | return false; | |||
2756 | } | |||
2757 | ||||
2758 | JS::Realm* realm = JS::GetCurrentRealmOrNull(cx); | |||
2759 | if (!realm) { | |||
2760 | return false; | |||
2761 | } | |||
2762 | ||||
2763 | return xpc::IsUAWidgetScope(realm); | |||
2764 | } | |||
2765 | ||||
2766 | bool nsContentUtils::IsSystemCaller(JSContext* aCx) { | |||
2767 | // Note that SubjectPrincipal() assumes we are in a compartment here. | |||
2768 | return SubjectPrincipal(aCx) == sSystemPrincipal; | |||
2769 | } | |||
2770 | ||||
2771 | bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) { | |||
2772 | CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get(); | |||
2773 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ccjscx->Context() == aCx" ")"); do { *((volatile int*)__null) = 2773; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2774 | ||||
2775 | return ccjscx->IsSystemCaller(); | |||
2776 | } | |||
2777 | ||||
2778 | // static | |||
2779 | bool nsContentUtils::LookupBindingMember( | |||
2780 | JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId, | |||
2781 | JS::MutableHandle<JS::PropertyDescriptor> aDesc) { | |||
2782 | return true; | |||
2783 | } | |||
2784 | ||||
2785 | nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode( | |||
2786 | nsINode* aChild) { | |||
2787 | if (aChild->IsDocument()) { | |||
2788 | for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc; | |||
2789 | bc = bc->GetParent()) { | |||
2790 | if (bc->GetEmbedderElement()) { | |||
2791 | return bc->GetEmbedderElement(); | |||
2792 | } | |||
2793 | } | |||
2794 | return nullptr; | |||
2795 | } | |||
2796 | ||||
2797 | nsINode* parent = aChild->GetParentNode(); | |||
2798 | if (parent && parent->IsContent() && aChild->IsContent()) { | |||
2799 | parent = aChild->AsContent()->GetFlattenedTreeParent(); | |||
2800 | } | |||
2801 | ||||
2802 | return parent; | |||
2803 | } | |||
2804 | ||||
2805 | bool nsContentUtils::ContentIsHostIncludingDescendantOf( | |||
2806 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
2807 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { *((volatile int*)__null) = 2807; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2808 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { *((volatile int*)__null) = 2808; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2809 | ||||
2810 | do { | |||
2811 | if (aPossibleDescendant == aPossibleAncestor) return true; | |||
2812 | if (aPossibleDescendant->IsDocumentFragment()) { | |||
2813 | aPossibleDescendant = | |||
2814 | aPossibleDescendant->AsDocumentFragment()->GetHost(); | |||
2815 | } else { | |||
2816 | aPossibleDescendant = aPossibleDescendant->GetParentNode(); | |||
2817 | } | |||
2818 | } while (aPossibleDescendant); | |||
2819 | ||||
2820 | return false; | |||
2821 | } | |||
2822 | ||||
2823 | // static | |||
2824 | bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant, | |||
2825 | nsINode* aPossibleAncestor) { | |||
2826 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { *((volatile int*)__null) = 2826; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2827 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { *((volatile int*)__null) = 2827; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2828 | ||||
2829 | do { | |||
2830 | if (aPossibleDescendant == aPossibleAncestor) { | |||
2831 | return true; | |||
2832 | } | |||
2833 | ||||
2834 | aPossibleDescendant = | |||
2835 | GetNearestInProcessCrossDocParentNode(aPossibleDescendant); | |||
2836 | } while (aPossibleDescendant); | |||
2837 | ||||
2838 | return false; | |||
2839 | } | |||
2840 | ||||
2841 | // static | |||
2842 | bool nsContentUtils::ContentIsFlattenedTreeDescendantOf( | |||
2843 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
2844 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { *((volatile int*)__null) = 2844; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2845 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { *((volatile int*)__null) = 2845; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2846 | ||||
2847 | do { | |||
2848 | if (aPossibleDescendant == aPossibleAncestor) { | |||
2849 | return true; | |||
2850 | } | |||
2851 | aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode(); | |||
2852 | } while (aPossibleDescendant); | |||
2853 | ||||
2854 | return false; | |||
2855 | } | |||
2856 | ||||
2857 | // static | |||
2858 | bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle( | |||
2859 | const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) { | |||
2860 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant" ") (" "The possible descendant is null!" ")"); do { *((volatile int*)__null) = 2860; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2861 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor" ") (" "The possible ancestor is null!" ")"); do { *((volatile int*)__null) = 2861; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
2862 | ||||
2863 | do { | |||
2864 | if (aPossibleDescendant == aPossibleAncestor) { | |||
2865 | return true; | |||
2866 | } | |||
2867 | aPossibleDescendant = | |||
2868 | aPossibleDescendant->GetFlattenedTreeParentNodeForStyle(); | |||
2869 | } while (aPossibleDescendant); | |||
2870 | ||||
2871 | return false; | |||
2872 | } | |||
2873 | ||||
2874 | // static | |||
2875 | nsINode* nsContentUtils::Retarget(nsINode* aTargetA, nsINode* aTargetB) { | |||
2876 | while (true && aTargetA) { | |||
2877 | // If A's root is not a shadow root... | |||
2878 | nsINode* root = aTargetA->SubtreeRoot(); | |||
2879 | if (!root->IsShadowRoot()) { | |||
2880 | // ...then return A. | |||
2881 | return aTargetA; | |||
2882 | } | |||
2883 | ||||
2884 | // or A's root is a shadow-including inclusive ancestor of B... | |||
2885 | if (aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) { | |||
2886 | // ...then return A. | |||
2887 | return aTargetA; | |||
2888 | } | |||
2889 | ||||
2890 | aTargetA = ShadowRoot::FromNode(root)->GetHost(); | |||
2891 | } | |||
2892 | ||||
2893 | return nullptr; | |||
2894 | } | |||
2895 | ||||
2896 | // static | |||
2897 | Element* nsContentUtils::GetAnElementForTiming(Element* aTarget, | |||
2898 | const Document* aDocument, | |||
2899 | nsIGlobalObject* aGlobal) { | |||
2900 | if (!aTarget->IsInComposedDoc()) { | |||
2901 | return nullptr; | |||
2902 | } | |||
2903 | ||||
2904 | if (!aDocument) { | |||
2905 | nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal); | |||
2906 | if (!inner) { | |||
2907 | return nullptr; | |||
2908 | } | |||
2909 | aDocument = inner->GetExtantDoc(); | |||
2910 | } | |||
2911 | ||||
2912 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { *((volatile int*)__null) = 2912; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2913 | ||||
2914 | if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument || | |||
2915 | !aDocument->IsCurrentActiveDocument()) { | |||
2916 | return nullptr; | |||
2917 | } | |||
2918 | ||||
2919 | return aTarget; | |||
2920 | } | |||
2921 | ||||
2922 | // static | |||
2923 | nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode, | |||
2924 | nsTArray<nsINode*>& aArray) { | |||
2925 | while (aNode) { | |||
2926 | aArray.AppendElement(aNode); | |||
2927 | aNode = aNode->GetParentNode(); | |||
2928 | } | |||
2929 | return NS_OK; | |||
2930 | } | |||
2931 | ||||
2932 | // static | |||
2933 | template <typename GetParentFunc> | |||
2934 | nsresult static GetInclusiveAncestorsAndOffsetsHelper( | |||
2935 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
2936 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc) { | |||
2937 | NS_ENSURE_ARG_POINTER(aNode)do { if ((__builtin_expect(!!(!(aNode)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNode" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2937); return NS_ERROR_INVALID_POINTER; } } while (false); | |||
2938 | ||||
2939 | if (!aNode->IsContent()) { | |||
2940 | return NS_ERROR_FAILURE; | |||
2941 | } | |||
2942 | nsIContent* content = aNode->AsContent(); | |||
2943 | ||||
2944 | if (!aAncestorNodes.IsEmpty()) { | |||
2945 | NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2945); | |||
2946 | aAncestorNodes.Clear(); | |||
2947 | } | |||
2948 | ||||
2949 | if (!aAncestorOffsets.IsEmpty()) { | |||
2950 | NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2950); | |||
2951 | aAncestorOffsets.Clear(); | |||
2952 | } | |||
2953 | ||||
2954 | // insert the node itself | |||
2955 | aAncestorNodes.AppendElement(content); | |||
2956 | aAncestorOffsets.AppendElement(Some(aOffset)); | |||
2957 | ||||
2958 | // insert all the ancestors | |||
2959 | nsIContent* child = content; | |||
2960 | nsIContent* parent = aGetParentFunc(child); | |||
2961 | while (parent) { | |||
2962 | aAncestorNodes.AppendElement(parent->AsContent()); | |||
2963 | aAncestorOffsets.AppendElement(parent->ComputeIndexOf(child)); | |||
2964 | child = parent; | |||
2965 | parent = aGetParentFunc(child); | |||
2966 | } | |||
2967 | ||||
2968 | return NS_OK; | |||
2969 | } | |||
2970 | ||||
2971 | nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets( | |||
2972 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
2973 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets) { | |||
2974 | return GetInclusiveAncestorsAndOffsetsHelper( | |||
2975 | aNode, aOffset, aAncestorNodes, aAncestorOffsets, | |||
2976 | [](nsIContent* aContent) { return aContent->GetParent(); }); | |||
2977 | } | |||
2978 | ||||
2979 | nsresult nsContentUtils::GetShadowIncludingAncestorsAndOffsets( | |||
2980 | nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes, | |||
2981 | nsTArray<Maybe<uint32_t>>& aAncestorOffsets) { | |||
2982 | return GetInclusiveAncestorsAndOffsetsHelper( | |||
2983 | aNode, aOffset, aAncestorNodes, aAncestorOffsets, | |||
2984 | [](nsIContent* aContent) -> nsIContent* { | |||
2985 | return nsIContent::FromNodeOrNull( | |||
2986 | aContent->GetParentOrShadowHostNode()); | |||
2987 | }); | |||
2988 | } | |||
2989 | ||||
2990 | template <typename Node, typename GetParentFunc> | |||
2991 | static Node* GetCommonAncestorInternal(Node* aNode1, Node* aNode2, | |||
2992 | GetParentFunc aGetParentFunc) { | |||
2993 | MOZ_ASSERT(aNode1 != aNode2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aNode1 != aNode2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aNode1 != aNode2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNode1 != aNode2" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 2993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1 != aNode2" ")"); do { *((volatile int*)__null) = 2993; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2994 | ||||
2995 | // Build the chain of parents | |||
2996 | AutoTArray<Node*, 30> parents1, parents2; | |||
2997 | do { | |||
2998 | parents1.AppendElement(aNode1); | |||
2999 | aNode1 = aGetParentFunc(aNode1); | |||
3000 | } while (aNode1); | |||
3001 | do { | |||
3002 | parents2.AppendElement(aNode2); | |||
3003 | aNode2 = aGetParentFunc(aNode2); | |||
3004 | } while (aNode2); | |||
3005 | ||||
3006 | // Find where the parent chain differs | |||
3007 | uint32_t pos1 = parents1.Length(); | |||
3008 | uint32_t pos2 = parents2.Length(); | |||
3009 | Node** data1 = parents1.Elements(); | |||
3010 | Node** data2 = parents2.Elements(); | |||
3011 | Node* parent = nullptr; | |||
3012 | uint32_t len; | |||
3013 | for (len = std::min(pos1, pos2); len > 0; --len) { | |||
3014 | Node* child1 = data1[--pos1]; | |||
3015 | Node* child2 = data2[--pos2]; | |||
3016 | if (child1 != child2) { | |||
3017 | break; | |||
3018 | } | |||
3019 | parent = child1; | |||
3020 | } | |||
3021 | ||||
3022 | return parent; | |||
3023 | } | |||
3024 | ||||
3025 | /* static */ | |||
3026 | nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1, | |||
3027 | nsINode* aNode2) { | |||
3028 | return GetCommonAncestorInternal( | |||
3029 | aNode1, aNode2, [](nsINode* aNode) { return aNode->GetParentNode(); }); | |||
3030 | } | |||
3031 | ||||
3032 | /* static */ | |||
3033 | nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor( | |||
3034 | nsINode* aNode1, nsINode* aNode2) { | |||
3035 | if (aNode1 == aNode2) { | |||
3036 | return aNode1; | |||
3037 | } | |||
3038 | ||||
3039 | return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) { | |||
3040 | return aNode->GetParentOrShadowHostNode(); | |||
3041 | }); | |||
3042 | } | |||
3043 | ||||
3044 | /* static */ | |||
3045 | nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper( | |||
3046 | nsIContent* aContent1, nsIContent* aContent2) { | |||
3047 | return GetCommonAncestorInternal( | |||
3048 | aContent1, aContent2, | |||
3049 | [](nsIContent* aContent) { return aContent->GetFlattenedTreeParent(); }); | |||
3050 | } | |||
3051 | ||||
3052 | /* static */ | |||
3053 | nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection( | |||
3054 | nsIContent* aContent1, nsIContent* aContent2) { | |||
3055 | if (aContent1 == aContent2) { | |||
3056 | return aContent1; | |||
3057 | } | |||
3058 | ||||
3059 | return GetCommonAncestorInternal( | |||
3060 | aContent1, aContent2, [](nsIContent* aContent) { | |||
3061 | return aContent->GetFlattenedTreeParentNodeForSelection(); | |||
3062 | }); | |||
3063 | } | |||
3064 | ||||
3065 | /* static */ | |||
3066 | Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle( | |||
3067 | Element* aElement1, Element* aElement2) { | |||
3068 | return GetCommonAncestorInternal(aElement1, aElement2, [](Element* aElement) { | |||
3069 | return aElement->GetFlattenedTreeParentElementForStyle(); | |||
3070 | }); | |||
3071 | } | |||
3072 | ||||
3073 | /* static */ | |||
3074 | bool nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2, | |||
3075 | Maybe<uint32_t>* aNode1Index, | |||
3076 | Maybe<uint32_t>* aNode2Index) { | |||
3077 | // Note, CompareDocumentPosition takes the latter params in different order. | |||
3078 | return (aNode2->CompareDocumentPosition(*aNode1, aNode2Index, aNode1Index) & | |||
3079 | (Node_Binding::DOCUMENT_POSITION_PRECEDING | | |||
3080 | Node_Binding::DOCUMENT_POSITION_DISCONNECTED)) == | |||
3081 | Node_Binding::DOCUMENT_POSITION_PRECEDING; | |||
3082 | } | |||
3083 | ||||
3084 | /* static */ | |||
3085 | Maybe<int32_t> nsContentUtils::ComparePoints(const nsINode* aParent1, | |||
3086 | uint32_t aOffset1, | |||
3087 | const nsINode* aParent2, | |||
3088 | uint32_t aOffset2, | |||
3089 | NodeIndexCache* aIndexCache) { | |||
3090 | bool disconnected{false}; | |||
3091 | ||||
3092 | const int32_t order = ComparePoints_Deprecated( | |||
3093 | aParent1, aOffset1, aParent2, aOffset2, &disconnected, aIndexCache); | |||
3094 | if (disconnected) { | |||
3095 | return Nothing(); | |||
3096 | } | |||
3097 | ||||
3098 | return Some(order); | |||
3099 | } | |||
3100 | ||||
3101 | /* static */ | |||
3102 | int32_t nsContentUtils::ComparePoints_Deprecated( | |||
3103 | const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2, | |||
3104 | uint32_t aOffset2, bool* aDisconnected, NodeIndexCache* aIndexCache) { | |||
3105 | if (aParent1 == aParent2) { | |||
3106 | return aOffset1 < aOffset2 ? -1 : aOffset1 > aOffset2 ? 1 : 0; | |||
3107 | } | |||
3108 | ||||
3109 | AutoTArray<const nsINode*, 32> parents1, parents2; | |||
3110 | const nsINode* node1 = aParent1; | |||
3111 | const nsINode* node2 = aParent2; | |||
3112 | do { | |||
3113 | parents1.AppendElement(node1); | |||
3114 | node1 = node1->GetParentOrShadowHostNode(); | |||
3115 | } while (node1); | |||
3116 | do { | |||
3117 | parents2.AppendElement(node2); | |||
3118 | node2 = node2->GetParentOrShadowHostNode(); | |||
3119 | } while (node2); | |||
3120 | ||||
3121 | uint32_t pos1 = parents1.Length() - 1; | |||
3122 | uint32_t pos2 = parents2.Length() - 1; | |||
3123 | ||||
3124 | bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2); | |||
3125 | if (aDisconnected) { | |||
3126 | *aDisconnected = disconnected; | |||
3127 | } | |||
3128 | if (disconnected) { | |||
3129 | NS_ASSERTION(aDisconnected, "unexpected disconnected nodes")do { if (!(aDisconnected)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "unexpected disconnected nodes", "aDisconnected", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3129); MOZ_PretendNoReturn(); } } while (0); | |||
3130 | return 1; | |||
3131 | } | |||
3132 | ||||
3133 | // Find where the parent chains differ | |||
3134 | const nsINode* parent = parents1.ElementAt(pos1); | |||
3135 | uint32_t len; | |||
3136 | for (len = std::min(pos1, pos2); len > 0; --len) { | |||
3137 | const nsINode* child1 = parents1.ElementAt(--pos1); | |||
3138 | const nsINode* child2 = parents2.ElementAt(--pos2); | |||
3139 | if (child1 != child2) { | |||
3140 | if (MOZ_UNLIKELY(child1->IsShadowRoot())(__builtin_expect(!!(child1->IsShadowRoot()), 0))) { | |||
3141 | // Shadow roots come before light DOM per | |||
3142 | // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order | |||
3143 | MOZ_ASSERT(!child2->IsShadowRoot(), "Two shadow roots?")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()" " (" "Two shadow roots?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child2->IsShadowRoot()" ") (" "Two shadow roots?" ")"); do { *((volatile int*)__null ) = 3143; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
3144 | return -1; | |||
3145 | } | |||
3146 | if (MOZ_UNLIKELY(child2->IsShadowRoot())(__builtin_expect(!!(child2->IsShadowRoot()), 0))) { | |||
3147 | return 1; | |||
3148 | } | |||
3149 | Maybe<uint32_t> child1Index; | |||
3150 | Maybe<uint32_t> child2Index; | |||
3151 | if (aIndexCache) { | |||
3152 | aIndexCache->ComputeIndicesOf(parent, child1, child2, child1Index, | |||
3153 | child2Index); | |||
3154 | } else { | |||
3155 | child1Index = parent->ComputeIndexOf(child1); | |||
3156 | child2Index = parent->ComputeIndexOf(child2); | |||
3157 | } | |||
3158 | if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index .isSome()), 1))) { | |||
3159 | return *child1Index < *child2Index ? -1 : 1; | |||
3160 | } | |||
3161 | // XXX Keep the odd traditional behavior for now. | |||
3162 | return child1Index.isNothing() && child2Index.isSome() ? -1 : 1; | |||
3163 | } | |||
3164 | parent = child1; | |||
3165 | } | |||
3166 | ||||
3167 | // The parent chains never differed, so one of the nodes is an ancestor of | |||
3168 | // the other | |||
3169 | ||||
3170 | NS_ASSERTION(!pos1 || !pos2,do { if (!(!pos1 || !pos2)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "should have run out of parent chain for one of the nodes", "!pos1 || !pos2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3171); MOZ_PretendNoReturn(); } } while (0) | |||
3171 | "should have run out of parent chain for one of the nodes")do { if (!(!pos1 || !pos2)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "should have run out of parent chain for one of the nodes", "!pos1 || !pos2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3171); MOZ_PretendNoReturn(); } } while (0); | |||
3172 | ||||
3173 | if (!pos1) { | |||
3174 | const nsINode* child2 = parents2.ElementAt(--pos2); | |||
3175 | const Maybe<uint32_t> child2Index = | |||
3176 | aIndexCache ? aIndexCache->ComputeIndexOf(parent, child2) | |||
3177 | : parent->ComputeIndexOf(child2); | |||
3178 | if (MOZ_UNLIKELY(NS_WARN_IF(child2Index.isNothing()))(__builtin_expect(!!(NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3178)), 0))) { | |||
3179 | return 1; | |||
3180 | } | |||
3181 | return aOffset1 <= *child2Index ? -1 : 1; | |||
3182 | } | |||
3183 | ||||
3184 | const nsINode* child1 = parents1.ElementAt(--pos1); | |||
3185 | const Maybe<uint32_t> child1Index = | |||
3186 | aIndexCache ? aIndexCache->ComputeIndexOf(parent, child1) | |||
3187 | : parent->ComputeIndexOf(child1); | |||
3188 | if (MOZ_UNLIKELY(NS_WARN_IF(child1Index.isNothing()))(__builtin_expect(!!(NS_warn_if_impl(child1Index.isNothing(), "child1Index.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3188)), 0))) { | |||
3189 | return -1; | |||
3190 | } | |||
3191 | return *child1Index < aOffset2 ? -1 : 1; | |||
3192 | } | |||
3193 | ||||
3194 | /* static */ | |||
3195 | BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor( | |||
3196 | BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) { | |||
3197 | return GetCommonAncestorInternal( | |||
3198 | aBrowserParent1, aBrowserParent2, [](BrowserParent* aBrowserParent) { | |||
3199 | return aBrowserParent->GetBrowserBridgeParent() | |||
3200 | ? aBrowserParent->GetBrowserBridgeParent()->Manager() | |||
3201 | : nullptr; | |||
3202 | }); | |||
3203 | } | |||
3204 | ||||
3205 | /* static */ | |||
3206 | Element* nsContentUtils::GetTargetElement(Document* aDocument, | |||
3207 | const nsAString& aAnchorName) { | |||
3208 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")" ); do { *((volatile int*)__null) = 3208; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3209 | ||||
3210 | if (aAnchorName.IsEmpty()) { | |||
3211 | return nullptr; | |||
3212 | } | |||
3213 | // 1. If there is an element in the document tree that has an ID equal to | |||
3214 | // fragment, then return the first such element in tree order. | |||
3215 | if (Element* el = aDocument->GetElementById(aAnchorName)) { | |||
3216 | return el; | |||
3217 | } | |||
3218 | ||||
3219 | // 2. If there is an a element in the document tree that has a name | |||
3220 | // attribute whose value is equal to fragment, then return the first such | |||
3221 | // element in tree order. | |||
3222 | // | |||
3223 | // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs? | |||
3224 | if (aDocument->IsHTMLDocument()) { | |||
3225 | nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName); | |||
3226 | // Loop through the named nodes looking for the first anchor | |||
3227 | uint32_t length = list->Length(); | |||
3228 | for (uint32_t i = 0; i < length; i++) { | |||
3229 | nsIContent* node = list->Item(i); | |||
3230 | if (node->IsHTMLElement(nsGkAtoms::a)) { | |||
3231 | return node->AsElement(); | |||
3232 | } | |||
3233 | } | |||
3234 | } else { | |||
3235 | constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns; | |||
3236 | // Get the list of anchor elements | |||
3237 | nsCOMPtr<nsINodeList> list = | |||
3238 | aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns); | |||
3239 | // Loop through the anchors looking for the first one with the given name. | |||
3240 | for (uint32_t i = 0; true; i++) { | |||
3241 | nsIContent* node = list->Item(i); | |||
3242 | if (!node) { // End of list | |||
3243 | break; | |||
3244 | } | |||
3245 | ||||
3246 | // Compare the name attribute | |||
3247 | if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, | |||
3248 | aAnchorName, eCaseMatters)) { | |||
3249 | return node->AsElement(); | |||
3250 | } | |||
3251 | } | |||
3252 | } | |||
3253 | ||||
3254 | // 3. Return null. | |||
3255 | return nullptr; | |||
3256 | } | |||
3257 | ||||
3258 | /* static */ | |||
3259 | template <typename FPT, typename FRT, typename SPT, typename SRT> | |||
3260 | Maybe<int32_t> nsContentUtils::ComparePoints( | |||
3261 | const RangeBoundaryBase<FPT, FRT>& aFirstBoundary, | |||
3262 | const RangeBoundaryBase<SPT, SRT>& aSecondBoundary) { | |||
3263 | if (!aFirstBoundary.IsSet() || !aSecondBoundary.IsSet()) { | |||
3264 | return Nothing{}; | |||
3265 | } | |||
3266 | ||||
3267 | bool disconnected{false}; | |||
3268 | const int32_t order = | |||
3269 | ComparePoints_Deprecated(aFirstBoundary, aSecondBoundary, &disconnected); | |||
3270 | ||||
3271 | if (disconnected) { | |||
3272 | return Nothing{}; | |||
3273 | } | |||
3274 | ||||
3275 | return Some(order); | |||
3276 | } | |||
3277 | ||||
3278 | /* static */ | |||
3279 | template <typename FPT, typename FRT, typename SPT, typename SRT> | |||
3280 | int32_t nsContentUtils::ComparePoints_Deprecated( | |||
3281 | const RangeBoundaryBase<FPT, FRT>& aFirstBoundary, | |||
3282 | const RangeBoundaryBase<SPT, SRT>& aSecondBoundary, bool* aDisconnected) { | |||
3283 | if (NS_WARN_IF(!aFirstBoundary.IsSet())NS_warn_if_impl(!aFirstBoundary.IsSet(), "!aFirstBoundary.IsSet()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3283) || | |||
3284 | NS_WARN_IF(!aSecondBoundary.IsSet())NS_warn_if_impl(!aSecondBoundary.IsSet(), "!aSecondBoundary.IsSet()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3284)) { | |||
3285 | return -1; | |||
3286 | } | |||
3287 | // XXX Re-implement this without calling `Offset()` as far as possible, | |||
3288 | // and the other overload should be an alias of this. | |||
3289 | return ComparePoints_Deprecated( | |||
3290 | aFirstBoundary.Container(), | |||
3291 | *aFirstBoundary.Offset( | |||
3292 | RangeBoundaryBase<FPT, FRT>::OffsetFilter::kValidOrInvalidOffsets), | |||
3293 | aSecondBoundary.Container(), | |||
3294 | *aSecondBoundary.Offset( | |||
3295 | RangeBoundaryBase<SPT, SRT>::OffsetFilter::kValidOrInvalidOffsets), | |||
3296 | aDisconnected); | |||
3297 | } | |||
3298 | ||||
3299 | inline bool IsCharInSet(const char* aSet, const char16_t aChar) { | |||
3300 | char16_t ch; | |||
3301 | while ((ch = *aSet)) { | |||
3302 | if (aChar == char16_t(ch)) { | |||
3303 | return true; | |||
3304 | } | |||
3305 | ++aSet; | |||
3306 | } | |||
3307 | return false; | |||
3308 | } | |||
3309 | ||||
3310 | /** | |||
3311 | * This method strips leading/trailing chars, in given set, from string. | |||
3312 | */ | |||
3313 | ||||
3314 | // static | |||
3315 | const nsDependentSubstring nsContentUtils::TrimCharsInSet( | |||
3316 | const char* aSet, const nsAString& aValue) { | |||
3317 | nsAString::const_iterator valueCurrent, valueEnd; | |||
3318 | ||||
3319 | aValue.BeginReading(valueCurrent); | |||
3320 | aValue.EndReading(valueEnd); | |||
3321 | ||||
3322 | // Skip characters in the beginning | |||
3323 | while (valueCurrent != valueEnd) { | |||
3324 | if (!IsCharInSet(aSet, *valueCurrent)) { | |||
3325 | break; | |||
3326 | } | |||
3327 | ++valueCurrent; | |||
3328 | } | |||
3329 | ||||
3330 | if (valueCurrent != valueEnd) { | |||
3331 | for (;;) { | |||
3332 | --valueEnd; | |||
3333 | if (!IsCharInSet(aSet, *valueEnd)) { | |||
3334 | break; | |||
3335 | } | |||
3336 | } | |||
3337 | ++valueEnd; // Step beyond the last character we want in the value. | |||
3338 | } | |||
3339 | ||||
3340 | // valueEnd should point to the char after the last to copy | |||
3341 | return Substring(valueCurrent, valueEnd); | |||
3342 | } | |||
3343 | ||||
3344 | /** | |||
3345 | * This method strips leading and trailing whitespace from a string. | |||
3346 | */ | |||
3347 | ||||
3348 | // static | |||
3349 | template <bool IsWhitespace(char16_t)> | |||
3350 | const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr, | |||
3351 | bool aTrimTrailing) { | |||
3352 | nsAString::const_iterator start, end; | |||
3353 | ||||
3354 | aStr.BeginReading(start); | |||
3355 | aStr.EndReading(end); | |||
3356 | ||||
3357 | // Skip whitespace characters in the beginning | |||
3358 | while (start != end && IsWhitespace(*start)) { | |||
3359 | ++start; | |||
3360 | } | |||
3361 | ||||
3362 | if (aTrimTrailing) { | |||
3363 | // Skip whitespace characters in the end. | |||
3364 | while (end != start) { | |||
3365 | --end; | |||
3366 | ||||
3367 | if (!IsWhitespace(*end)) { | |||
3368 | // Step back to the last non-whitespace character. | |||
3369 | ++end; | |||
3370 | ||||
3371 | break; | |||
3372 | } | |||
3373 | } | |||
3374 | } | |||
3375 | ||||
3376 | // Return a substring for the string w/o leading and/or trailing | |||
3377 | // whitespace | |||
3378 | ||||
3379 | return Substring(start, end); | |||
3380 | } | |||
3381 | ||||
3382 | // Declaring the templates we are going to use avoid linking issues without | |||
3383 | // inlining the method. Considering there is not so much spaces checking | |||
3384 | // methods we can consider this to be better than inlining. | |||
3385 | template const nsDependentSubstring | |||
3386 | nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool); | |||
3387 | template const nsDependentSubstring nsContentUtils::TrimWhitespace< | |||
3388 | nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool); | |||
3389 | template const nsDependentSubstring nsContentUtils::TrimWhitespace< | |||
3390 | nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool); | |||
3391 | ||||
3392 | static inline void KeyAppendSep(nsACString& aKey) { | |||
3393 | if (!aKey.IsEmpty()) { | |||
3394 | aKey.Append('>'); | |||
3395 | } | |||
3396 | } | |||
3397 | ||||
3398 | static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) { | |||
3399 | KeyAppendSep(aKey); | |||
3400 | ||||
3401 | // Could escape separator here if collisions happen. > is not a legal char | |||
3402 | // for a name or type attribute, so we should be safe avoiding that extra | |||
3403 | // work. | |||
3404 | ||||
3405 | AppendUTF16toUTF8(aString, aKey); | |||
3406 | } | |||
3407 | ||||
3408 | static inline void KeyAppendString(const nsACString& aString, | |||
3409 | nsACString& aKey) { | |||
3410 | KeyAppendSep(aKey); | |||
3411 | ||||
3412 | // Could escape separator here if collisions happen. > is not a legal char | |||
3413 | // for a name or type attribute, so we should be safe avoiding that extra | |||
3414 | // work. | |||
3415 | ||||
3416 | aKey.Append(aString); | |||
3417 | } | |||
3418 | ||||
3419 | static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) { | |||
3420 | KeyAppendSep(aKey); | |||
3421 | ||||
3422 | aKey.AppendInt(aInt); | |||
3423 | } | |||
3424 | ||||
3425 | static inline bool IsAutocompleteOff(const nsIContent* aContent) { | |||
3426 | return aContent->IsElement() && | |||
3427 | aContent->AsElement()->AttrValueIs(kNameSpaceID_None, | |||
3428 | nsGkAtoms::autocomplete, u"off"_ns, | |||
3429 | eIgnoreCase); | |||
3430 | } | |||
3431 | ||||
3432 | /*static*/ | |||
3433 | void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument, | |||
3434 | nsACString& aKey) { | |||
3435 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { *((volatile int*)__null) = 3435; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3436 | ||||
3437 | aKey.Truncate(); | |||
3438 | ||||
3439 | uint32_t partID = aDocument ? aDocument->GetPartID() : 0; | |||
3440 | ||||
3441 | // Don't capture state for anonymous content | |||
3442 | if (aContent->IsInNativeAnonymousSubtree()) { | |||
3443 | return; | |||
3444 | } | |||
3445 | ||||
3446 | if (IsAutocompleteOff(aContent)) { | |||
3447 | return; | |||
3448 | } | |||
3449 | ||||
3450 | RefPtr<Document> doc = aContent->GetUncomposedDoc(); | |||
3451 | ||||
3452 | KeyAppendInt(partID, aKey); // first append a partID | |||
3453 | bool generatedUniqueKey = false; | |||
3454 | ||||
3455 | if (doc && doc->IsHTMLOrXHTML()) { | |||
3456 | nsHTMLDocument* htmlDoc = doc->AsHTMLDocument(); | |||
3457 | ||||
3458 | // If we have a form control and can calculate form information, use that | |||
3459 | // as the key - it is more reliable than just recording position in the | |||
3460 | // DOM. | |||
3461 | // XXXbz Is it, really? We have bugs on this, I think... | |||
3462 | // Important to have a unique key, and tag/type/name may not be. | |||
3463 | // | |||
3464 | // The format of the key depends on whether the control has a form, | |||
3465 | // and whether the element was parser inserted: | |||
3466 | // | |||
3467 | // [Has Form, Parser Inserted]: | |||
3468 | // fp>type>FormNum>IndOfControlInForm>FormName>name | |||
3469 | // | |||
3470 | // [No Form, Parser Inserted]: | |||
3471 | // dp>type>ControlNum>name | |||
3472 | // | |||
3473 | // [Has Form, Not Parser Inserted]: | |||
3474 | // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name | |||
3475 | // | |||
3476 | // [No Form, Not Parser Inserted]: | |||
3477 | // dn>type>IndOfControlInDoc>name | |||
3478 | // | |||
3479 | // XXX We don't need to use index if name is there | |||
3480 | // XXXbz We don't? Why not? I don't follow. | |||
3481 | // | |||
3482 | if (const auto* control = nsIFormControl::FromNode(aContent)) { | |||
3483 | // Get the control number if this was a parser inserted element from the | |||
3484 | // network. | |||
3485 | int32_t controlNumber = | |||
3486 | control->GetParserInsertedControlNumberForStateKey(); | |||
3487 | bool parserInserted = controlNumber != -1; | |||
3488 | ||||
3489 | RefPtr<nsContentList> htmlForms; | |||
3490 | RefPtr<nsContentList> htmlFormControls; | |||
3491 | if (!parserInserted) { | |||
3492 | // Getting these lists is expensive, as we need to keep them up to date | |||
3493 | // as the document loads, so we avoid it if we don't need them. | |||
3494 | htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms), | |||
3495 | getter_AddRefs(htmlFormControls)); | |||
3496 | } | |||
3497 | ||||
3498 | // Append the control type | |||
3499 | KeyAppendInt(int32_t(control->ControlType()), aKey); | |||
3500 | ||||
3501 | // If in a form, add form name / index of form / index in form | |||
3502 | HTMLFormElement* formElement = control->GetForm(); | |||
3503 | if (formElement) { | |||
3504 | if (IsAutocompleteOff(formElement)) { | |||
3505 | aKey.Truncate(); | |||
3506 | return; | |||
3507 | } | |||
3508 | ||||
3509 | // Append the form number, if this is a parser inserted control, or | |||
3510 | // the index of the form in the document otherwise. | |||
3511 | bool appendedForm = false; | |||
3512 | if (parserInserted) { | |||
3513 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3515); 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 { *((volatile int*)__null) = 3515; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
3514 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3515); 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 { *((volatile int*)__null) = 3515; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
3515 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3515); 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 { *((volatile int*)__null) = 3515; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3516 | KeyAppendString("fp"_ns, aKey); | |||
3517 | KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey); | |||
3518 | appendedForm = true; | |||
3519 | } else { | |||
3520 | KeyAppendString("fn"_ns, aKey); | |||
3521 | int32_t index = htmlForms->IndexOf(formElement, false); | |||
3522 | if (index <= -1) { | |||
3523 | // | |||
3524 | // XXX HACK this uses some state that was dumped into the document | |||
3525 | // specifically to fix bug 138892. What we are trying to do is | |||
3526 | // *guess* which form this control's state is found in, with the | |||
3527 | // highly likely guess that the highest form parsed so far is the | |||
3528 | // one. This code should not be on trunk, only branch. | |||
3529 | // | |||
3530 | index = htmlDoc->GetNumFormsSynchronous() - 1; | |||
3531 | } | |||
3532 | if (index > -1) { | |||
3533 | KeyAppendInt(index, aKey); | |||
3534 | appendedForm = true; | |||
3535 | } | |||
3536 | } | |||
3537 | ||||
3538 | if (appendedForm) { | |||
3539 | // Append the index of the control in the form | |||
3540 | int32_t index = formElement->IndexOfContent(aContent); | |||
3541 | ||||
3542 | if (index > -1) { | |||
3543 | KeyAppendInt(index, aKey); | |||
3544 | generatedUniqueKey = true; | |||
3545 | } | |||
3546 | } | |||
3547 | ||||
3548 | // Append the form name | |||
3549 | nsAutoString formName; | |||
3550 | formElement->GetAttr(nsGkAtoms::name, formName); | |||
3551 | KeyAppendString(formName, aKey); | |||
3552 | } else { | |||
3553 | // Not in a form. Append the control number, if this is a parser | |||
3554 | // inserted control, or the index of the control in the document | |||
3555 | // otherwise. | |||
3556 | if (parserInserted) { | |||
3557 | KeyAppendString("dp"_ns, aKey); | |||
3558 | KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(), | |||
3559 | aKey); | |||
3560 | generatedUniqueKey = true; | |||
3561 | } else { | |||
3562 | KeyAppendString("dn"_ns, aKey); | |||
3563 | int32_t index = htmlFormControls->IndexOf(aContent, true); | |||
3564 | if (index > -1) { | |||
3565 | KeyAppendInt(index, aKey); | |||
3566 | generatedUniqueKey = true; | |||
3567 | } | |||
3568 | } | |||
3569 | ||||
3570 | // Append the control name | |||
3571 | nsAutoString name; | |||
3572 | aContent->AsElement()->GetAttr(nsGkAtoms::name, name); | |||
3573 | KeyAppendString(name, aKey); | |||
3574 | } | |||
3575 | } | |||
3576 | } | |||
3577 | ||||
3578 | if (!generatedUniqueKey) { | |||
3579 | // Either we didn't have a form control or we aren't in an HTML document so | |||
3580 | // we can't figure out form info. Append the tag name if it's an element | |||
3581 | // to avoid restoring state for one type of element on another type. | |||
3582 | if (aContent->IsElement()) { | |||
3583 | KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()), | |||
3584 | aKey); | |||
3585 | } else { | |||
3586 | // Append a character that is not "d" or "f" to disambiguate from | |||
3587 | // the case when we were a form control in an HTML document. | |||
3588 | KeyAppendString("o"_ns, aKey); | |||
3589 | } | |||
3590 | ||||
3591 | // Now start at aContent and append the indices of it and all its ancestors | |||
3592 | // in their containers. That should at least pin down its position in the | |||
3593 | // DOM... | |||
3594 | nsINode* parent = aContent->GetParentNode(); | |||
3595 | nsINode* content = aContent; | |||
3596 | while (parent) { | |||
3597 | KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey); | |||
3598 | content = parent; | |||
3599 | parent = content->GetParentNode(); | |||
3600 | } | |||
3601 | } | |||
3602 | } | |||
3603 | ||||
3604 | // static | |||
3605 | nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) { | |||
3606 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3606; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3607 | ||||
3608 | // As opposed to SubjectPrincipal(), we do in fact assume that | |||
3609 | // we're in a realm here; anyone who calls this function in | |||
3610 | // situations where that's not the case is doing it wrong. | |||
3611 | JS::Realm* realm = js::GetContextRealm(aCx); | |||
3612 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")") ; do { *((volatile int*)__null) = 3612; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3613 | ||||
3614 | JSPrincipals* principals = JS::GetRealmPrincipals(realm); | |||
3615 | return nsJSPrincipals::get(principals); | |||
3616 | } | |||
3617 | ||||
3618 | // static | |||
3619 | nsIPrincipal* nsContentUtils::SubjectPrincipal() { | |||
3620 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { *((volatile int*)__null) = 3620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3621 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3622 | JSContext* cx = GetCurrentJSContext(); | |||
3623 | if (!cx) { | |||
3624 | MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__ ((nomerge)) ::abort(); } while (false); } while (false) | |||
3625 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__ ((nomerge)) ::abort(); } while (false); } while (false) | |||
3626 | "forbidden")do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3626); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is " "forbidden" ")"); do { *((volatile int*)__null) = 3626; __attribute__ ((nomerge)) ::abort(); } while (false); } while (false); | |||
3627 | } | |||
3628 | ||||
3629 | JS::Realm* realm = js::GetContextRealm(cx); | |||
3630 | ||||
3631 | // When an AutoJSAPI is instantiated, we are in a null realm until the | |||
3632 | // first JSAutoRealm, which is kind of a purgatory as far as permissions | |||
3633 | // go. It would be nice to just hard-abort if somebody does a security check | |||
3634 | // in this purgatory zone, but that would be too fragile, since it could be | |||
3635 | // triggered by random IsCallerChrome() checks 20-levels deep. | |||
3636 | // | |||
3637 | // So we want to return _something_ here - and definitely not the System | |||
3638 | // Principal, since that would make an AutoJSAPI a very dangerous thing to | |||
3639 | // instantiate. | |||
3640 | // | |||
3641 | // The natural thing to return is a null principal. Ideally, we'd return a | |||
3642 | // different null principal each time, to avoid any unexpected interactions | |||
3643 | // when the principal accidentally gets inherited somewhere. But | |||
3644 | // SubjectPrincipal doesn't return strong references, so there's no way to | |||
3645 | // sanely manage the lifetime of multiple null principals. | |||
3646 | // | |||
3647 | // So we use a singleton null principal. To avoid it being accidentally | |||
3648 | // inherited and becoming a "real" subject or object principal, we do a | |||
3649 | // release-mode assert during realm creation against using this principal on | |||
3650 | // an actual global. | |||
3651 | if (!realm) { | |||
3652 | return sNullSubjectPrincipal; | |||
3653 | } | |||
3654 | ||||
3655 | return SubjectPrincipal(cx); | |||
3656 | } | |||
3657 | ||||
3658 | // static | |||
3659 | nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) { | |||
3660 | #ifdef DEBUG1 | |||
3661 | JS::AssertObjectBelongsToCurrentThread(aObj); | |||
3662 | #endif | |||
3663 | ||||
3664 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3664); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)" ")"); do { *((volatile int*)__null) = 3664; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3665 | ||||
3666 | JS::Realm* realm = js::GetNonCCWObjectRealm(aObj); | |||
3667 | JSPrincipals* principals = JS::GetRealmPrincipals(realm); | |||
3668 | return nsJSPrincipals::get(principals); | |||
3669 | } | |||
3670 | ||||
3671 | // static | |||
3672 | nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult, | |||
3673 | const nsAString& aSpec, | |||
3674 | Document* aDocument, | |||
3675 | nsIURI* aBaseURI) { | |||
3676 | if (aDocument) { | |||
3677 | return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(), | |||
3678 | aBaseURI); | |||
3679 | } | |||
3680 | return NS_NewURI(aResult, aSpec, nullptr, aBaseURI); | |||
3681 | } | |||
3682 | ||||
3683 | // static | |||
3684 | bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) { | |||
3685 | const uint32_t len = aAtom->GetLength(); | |||
3686 | if (!len) { | |||
3687 | return false; | |||
3688 | } | |||
3689 | const char16_t* name = aAtom->GetUTF16String(); | |||
3690 | uint32_t i = 0; | |||
3691 | while (i < len) { | |||
3692 | if (name[i] == aChar) { | |||
3693 | return true; | |||
3694 | } | |||
3695 | i++; | |||
3696 | } | |||
3697 | return false; | |||
3698 | } | |||
3699 | ||||
3700 | // static | |||
3701 | bool nsContentUtils::IsNameWithDash(nsAtom* aName) { | |||
3702 | // A valid custom element name is a sequence of characters name which | |||
3703 | // must match the PotentialCustomElementName production: | |||
3704 | // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)* | |||
3705 | const char16_t* name = aName->GetUTF16String(); | |||
3706 | uint32_t len = aName->GetLength(); | |||
3707 | bool hasDash = false; | |||
3708 | ||||
3709 | if (!len || name[0] < 'a' || name[0] > 'z') { | |||
3710 | return false; | |||
3711 | } | |||
3712 | ||||
3713 | uint32_t i = 1; | |||
3714 | while (i < len) { | |||
3715 | if (i + 1 < len && NS_IS_SURROGATE_PAIR(name[i], name[i + 1])(((uint32_t(name[i]) & 0xFFFFFC00) == 0xD800) && ( (uint32_t(name[i + 1]) & 0xFFFFFC00) == 0xDC00))) { | |||
3716 | // Merged two 16-bit surrogate pairs into code point. | |||
3717 | char32_t code = SURROGATE_TO_UCS4(name[i], name[i + 1])(((uint32_t(name[i]) & 0x03FF) << 10) + (uint32_t(name [i + 1]) & 0x03FF) + uint32_t(0x00010000)); | |||
3718 | ||||
3719 | if (code < 0x10000 || code > 0xEFFFF) { | |||
3720 | return false; | |||
3721 | } | |||
3722 | ||||
3723 | i += 2; | |||
3724 | } else { | |||
3725 | if (name[i] == '-') { | |||
3726 | hasDash = true; | |||
3727 | } | |||
3728 | ||||
3729 | if (name[i] != '-' && name[i] != '.' && name[i] != '_' && | |||
3730 | name[i] != 0xB7 && (name[i] < '0' || name[i] > '9') && | |||
3731 | (name[i] < 'a' || name[i] > 'z') && | |||
3732 | (name[i] < 0xC0 || name[i] > 0xD6) && | |||
3733 | (name[i] < 0xF8 || name[i] > 0x37D) && | |||
3734 | (name[i] < 0x37F || name[i] > 0x1FFF) && | |||
3735 | (name[i] < 0x200C || name[i] > 0x200D) && | |||
3736 | (name[i] < 0x203F || name[i] > 0x2040) && | |||
3737 | (name[i] < 0x2070 || name[i] > 0x218F) && | |||
3738 | (name[i] < 0x2C00 || name[i] > 0x2FEF) && | |||
3739 | (name[i] < 0x3001 || name[i] > 0xD7FF) && | |||
3740 | (name[i] < 0xF900 || name[i] > 0xFDCF) && | |||
3741 | (name[i] < 0xFDF0 || name[i] > 0xFFFD)) { | |||
3742 | return false; | |||
3743 | } | |||
3744 | ||||
3745 | i++; | |||
3746 | } | |||
3747 | } | |||
3748 | ||||
3749 | return hasDash; | |||
3750 | } | |||
3751 | ||||
3752 | // static | |||
3753 | bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) { | |||
3754 | // Allow non-dashed names in XUL for XBL to Custom Element migrations. | |||
3755 | if (aNameSpaceID == kNameSpaceID_XUL8) { | |||
3756 | return true; | |||
3757 | } | |||
3758 | ||||
3759 | bool hasDash = IsNameWithDash(aName); | |||
3760 | if (!hasDash) { | |||
3761 | return false; | |||
3762 | } | |||
3763 | ||||
3764 | // The custom element name must not be one of the following values: | |||
3765 | // annotation-xml | |||
3766 | // color-profile | |||
3767 | // font-face | |||
3768 | // font-face-src | |||
3769 | // font-face-uri | |||
3770 | // font-face-format | |||
3771 | // font-face-name | |||
3772 | // missing-glyph | |||
3773 | return aName != nsGkAtoms::annotation_xml_ && | |||
3774 | aName != nsGkAtoms::colorProfile && aName != nsGkAtoms::font_face && | |||
3775 | aName != nsGkAtoms::font_face_src && | |||
3776 | aName != nsGkAtoms::font_face_uri && | |||
3777 | aName != nsGkAtoms::font_face_format && | |||
3778 | aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph; | |||
3779 | } | |||
3780 | ||||
3781 | // static | |||
3782 | nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName, | |||
3783 | bool aNamespaceAware, | |||
3784 | const char16_t** aColon) { | |||
3785 | const char* colon = nullptr; | |||
3786 | const char16_t* begin = aQualifiedName.BeginReading(); | |||
3787 | const char16_t* end = aQualifiedName.EndReading(); | |||
3788 | ||||
3789 | int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin), | |||
3790 | reinterpret_cast<const char*>(end), | |||
3791 | aNamespaceAware, &colon); | |||
3792 | ||||
3793 | if (!result) { | |||
3794 | if (aColon) { | |||
3795 | *aColon = reinterpret_cast<const char16_t*>(colon); | |||
3796 | } | |||
3797 | ||||
3798 | return NS_OK; | |||
3799 | } | |||
3800 | ||||
3801 | return NS_ERROR_DOM_INVALID_CHARACTER_ERR; | |||
3802 | } | |||
3803 | ||||
3804 | // static | |||
3805 | nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver, | |||
3806 | const nsString& aQName, int32_t* aNamespace, | |||
3807 | nsAtom** aLocalName) { | |||
3808 | const char16_t* colon; | |||
3809 | nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon); | |||
3810 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3810); return rv; } } while (false); | |||
3811 | ||||
3812 | if (colon) { | |||
3813 | const char16_t* end; | |||
3814 | aQName.EndReading(end); | |||
3815 | nsAutoString nameSpace; | |||
3816 | rv = aNamespaceResolver->LookupNamespaceURIInternal( | |||
3817 | Substring(aQName.get(), colon), nameSpace); | |||
3818 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3818); return rv; } } while (false); | |||
3819 | ||||
3820 | *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID( | |||
3821 | nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc())); | |||
3822 | if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE; | |||
3823 | ||||
3824 | *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take(); | |||
3825 | } else { | |||
3826 | *aNamespace = kNameSpaceID_None; | |||
3827 | *aLocalName = NS_AtomizeMainThread(aQName).take(); | |||
3828 | } | |||
3829 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3829); return NS_ERROR_OUT_OF_MEMORY; } } while (false); | |||
3830 | return NS_OK; | |||
3831 | } | |||
3832 | ||||
3833 | // static | |||
3834 | nsresult nsContentUtils::GetNodeInfoFromQName( | |||
3835 | const nsAString& aNamespaceURI, const nsAString& aQualifiedName, | |||
3836 | nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType, | |||
3837 | mozilla::dom::NodeInfo** aNodeInfo) { | |||
3838 | const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName); | |||
3839 | const char16_t* colon; | |||
3840 | nsresult rv = nsContentUtils::CheckQName(qName, true, &colon); | |||
3841 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3841); return rv; } } while (false); | |||
3842 | ||||
3843 | int32_t nsID; | |||
3844 | nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID); | |||
3845 | if (colon) { | |||
3846 | const char16_t* end; | |||
3847 | qName.EndReading(end); | |||
3848 | ||||
3849 | RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon)); | |||
3850 | ||||
3851 | rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix, nsID, | |||
3852 | aNodeType, aNodeInfo); | |||
3853 | } else { | |||
3854 | rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType, | |||
3855 | aNodeInfo); | |||
3856 | } | |||
3857 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3857); return rv; } } while (false); | |||
3858 | ||||
3859 | return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(), | |||
3860 | (*aNodeInfo)->GetPrefixAtom(), | |||
3861 | (*aNodeInfo)->NamespaceID()) | |||
3862 | ? NS_OK | |||
3863 | : NS_ERROR_DOM_NAMESPACE_ERR; | |||
3864 | } | |||
3865 | ||||
3866 | // static | |||
3867 | void nsContentUtils::SplitExpatName(const char16_t* aExpatName, | |||
3868 | nsAtom** aPrefix, nsAtom** aLocalName, | |||
3869 | int32_t* aNameSpaceID) { | |||
3870 | /** | |||
3871 | * Expat can send the following: | |||
3872 | * localName | |||
3873 | * namespaceURI<separator>localName | |||
3874 | * namespaceURI<separator>localName<separator>prefix | |||
3875 | * | |||
3876 | * and we use 0xFFFF for the <separator>. | |||
3877 | * | |||
3878 | */ | |||
3879 | ||||
3880 | const char16_t* uriEnd = nullptr; | |||
3881 | const char16_t* nameEnd = nullptr; | |||
3882 | const char16_t* pos; | |||
3883 | for (pos = aExpatName; *pos; ++pos) { | |||
3884 | if (*pos == 0xFFFF) { | |||
3885 | if (uriEnd) { | |||
3886 | nameEnd = pos; | |||
3887 | } else { | |||
3888 | uriEnd = pos; | |||
3889 | } | |||
3890 | } | |||
3891 | } | |||
3892 | ||||
3893 | const char16_t* nameStart; | |||
3894 | if (uriEnd) { | |||
3895 | nsNameSpaceManager::GetInstance()->RegisterNameSpace( | |||
3896 | nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID); | |||
3897 | ||||
3898 | nameStart = (uriEnd + 1); | |||
3899 | if (nameEnd) { | |||
3900 | const char16_t* prefixStart = nameEnd + 1; | |||
3901 | *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take(); | |||
3902 | } else { | |||
3903 | nameEnd = pos; | |||
3904 | *aPrefix = nullptr; | |||
3905 | } | |||
3906 | } else { | |||
3907 | *aNameSpaceID = kNameSpaceID_None; | |||
3908 | nameStart = aExpatName; | |||
3909 | nameEnd = pos; | |||
3910 | *aPrefix = nullptr; | |||
3911 | } | |||
3912 | *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take(); | |||
3913 | } | |||
3914 | ||||
3915 | // static | |||
3916 | PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) { | |||
3917 | Document* doc = aContent->GetComposedDoc(); | |||
3918 | if (!doc) { | |||
3919 | return nullptr; | |||
3920 | } | |||
3921 | return doc->GetPresShell(); | |||
3922 | } | |||
3923 | ||||
3924 | // static | |||
3925 | nsPresContext* nsContentUtils::GetContextForContent( | |||
3926 | const nsIContent* aContent) { | |||
3927 | PresShell* presShell = GetPresShellForContent(aContent); | |||
3928 | if (!presShell) { | |||
3929 | return nullptr; | |||
3930 | } | |||
3931 | return presShell->GetPresContext(); | |||
3932 | } | |||
3933 | ||||
3934 | // static | |||
3935 | bool nsContentUtils::CanLoadImage(nsIURI* aURI, nsINode* aNode, | |||
3936 | Document* aLoadingDocument, | |||
3937 | nsIPrincipal* aLoadingPrincipal) { | |||
3938 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { *((volatile int*)__null) = 3938 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
3939 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument" ") (" "Must have a document" ")"); do { *((volatile int*)__null ) = 3939; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
3940 | MOZ_ASSERT(aLoadingPrincipal, "Must have a loading 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 loading principal" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 3940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Must have a loading principal" ")"); do { *((volatile int*)__null) = 3940; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
3941 | ||||
3942 | nsresult rv; | |||
3943 | ||||
3944 | auto appType = nsIDocShell::APP_TYPE_UNKNOWN; | |||
3945 | ||||
3946 | { | |||
3947 | nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = | |||
3948 | aLoadingDocument->GetDocShell(); | |||
3949 | if (docShellTreeItem) { | |||
3950 | nsCOMPtr<nsIDocShellTreeItem> root; | |||
3951 | docShellTreeItem->GetInProcessRootTreeItem(getter_AddRefs(root)); | |||
3952 | ||||
3953 | nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root)); | |||
3954 | ||||
3955 | if (docShell) { | |||
3956 | appType = docShell->GetAppType(); | |||
3957 | } | |||
3958 | } | |||
3959 | } | |||
3960 | ||||
3961 | if (appType != nsIDocShell::APP_TYPE_EDITOR) { | |||
3962 | // Editor apps get special treatment here, editors can load images | |||
3963 | // from anywhere. This allows editor to insert images from file:// | |||
3964 | // into documents that are being edited. | |||
3965 | rv = sSecurityManager->CheckLoadURIWithPrincipal( | |||
3966 | aLoadingPrincipal, aURI, nsIScriptSecurityManager::ALLOW_CHROME, | |||
3967 | aLoadingDocument->InnerWindowID()); | |||
3968 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
3969 | return false; | |||
3970 | } | |||
3971 | } | |||
3972 | ||||
3973 | nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new mozilla::net::LoadInfo( | |||
3974 | aLoadingPrincipal, | |||
3975 | aLoadingPrincipal, // triggering principal | |||
3976 | aNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, | |||
3977 | nsIContentPolicy::TYPE_INTERNAL_IMAGE); | |||
3978 | ||||
3979 | int16_t decision = nsIContentPolicy::ACCEPT; | |||
3980 | ||||
3981 | rv = NS_CheckContentLoadPolicy(aURI, secCheckLoadInfo, &decision, | |||
3982 | GetContentPolicy()); | |||
3983 | ||||
3984 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && NS_CP_ACCEPTED(decision)((decision) == nsIContentPolicy::ACCEPT); | |||
3985 | } | |||
3986 | ||||
3987 | // static | |||
3988 | bool nsContentUtils::IsInPrivateBrowsing(const Document* aDoc) { | |||
3989 | if (!aDoc) { | |||
3990 | return false; | |||
3991 | } | |||
3992 | ||||
3993 | nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup(); | |||
3994 | // See duplicated code below in IsInPrivateBrowsing(nsILoadGroup*) | |||
3995 | // and Document::Reset/ResetToURI | |||
3996 | if (loadGroup) { | |||
3997 | nsCOMPtr<nsIInterfaceRequestor> callbacks; | |||
3998 | loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); | |||
3999 | if (callbacks) { | |||
4000 | nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); | |||
4001 | if (loadContext) { | |||
4002 | return loadContext->UsePrivateBrowsing(); | |||
4003 | } | |||
4004 | } | |||
4005 | } | |||
4006 | ||||
4007 | nsCOMPtr<nsIChannel> channel = aDoc->GetChannel(); | |||
4008 | return channel && NS_UsePrivateBrowsing(channel); | |||
4009 | } | |||
4010 | ||||
4011 | // static | |||
4012 | bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) { | |||
4013 | if (!aLoadGroup) { | |||
4014 | return false; | |||
4015 | } | |||
4016 | bool isPrivate = false; | |||
4017 | nsCOMPtr<nsIInterfaceRequestor> callbacks; | |||
4018 | aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); | |||
4019 | if (callbacks) { | |||
4020 | nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); | |||
4021 | isPrivate = loadContext && loadContext->UsePrivateBrowsing(); | |||
4022 | } | |||
4023 | return isPrivate; | |||
4024 | } | |||
4025 | ||||
4026 | // FIXME(emilio): This is (effectively) almost but not quite the same as | |||
4027 | // Document::ShouldLoadImages(), which one is right? | |||
4028 | bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) { | |||
4029 | if (!aDocument) { | |||
4030 | return false; | |||
4031 | } | |||
4032 | if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() || | |||
4033 | aDocument->IsStaticDocument()) { | |||
4034 | return false; | |||
4035 | } | |||
4036 | nsCOMPtr<nsPIDOMWindowInner> win = | |||
4037 | do_QueryInterface(aDocument->GetScopeObject()); | |||
4038 | return !win || !win->GetDocShell(); | |||
4039 | } | |||
4040 | ||||
4041 | imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) { | |||
4042 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4042); return nullptr; } } while (false); | |||
4043 | ||||
4044 | if (!aDoc) { | |||
4045 | return imgLoader::NormalLoader(); | |||
4046 | } | |||
4047 | bool isPrivate = IsInPrivateBrowsing(aDoc); | |||
4048 | return isPrivate ? imgLoader::PrivateBrowsingLoader() | |||
4049 | : imgLoader::NormalLoader(); | |||
4050 | } | |||
4051 | ||||
4052 | // static | |||
4053 | imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel, | |||
4054 | Document* aContext) { | |||
4055 | 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 , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4055); return nullptr; } } while (false); | |||
4056 | ||||
4057 | if (!aChannel) { | |||
4058 | return imgLoader::NormalLoader(); | |||
4059 | } | |||
4060 | return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader() | |||
4061 | : imgLoader::NormalLoader(); | |||
4062 | } | |||
4063 | ||||
4064 | // static | |||
4065 | int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) { | |||
4066 | switch (aMode) { | |||
4067 | case CORS_ANONYMOUS: | |||
4068 | return imgILoader::LOAD_CORS_ANONYMOUS; | |||
4069 | case CORS_USE_CREDENTIALS: | |||
4070 | return imgILoader::LOAD_CORS_USE_CREDENTIALS; | |||
4071 | default: | |||
4072 | return 0; | |||
4073 | } | |||
4074 | } | |||
4075 | ||||
4076 | // static | |||
4077 | nsresult nsContentUtils::LoadImage( | |||
4078 | nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument, | |||
4079 | nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID, | |||
4080 | nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver, | |||
4081 | int32_t aLoadFlags, const nsAString& initiatorType, | |||
4082 | imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType, | |||
4083 | bool aUseUrgentStartForChannel, bool aLinkPreload, | |||
4084 | uint64_t aEarlyHintPreloaderId, | |||
4085 | mozilla::dom::FetchPriority aFetchPriority) { | |||
4086 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { *((volatile int*)__null) = 4086 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4087 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") (" "Must have a context" ")"); do { *((volatile int*)__null) = 4087 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4088 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4088); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument" ") (" "Must have a document" ")"); do { *((volatile int*)__null ) = 4088; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
4089 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4089); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Must have a principal" ")"); do { *((volatile int*)__null ) = 4089; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
4090 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") (" "Null out param" ")"); do { *((volatile int*)__null) = 4090; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4091 | ||||
4092 | imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument); | |||
4093 | if (!imgLoader) { | |||
4094 | // nothing we can do here | |||
4095 | return NS_ERROR_FAILURE; | |||
4096 | } | |||
4097 | ||||
4098 | nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup(); | |||
4099 | ||||
4100 | nsIURI* documentURI = aLoadingDocument->GetDocumentURI(); | |||
4101 | ||||
4102 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4103); MOZ_PretendNoReturn(); } } while (0) | |||
4103 | "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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4103); MOZ_PretendNoReturn(); } } while (0); | |||
4104 | ||||
4105 | // XXXbz using "documentURI" for the initialDocumentURI is not quite | |||
4106 | // right, but the best we can do here... | |||
4107 | return imgLoader->LoadImage(aURI, /* uri to load */ | |||
4108 | documentURI, /* initialDocumentURI */ | |||
4109 | aReferrerInfo, /* referrerInfo */ | |||
4110 | aLoadingPrincipal, /* loading principal */ | |||
4111 | aRequestContextID, /* request context ID */ | |||
4112 | loadGroup, /* loadgroup */ | |||
4113 | aObserver, /* imgINotificationObserver */ | |||
4114 | aContext, /* loading context */ | |||
4115 | aLoadingDocument, /* uniquification key */ | |||
4116 | aLoadFlags, /* load flags */ | |||
4117 | nullptr, /* cache key */ | |||
4118 | aContentPolicyType, /* content policy type */ | |||
4119 | initiatorType, /* the load initiator */ | |||
4120 | aUseUrgentStartForChannel, /* urgent-start flag */ | |||
4121 | aLinkPreload, /* <link preload> initiator */ | |||
4122 | aEarlyHintPreloaderId, aFetchPriority, aRequest); | |||
4123 | } | |||
4124 | ||||
4125 | // static | |||
4126 | already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent( | |||
4127 | nsIImageLoadingContent* aContent, imgIRequest** aRequest) { | |||
4128 | if (aRequest) { | |||
4129 | *aRequest = nullptr; | |||
4130 | } | |||
4131 | ||||
4132 | NS_ENSURE_TRUE(aContent, nullptr)do { if ((__builtin_expect(!!(!(aContent)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContent" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4132); return nullptr; } } while (false); | |||
4133 | ||||
4134 | nsCOMPtr<imgIRequest> imgRequest; | |||
4135 | aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, | |||
4136 | getter_AddRefs(imgRequest)); | |||
4137 | if (!imgRequest) { | |||
4138 | return nullptr; | |||
4139 | } | |||
4140 | ||||
4141 | nsCOMPtr<imgIContainer> imgContainer; | |||
4142 | imgRequest->GetImage(getter_AddRefs(imgContainer)); | |||
4143 | ||||
4144 | if (!imgContainer) { | |||
4145 | return nullptr; | |||
4146 | } | |||
4147 | ||||
4148 | if (aRequest) { | |||
4149 | // If the consumer wants the request, verify it has actually loaded | |||
4150 | // successfully. | |||
4151 | uint32_t imgStatus; | |||
4152 | imgRequest->GetImageStatus(&imgStatus); | |||
4153 | if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE && | |||
4154 | !(imgStatus & imgIRequest::STATUS_ERROR)) { | |||
4155 | imgRequest.swap(*aRequest); | |||
4156 | } | |||
4157 | } | |||
4158 | ||||
4159 | return imgContainer.forget(); | |||
4160 | } | |||
4161 | ||||
4162 | static bool IsLinkWithURI(const nsIContent& aContent) { | |||
4163 | const auto* element = Element::FromNode(aContent); | |||
4164 | if (!element || !element->IsLink()) { | |||
4165 | return false; | |||
4166 | } | |||
4167 | nsCOMPtr<nsIURI> absURI = element->GetHrefURI(); | |||
4168 | return !!absURI; | |||
4169 | } | |||
4170 | ||||
4171 | static bool HasImageRequest(nsIContent& aContent) { | |||
4172 | nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent)); | |||
4173 | if (!imageContent) { | |||
4174 | return false; | |||
4175 | } | |||
4176 | ||||
4177 | nsCOMPtr<imgIRequest> imgRequest; | |||
4178 | imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, | |||
4179 | getter_AddRefs(imgRequest)); | |||
4180 | ||||
4181 | // XXXbz It may be draggable even if the request resulted in an error. Why? | |||
4182 | // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did. | |||
4183 | return !!imgRequest; | |||
4184 | } | |||
4185 | ||||
4186 | static Maybe<bool> DraggableOverride(const nsIContent& aContent) { | |||
4187 | if (auto* el = nsGenericHTMLElement::FromNode(aContent)) { | |||
4188 | if (el->Draggable()) { | |||
4189 | return Some(true); | |||
4190 | } | |||
4191 | ||||
4192 | if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, | |||
4193 | nsGkAtoms::_false, eIgnoreCase)) { | |||
4194 | return Some(false); | |||
4195 | } | |||
4196 | } | |||
4197 | if (aContent.IsSVGElement()) { | |||
4198 | return Some(false); | |||
4199 | } | |||
4200 | return Nothing(); | |||
4201 | } | |||
4202 | ||||
4203 | // static | |||
4204 | bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) { | |||
4205 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { *((volatile int*)__null) = 4205; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4206 | ||||
4207 | if (auto draggable = DraggableOverride(*aContent)) { | |||
4208 | return *draggable; | |||
4209 | } | |||
4210 | ||||
4211 | // special handling for content area image and link dragging | |||
4212 | return HasImageRequest(*aContent) || IsLinkWithURI(*aContent); | |||
4213 | } | |||
4214 | ||||
4215 | // static | |||
4216 | bool nsContentUtils::IsDraggableImage(nsIContent* aContent) { | |||
4217 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { *((volatile int*)__null) = 4217; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4218 | return HasImageRequest(*aContent) && | |||
4219 | DraggableOverride(*aContent).valueOr(true); | |||
4220 | } | |||
4221 | ||||
4222 | // static | |||
4223 | bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) { | |||
4224 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")" ); do { *((volatile int*)__null) = 4224; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4225 | return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true); | |||
4226 | } | |||
4227 | ||||
4228 | // static | |||
4229 | nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo, | |||
4230 | nsAtom* aName, | |||
4231 | mozilla::dom::NodeInfo** aResult) { | |||
4232 | nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager(); | |||
4233 | ||||
4234 | *aResult = niMgr | |||
4235 | ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(), | |||
4236 | aNodeInfo->NodeType(), aNodeInfo->GetExtraName()) | |||
4237 | .take(); | |||
4238 | return NS_OK; | |||
4239 | } | |||
4240 | ||||
4241 | static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType, | |||
4242 | uint32_t aPerm, bool aExactHostMatch) { | |||
4243 | if (!aPrincipal) { | |||
4244 | // We always deny (i.e. don't allow) the permission if we don't have a | |||
4245 | // principal. | |||
4246 | return aPerm != nsIPermissionManager::ALLOW_ACTION; | |||
4247 | } | |||
4248 | ||||
4249 | nsCOMPtr<nsIPermissionManager> permMgr = | |||
4250 | components::PermissionManager::Service(); | |||
4251 | NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4251); return false; } } while (false); | |||
4252 | ||||
4253 | uint32_t perm; | |||
4254 | nsresult rv; | |||
4255 | if (aExactHostMatch) { | |||
4256 | rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
4257 | } else { | |||
4258 | rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
4259 | } | |||
4260 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4260); return false; } } while (false); | |||
4261 | ||||
4262 | return perm == aPerm; | |||
4263 | } | |||
4264 | ||||
4265 | bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, | |||
4266 | const nsACString& aType) { | |||
4267 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, | |||
4268 | false); | |||
4269 | } | |||
4270 | ||||
4271 | bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal, | |||
4272 | const nsACString& aType) { | |||
4273 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, | |||
4274 | false); | |||
4275 | } | |||
4276 | ||||
4277 | bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal, | |||
4278 | const nsACString& aType) { | |||
4279 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, | |||
4280 | true); | |||
4281 | } | |||
4282 | ||||
4283 | bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal, | |||
4284 | const nsACString& aType) { | |||
4285 | return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, | |||
4286 | true); | |||
4287 | } | |||
4288 | ||||
4289 | bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal, | |||
4290 | const nsACString& aType) { | |||
4291 | if (!aPrincipal) { | |||
4292 | return false; | |||
4293 | } | |||
4294 | ||||
4295 | nsCOMPtr<nsIPermissionManager> permMgr = | |||
4296 | components::PermissionManager::Service(); | |||
4297 | NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4297); return false; } } while (false); | |||
4298 | ||||
4299 | uint32_t perm; | |||
4300 | nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm); | |||
4301 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4301); return false; } } while (false); | |||
4302 | ||||
4303 | return perm != nsIPermissionManager::UNKNOWN_ACTION; | |||
4304 | } | |||
4305 | ||||
4306 | static const char* gEventNames[] = {"event"}; | |||
4307 | static const char* gSVGEventNames[] = {"evt"}; | |||
4308 | // for b/w compat, the first name to onerror is still 'event', even though it | |||
4309 | // is actually the error message | |||
4310 | static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno", | |||
4311 | "error"}; | |||
4312 | ||||
4313 | // static | |||
4314 | void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName, | |||
4315 | bool aIsForWindow, uint32_t* aArgCount, | |||
4316 | const char*** aArgArray) { | |||
4317 | #define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names ; \ | |||
4318 | *aArgCount = sizeof(names) / sizeof(names[0]); \ | |||
4319 | *aArgArray = names; | |||
4320 | ||||
4321 | // JSEventHandler is what does the arg magic for onerror, and it does | |||
4322 | // not seem to take the namespace into account. So we let onerror in all | |||
4323 | // namespaces get the 3 arg names. | |||
4324 | if (aEventName == nsGkAtoms::onerror && aIsForWindow) { | |||
4325 | SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0]) ; *aArgArray = gOnErrorNames;; | |||
4326 | } else if (aNameSpaceID == kNameSpaceID_SVG9) { | |||
4327 | SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0 ]); *aArgArray = gSVGEventNames;; | |||
4328 | } else { | |||
4329 | SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray = gEventNames;; | |||
4330 | } | |||
4331 | } | |||
4332 | ||||
4333 | // Note: The list of content bundles in nsStringBundle.cpp should be updated | |||
4334 | // whenever entries are added or removed from this list. | |||
4335 | static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = { | |||
4336 | // Must line up with the enum values in |PropertiesFile| enum. | |||
4337 | "chrome://global/locale/css.properties", | |||
4338 | "chrome://global/locale/xul.properties", | |||
4339 | "chrome://global/locale/layout_errors.properties", | |||
4340 | "chrome://global/locale/layout/HtmlForm.properties", | |||
4341 | "chrome://global/locale/printing.properties", | |||
4342 | "chrome://global/locale/dom/dom.properties", | |||
4343 | "chrome://global/locale/layout/htmlparser.properties", | |||
4344 | "chrome://global/locale/svg/svg.properties", | |||
4345 | "chrome://branding/locale/brand.properties", | |||
4346 | "chrome://global/locale/commonDialogs.properties", | |||
4347 | "chrome://global/locale/mathml/mathml.properties", | |||
4348 | "chrome://global/locale/security/security.properties", | |||
4349 | "chrome://necko/locale/necko.properties", | |||
4350 | "resource://gre/res/locale/layout/HtmlForm.properties", | |||
4351 | "resource://gre/res/locale/dom/dom.properties"}; | |||
4352 | ||||
4353 | /* static */ | |||
4354 | nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) { | |||
4355 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4356); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()" ") (" "Should not create bundles off main thread." ")"); do { *((volatile int*)__null) = 4356; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
4356 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4356); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()" ") (" "Should not create bundles off main thread." ")"); do { *((volatile int*)__null) = 4356; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
4357 | if (!sStringBundles[aFile]) { | |||
4358 | if (!sStringBundleService) { | |||
4359 | nsresult rv = | |||
4360 | CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService); | |||
4361 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4361); return rv; } } while (false); | |||
4362 | } | |||
4363 | RefPtr<nsIStringBundle> bundle; | |||
4364 | MOZ_TRY(sStringBundleService->CreateBundle(gPropertiesFiles[aFile],do { auto mozTryTempResult_ = ::mozilla::ToResult(sStringBundleService ->CreateBundle(gPropertiesFiles[aFile], getter_AddRefs(bundle ))); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0)) ) { return mozTryTempResult_.propagateErr(); } } while (0) | |||
4365 | getter_AddRefs(bundle)))do { auto mozTryTempResult_ = ::mozilla::ToResult(sStringBundleService ->CreateBundle(gPropertiesFiles[aFile], getter_AddRefs(bundle ))); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0)) ) { return mozTryTempResult_.propagateErr(); } } while (0); | |||
4366 | sStringBundles[aFile] = bundle.forget(); | |||
4367 | } | |||
4368 | return NS_OK; | |||
4369 | } | |||
4370 | ||||
4371 | /* static */ | |||
4372 | void nsContentUtils::AsyncPrecreateStringBundles() { | |||
4373 | // We only ever want to pre-create bundles in the parent process. | |||
4374 | // | |||
4375 | // All nsContentUtils bundles are shared between the parent and child | |||
4376 | // precesses, and the shared memory regions that back them *must* be created | |||
4377 | // in the parent, and then sent to all children. | |||
4378 | // | |||
4379 | // If we attempt to create a bundle in the child before its memory region is | |||
4380 | // available, we need to create a temporary non-shared bundle, and later | |||
4381 | // replace that with the shared memory copy. So attempting to pre-load in the | |||
4382 | // child is wasteful and unnecessary. | |||
4383 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { *((volatile int*)__null) = 4383; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4384 | ||||
4385 | for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT; | |||
4386 | ++bundleIndex) { | |||
4387 | nsresult rv = NS_DispatchToCurrentThreadQueue( | |||
4388 | NS_NewRunnableFunction("AsyncPrecreateStringBundles", | |||
4389 | [bundleIndex]() { | |||
4390 | PropertiesFile file = | |||
4391 | static_cast<PropertiesFile>(bundleIndex); | |||
4392 | EnsureStringBundle(file); | |||
4393 | nsIStringBundle* bundle = sStringBundles[file]; | |||
4394 | bundle->AsyncPreload(); | |||
4395 | }), | |||
4396 | EventQueuePriority::Idle); | |||
4397 | Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4397); | |||
4398 | } | |||
4399 | } | |||
4400 | ||||
4401 | /* static */ | |||
4402 | bool nsContentUtils::SpoofLocaleEnglish() { | |||
4403 | // 0 - will prompt | |||
4404 | // 1 - don't spoof | |||
4405 | // 2 - spoof | |||
4406 | return StaticPrefs::privacy_spoof_english() == 2; | |||
4407 | } | |||
4408 | ||||
4409 | static nsContentUtils::PropertiesFile GetMaybeSpoofedPropertiesFile( | |||
4410 | nsContentUtils::PropertiesFile aFile, const char* aKey, | |||
4411 | Document* aDocument) { | |||
4412 | // When we spoof English, use en-US properties in strings that are accessible | |||
4413 | // by content. | |||
4414 | bool spoofLocale = nsContentUtils::SpoofLocaleEnglish() && | |||
4415 | (!aDocument || !aDocument->AllowsL10n()); | |||
4416 | if (spoofLocale) { | |||
4417 | switch (aFile) { | |||
4418 | case nsContentUtils::eFORMS_PROPERTIES: | |||
4419 | return nsContentUtils::eFORMS_PROPERTIES_en_US; | |||
4420 | case nsContentUtils::eDOM_PROPERTIES: | |||
4421 | return nsContentUtils::eDOM_PROPERTIES_en_US; | |||
4422 | default: | |||
4423 | break; | |||
4424 | } | |||
4425 | } | |||
4426 | return aFile; | |||
4427 | } | |||
4428 | ||||
4429 | /* static */ | |||
4430 | nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile, | |||
4431 | const char* aKey, | |||
4432 | Document* aDocument, | |||
4433 | nsAString& aResult) { | |||
4434 | return GetLocalizedString( | |||
4435 | GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult); | |||
4436 | } | |||
4437 | ||||
4438 | /* static */ | |||
4439 | nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile, | |||
4440 | const char* aKey, | |||
4441 | nsAString& aResult) { | |||
4442 | return FormatLocalizedString(aFile, aKey, {}, aResult); | |||
4443 | } | |||
4444 | ||||
4445 | /* static */ | |||
4446 | nsresult nsContentUtils::FormatMaybeLocalizedString( | |||
4447 | PropertiesFile aFile, const char* aKey, Document* aDocument, | |||
4448 | const nsTArray<nsString>& aParams, nsAString& aResult) { | |||
4449 | return FormatLocalizedString( | |||
4450 | GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams, | |||
4451 | aResult); | |||
4452 | } | |||
4453 | ||||
4454 | class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable { | |||
4455 | public: | |||
4456 | FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate, | |||
4457 | nsContentUtils::PropertiesFile aFile, | |||
4458 | const char* aKey, | |||
4459 | const nsTArray<nsString>& aParams, | |||
4460 | nsAString& aLocalizedString) | |||
4461 | : WorkerMainThreadRunnable(aWorkerPrivate, | |||
4462 | "FormatLocalizedStringRunnable"_ns), | |||
4463 | mFile(aFile), | |||
4464 | mKey(aKey), | |||
4465 | mParams(aParams), | |||
4466 | mLocalizedString(aLocalizedString) { | |||
4467 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWorkerPrivate" ")"); do { *((volatile int*)__null) = 4467; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4468 | aWorkerPrivate->AssertIsOnWorkerThread(); | |||
4469 | } | |||
4470 | ||||
4471 | bool MainThreadRun() override { | |||
4472 | AssertIsOnMainThread(); | |||
4473 | ||||
4474 | mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams, | |||
4475 | mLocalizedString); | |||
4476 | Unused << NS_WARN_IF(NS_FAILED(mResult))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mResult )), 0))), "NS_FAILED(mResult)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4476); | |||
4477 | return true; | |||
4478 | } | |||
4479 | ||||
4480 | nsresult GetResult() const { return mResult; } | |||
4481 | ||||
4482 | private: | |||
4483 | const nsContentUtils::PropertiesFile mFile; | |||
4484 | const char* mKey; | |||
4485 | const nsTArray<nsString>& mParams; | |||
4486 | nsresult mResult = NS_ERROR_FAILURE; | |||
4487 | nsAString& mLocalizedString; | |||
4488 | }; | |||
4489 | ||||
4490 | /* static */ | |||
4491 | nsresult nsContentUtils::FormatLocalizedString( | |||
4492 | PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams, | |||
4493 | nsAString& aResult) { | |||
4494 | if (!NS_IsMainThread()) { | |||
4495 | // nsIStringBundle is thread-safe but its creation is not, and in particular | |||
4496 | // we don't create and store nsIStringBundle objects in a thread-safe way. | |||
4497 | // | |||
4498 | // TODO(emilio): Maybe if we already have the right bundle created we could | |||
4499 | // just call into it, but we should make sure that Shutdown() doesn't get | |||
4500 | // called on the main thread when that happens which is a bit tricky to | |||
4501 | // prove? | |||
4502 | WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); | |||
4503 | if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4503)) { | |||
4504 | return NS_ERROR_UNEXPECTED; | |||
4505 | } | |||
4506 | ||||
4507 | auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>( | |||
4508 | workerPrivate, aFile, aKey, aParams, aResult); | |||
4509 | ||||
4510 | runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors()); | |||
4511 | return runnable->GetResult(); | |||
4512 | } | |||
4513 | ||||
4514 | MOZ_TRY(EnsureStringBundle(aFile))do { auto mozTryTempResult_ = ::mozilla::ToResult(EnsureStringBundle (aFile)); if ((__builtin_expect(!!(mozTryTempResult_.isErr()) , 0))) { return mozTryTempResult_.propagateErr(); } } while ( 0); | |||
4515 | nsIStringBundle* bundle = sStringBundles[aFile]; | |||
4516 | if (aParams.IsEmpty()) { | |||
4517 | return bundle->GetStringFromName(aKey, aResult); | |||
4518 | } | |||
4519 | return bundle->FormatStringFromName(aKey, aParams, aResult); | |||
4520 | } | |||
4521 | ||||
4522 | /* static */ | |||
4523 | void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText, | |||
4524 | const nsACString& aCategory, | |||
4525 | bool aFromPrivateWindow, | |||
4526 | bool aFromChromeContext, | |||
4527 | uint32_t aErrorFlags) { | |||
4528 | nsCOMPtr<nsIScriptError> scriptError = | |||
4529 | do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"); | |||
4530 | if (scriptError) { | |||
4531 | nsCOMPtr<nsIConsoleService> console = | |||
4532 | do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1"); | |||
4533 | if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1))) | |||
4534 | aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1))) | |||
4535 | aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init ( aErrorText, u""_ns, u""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow , aFromChromeContext))), 1)))) { | |||
4536 | console->LogMessage(scriptError); | |||
4537 | } | |||
4538 | } | |||
4539 | } | |||
4540 | ||||
4541 | /* static */ | |||
4542 | nsresult nsContentUtils::ReportToConsole( | |||
4543 | uint32_t aErrorFlags, const nsACString& aCategory, | |||
4544 | const Document* aDocument, PropertiesFile aFile, const char* aMessageName, | |||
4545 | const nsTArray<nsString>& aParams, nsIURI* aURI, | |||
4546 | const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber) { | |||
4547 | nsresult rv; | |||
4548 | nsAutoString errorText; | |||
4549 | if (!aParams.IsEmpty()) { | |||
4550 | rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText); | |||
4551 | } else { | |||
4552 | rv = GetLocalizedString(aFile, aMessageName, errorText); | |||
4553 | } | |||
4554 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4554); return rv; } } while (false); | |||
4555 | ||||
4556 | return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory, | |||
4557 | aDocument, aURI, aSourceLine, aLineNumber, | |||
4558 | aColumnNumber); | |||
4559 | } | |||
4560 | ||||
4561 | /* static */ | |||
4562 | void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) { | |||
4563 | ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc, | |||
4564 | nsContentUtils::eDOM_PROPERTIES, "EmptyGetElementByIdParam"); | |||
4565 | } | |||
4566 | ||||
4567 | /* static */ | |||
4568 | nsresult nsContentUtils::ReportToConsoleNonLocalized( | |||
4569 | const nsAString& aErrorText, uint32_t aErrorFlags, | |||
4570 | const nsACString& aCategory, const Document* aDocument, nsIURI* aURI, | |||
4571 | const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber, | |||
4572 | MissingErrorLocationMode aLocationMode) { | |||
4573 | uint64_t innerWindowID = 0; | |||
4574 | if (aDocument) { | |||
4575 | if (!aURI) { | |||
4576 | aURI = aDocument->GetDocumentURI(); | |||
4577 | } | |||
4578 | innerWindowID = aDocument->InnerWindowID(); | |||
4579 | } | |||
4580 | ||||
4581 | return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory, | |||
4582 | innerWindowID, aURI, aSourceLine, | |||
4583 | aLineNumber, aColumnNumber, aLocationMode); | |||
4584 | } | |||
4585 | ||||
4586 | /* static */ | |||
4587 | nsresult nsContentUtils::ReportToConsoleByWindowID( | |||
4588 | const nsAString& aErrorText, uint32_t aErrorFlags, | |||
4589 | const nsACString& aCategory, uint64_t aInnerWindowID, nsIURI* aURI, | |||
4590 | const nsString& aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber, | |||
4591 | MissingErrorLocationMode aLocationMode) { | |||
4592 | nsresult rv; | |||
4593 | if (!sConsoleService) { // only need to bother null-checking here | |||
4594 | rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService); | |||
4595 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4595); return rv; } } while (false); | |||
4596 | } | |||
4597 | ||||
4598 | nsAutoString spec; | |||
4599 | if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) { | |||
4600 | JSContext* cx = GetCurrentJSContext(); | |||
4601 | if (cx) { | |||
4602 | nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber); | |||
4603 | } | |||
4604 | } | |||
4605 | ||||
4606 | nsCOMPtr<nsIScriptError> errorObject = | |||
4607 | do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv); | |||
4608 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4608); return rv; } } while (false); | |||
4609 | ||||
4610 | if (!spec.IsEmpty()) { | |||
4611 | rv = errorObject->InitWithWindowID(aErrorText, | |||
4612 | spec, // file name | |||
4613 | aSourceLine, aLineNumber, aColumnNumber, | |||
4614 | aErrorFlags, aCategory, aInnerWindowID); | |||
4615 | } else { | |||
4616 | rv = errorObject->InitWithSourceURI(aErrorText, aURI, aSourceLine, | |||
4617 | aLineNumber, aColumnNumber, aErrorFlags, | |||
4618 | aCategory, aInnerWindowID); | |||
4619 | } | |||
4620 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4620); return rv; } } while (false); | |||
4621 | ||||
4622 | return sConsoleService->LogMessage(errorObject); | |||
4623 | } | |||
4624 | ||||
4625 | void nsContentUtils::LogMessageToConsole(const char* aMsg) { | |||
4626 | if (!sConsoleService) { // only need to bother null-checking here | |||
4627 | CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService); | |||
4628 | if (!sConsoleService) { | |||
4629 | return; | |||
4630 | } | |||
4631 | } | |||
4632 | sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get()); | |||
4633 | } | |||
4634 | ||||
4635 | bool nsContentUtils::IsChromeDoc(const Document* aDocument) { | |||
4636 | return aDocument && aDocument->NodePrincipal() == sSystemPrincipal; | |||
4637 | } | |||
4638 | ||||
4639 | bool nsContentUtils::IsAddonDoc(const Document* aDocument) { | |||
4640 | return aDocument && | |||
4641 | aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal(); | |||
4642 | } | |||
4643 | ||||
4644 | bool nsContentUtils::IsChildOfSameType(Document* aDoc) { | |||
4645 | if (BrowsingContext* bc = aDoc->GetBrowsingContext()) { | |||
4646 | return bc->GetParent(); | |||
4647 | } | |||
4648 | return false; | |||
4649 | } | |||
4650 | ||||
4651 | static bool IsJSONType(const nsACString& aContentType) { | |||
4652 | return aContentType.EqualsLiteral(TEXT_JSON"text/json") || | |||
4653 | aContentType.EqualsLiteral(APPLICATION_JSON"application/json"); | |||
4654 | } | |||
4655 | ||||
4656 | static bool IsNonPlainTextType(const nsACString& aContentType) { | |||
4657 | // MIME type suffixes which should not be plain text. | |||
4658 | static constexpr std::string_view kNonPlainTextTypes[] = { | |||
4659 | "html", | |||
4660 | "xml", | |||
4661 | "xsl", | |||
4662 | "calendar", | |||
4663 | "x-calendar", | |||
4664 | "x-vcalendar", | |||
4665 | "vcalendar", | |||
4666 | "vcard", | |||
4667 | "x-vcard", | |||
4668 | "directory", | |||
4669 | "ldif", | |||
4670 | "qif", | |||
4671 | "x-qif", | |||
4672 | "x-csv", | |||
4673 | "x-vcf", | |||
4674 | "rtf", | |||
4675 | "comma-separated-values", | |||
4676 | "csv", | |||
4677 | "tab-separated-values", | |||
4678 | "tsv", | |||
4679 | "ofx", | |||
4680 | "vnd.sun.j2me.app-descriptor", | |||
4681 | "x-ms-iqy", | |||
4682 | "x-ms-odc", | |||
4683 | "x-ms-rqy", | |||
4684 | "x-ms-contact"}; | |||
4685 | ||||
4686 | // Trim off the "text/" prefix for comparison. | |||
4687 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)" ")"); do { *((volatile int*)__null) = 4687; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4688 | std::string_view suffix = aContentType; | |||
4689 | suffix.remove_prefix(5); | |||
4690 | ||||
4691 | for (std::string_view type : kNonPlainTextTypes) { | |||
4692 | if (type == suffix) { | |||
4693 | return true; | |||
4694 | } | |||
4695 | } | |||
4696 | return false; | |||
4697 | } | |||
4698 | ||||
4699 | bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) { | |||
4700 | // All `text/*`, any JSON type and any JavaScript type are considered "plain | |||
4701 | // text" types for the purposes of how to render them as a document. | |||
4702 | return (StringBeginsWith(aContentType, "text/"_ns) && | |||
4703 | !IsNonPlainTextType(aContentType)) || | |||
4704 | IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType); | |||
4705 | } | |||
4706 | ||||
4707 | bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) { | |||
4708 | // NOTE: This must be a subset of the list in IsPlainTextType(). | |||
4709 | return IsJSONType(aContentType) || | |||
4710 | aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") || | |||
4711 | aContentType.EqualsLiteral(TEXT_VTT"text/vtt"); | |||
4712 | } | |||
4713 | ||||
4714 | bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) { | |||
4715 | return aDocument && aDocument->IsInChromeDocShell(); | |||
4716 | } | |||
4717 | ||||
4718 | // static | |||
4719 | nsIContentPolicy* nsContentUtils::GetContentPolicy() { | |||
4720 | if (!sTriedToGetContentPolicy) { | |||
4721 | CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService); | |||
4722 | // It's OK to not have a content policy service | |||
4723 | sTriedToGetContentPolicy = true; | |||
4724 | } | |||
4725 | ||||
4726 | return sContentPolicyService; | |||
4727 | } | |||
4728 | ||||
4729 | // static | |||
4730 | bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) { | |||
4731 | const char16_t* name = aName->GetUTF16String(); | |||
4732 | if (name[0] != 'o' || name[1] != 'n') { | |||
4733 | return false; | |||
4734 | } | |||
4735 | ||||
4736 | EventNameMapping mapping; | |||
4737 | return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType); | |||
4738 | } | |||
4739 | ||||
4740 | // static | |||
4741 | EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) { | |||
4742 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "sAtomEventTable is not threadsafe" ")"); do { *((volatile int*)__null) = 4742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4743 | if (aName) { | |||
4744 | EventNameMapping mapping; | |||
4745 | if (sAtomEventTable->Get(aName, &mapping)) { | |||
4746 | return mapping.mMessage; | |||
4747 | } | |||
4748 | } | |||
4749 | ||||
4750 | return eUnidentifiedEvent; | |||
4751 | } | |||
4752 | ||||
4753 | // static | |||
4754 | mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) { | |||
4755 | EventNameMapping mapping; | |||
4756 | if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID; | |||
4757 | ||||
4758 | return eBasicEventClass; | |||
4759 | } | |||
4760 | ||||
4761 | nsAtom* nsContentUtils::GetEventMessageAndAtom( | |||
4762 | const nsAString& aName, mozilla::EventClassID aEventClassID, | |||
4763 | EventMessage* aEventMessage) { | |||
4764 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Our hashtables are not threadsafe" ")"); do { *((volatile int*)__null) = 4764; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4765 | EventNameMapping mapping; | |||
4766 | if (sStringEventTable->Get(aName, &mapping)) { | |||
4767 | *aEventMessage = mapping.mEventClassID == aEventClassID | |||
4768 | ? mapping.mMessage | |||
4769 | : eUnidentifiedEvent; | |||
4770 | return mapping.mAtom; | |||
4771 | } | |||
4772 | ||||
4773 | // If we have cached lots of user defined event names, clear some of them. | |||
4774 | if (sUserDefinedEvents->Length() > 127) { | |||
4775 | while (sUserDefinedEvents->Length() > 64) { | |||
4776 | nsAtom* first = sUserDefinedEvents->ElementAt(0); | |||
4777 | sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2)); | |||
4778 | sUserDefinedEvents->RemoveElementAt(0); | |||
4779 | } | |||
4780 | } | |||
4781 | ||||
4782 | *aEventMessage = eUnidentifiedEvent; | |||
4783 | RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName); | |||
4784 | sUserDefinedEvents->AppendElement(atom); | |||
4785 | mapping.mAtom = atom; | |||
4786 | mapping.mMessage = eUnidentifiedEvent; | |||
4787 | mapping.mType = EventNameType_None; | |||
4788 | mapping.mEventClassID = eBasicEventClass; | |||
4789 | sStringEventTable->InsertOrUpdate(aName, mapping); | |||
4790 | return mapping.mAtom; | |||
4791 | } | |||
4792 | ||||
4793 | // static | |||
4794 | EventMessage nsContentUtils::GetEventMessageAndAtomForListener( | |||
4795 | const nsAString& aName, nsAtom** aOnName) { | |||
4796 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Our hashtables are not threadsafe" ")"); do { *((volatile int*)__null) = 4796; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4797 | ||||
4798 | // Check sStringEventTable for a matching entry. This will only fail for | |||
4799 | // user-defined event types. | |||
4800 | EventNameMapping mapping; | |||
4801 | if (sStringEventTable->Get(aName, &mapping)) { | |||
4802 | RefPtr<nsAtom> atom = mapping.mAtom; | |||
4803 | atom.forget(aOnName); | |||
4804 | return mapping.mMessage; | |||
4805 | } | |||
4806 | ||||
4807 | // sStringEventTable did not contain an entry for this event type string. | |||
4808 | // Call GetEventMessageAndAtom, which will create an event type atom and | |||
4809 | // cache it in sStringEventTable for future calls. | |||
4810 | EventMessage msg = eUnidentifiedEvent; | |||
4811 | RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg); | |||
4812 | atom.forget(aOnName); | |||
4813 | return msg; | |||
4814 | } | |||
4815 | ||||
4816 | static already_AddRefed<Event> GetEventWithTarget( | |||
4817 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
4818 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
4819 | Trusted aTrusted, ErrorResult& aErrorResult) { | |||
4820 | RefPtr<Event> event = | |||
4821 | aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult); | |||
4822 | if (aErrorResult.Failed()) { | |||
4823 | return nullptr; | |||
4824 | } | |||
4825 | ||||
4826 | event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed); | |||
4827 | event->SetTrusted(aTrusted == Trusted::eYes); | |||
4828 | ||||
4829 | event->SetTarget(aTarget); | |||
4830 | ||||
4831 | return event.forget(); | |||
4832 | } | |||
4833 | ||||
4834 | // static | |||
4835 | nsresult nsContentUtils::DispatchTrustedEvent( | |||
4836 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
4837 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
4838 | bool* aDefaultAction) { | |||
4839 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) | |||
4840 | !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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) | |||
4841 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")" ") (" "Use DispatchInputEvent() instead" ")"); do { *((volatile int*)__null) = 4841; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4842 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
4843 | aComposed, Trusted::eYes, aDefaultAction); | |||
4844 | } | |||
4845 | ||||
4846 | // static | |||
4847 | nsresult nsContentUtils::DispatchUntrustedEvent( | |||
4848 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
4849 | CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) { | |||
4850 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
4851 | Composed::eDefault, Trusted::eNo, aDefaultAction); | |||
4852 | } | |||
4853 | ||||
4854 | // static | |||
4855 | nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget, | |||
4856 | const nsAString& aEventName, | |||
4857 | CanBubble aCanBubble, | |||
4858 | Cancelable aCancelable, | |||
4859 | Composed aComposed, Trusted aTrusted, | |||
4860 | bool* aDefaultAction, | |||
4861 | ChromeOnlyDispatch aOnlyChromeDispatch) { | |||
4862 | if (!aDoc || !aTarget) { | |||
4863 | return NS_ERROR_INVALID_ARG; | |||
4864 | } | |||
4865 | ||||
4866 | ErrorResult err; | |||
4867 | RefPtr<Event> event = | |||
4868 | GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
4869 | aComposed, aTrusted, err); | |||
4870 | if (err.Failed()) { | |||
4871 | return err.StealNSResult(); | |||
4872 | } | |||
4873 | event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = | |||
4874 | aOnlyChromeDispatch == ChromeOnlyDispatch::eYes; | |||
4875 | ||||
4876 | bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err); | |||
4877 | if (aDefaultAction) { | |||
4878 | *aDefaultAction = doDefault; | |||
4879 | } | |||
4880 | return err.StealNSResult(); | |||
4881 | } | |||
4882 | ||||
4883 | // static | |||
4884 | nsresult nsContentUtils::DispatchEvent(Document* aDoc, EventTarget* aTarget, | |||
4885 | WidgetEvent& aEvent, | |||
4886 | EventMessage aEventMessage, | |||
4887 | CanBubble aCanBubble, | |||
4888 | Cancelable aCancelable, Trusted aTrusted, | |||
4889 | bool* aDefaultAction, | |||
4890 | ChromeOnlyDispatch aOnlyChromeDispatch) { | |||
4891 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
4892 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { *((volatile int*)__null) = 4892; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
4893 | ||||
4894 | aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage); | |||
4895 | aEvent.SetDefaultComposed(); | |||
4896 | aEvent.SetDefaultComposedInNativeAnonymousContent(); | |||
4897 | ||||
4898 | aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes; | |||
4899 | aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes; | |||
4900 | aEvent.mFlags.mOnlyChromeDispatch = | |||
4901 | aOnlyChromeDispatch == ChromeOnlyDispatch::eYes; | |||
4902 | ||||
4903 | aEvent.mTarget = aTarget; | |||
4904 | ||||
4905 | nsEventStatus status = nsEventStatus_eIgnore; | |||
4906 | nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr, | |||
4907 | nullptr, &status); | |||
4908 | if (aDefaultAction) { | |||
4909 | *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault); | |||
4910 | } | |||
4911 | return rv; | |||
4912 | } | |||
4913 | ||||
4914 | // static | |||
4915 | nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) { | |||
4916 | return DispatchInputEvent(aEventTarget, mozilla::eEditorInput, | |||
4917 | mozilla::EditorInputType::eUnknown, nullptr, | |||
4918 | InputEventOptions()); | |||
4919 | } | |||
4920 | ||||
4921 | // static | |||
4922 | nsresult nsContentUtils::DispatchInputEvent( | |||
4923 | Element* aEventTargetElement, EventMessage aEventMessage, | |||
4924 | EditorInputType aEditorInputType, EditorBase* aEditorBase, | |||
4925 | InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) { | |||
4926 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" ")"); do { *((volatile int*)__null) = 4927; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
4927 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput" ")"); do { *((volatile int*)__null) = 4927; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4928 | ||||
4929 | if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4929)) { | |||
4930 | return NS_ERROR_INVALID_ARG; | |||
4931 | } | |||
4932 | ||||
4933 | // If this is called from editor, the instance should be set to aEditorBase. | |||
4934 | // Otherwise, we need to look for an editor for aEventTargetElement. | |||
4935 | // However, we don't need to do it for HTMLEditor since nobody shouldn't | |||
4936 | // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor | |||
4937 | // itself. | |||
4938 | bool useInputEvent = false; | |||
4939 | if (aEditorBase) { | |||
4940 | useInputEvent = true; | |||
4941 | } else if (HTMLTextAreaElement* textAreaElement = | |||
4942 | HTMLTextAreaElement::FromNode(aEventTargetElement)) { | |||
4943 | aEditorBase = textAreaElement->GetTextEditorWithoutCreation(); | |||
4944 | useInputEvent = true; | |||
4945 | } else if (HTMLInputElement* inputElement = | |||
4946 | HTMLInputElement::FromNode(aEventTargetElement)) { | |||
4947 | if (inputElement->IsInputEventTarget()) { | |||
4948 | aEditorBase = inputElement->GetTextEditorWithoutCreation(); | |||
4949 | useInputEvent = true; | |||
4950 | } | |||
4951 | } | |||
4952 | #ifdef DEBUG1 | |||
4953 | else { | |||
4954 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()" ") (" "The event target may have editor, but we've not known it yet." ")"); do { *((volatile int*)__null) = 4955; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
4955 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()" ") (" "The event target may have editor, but we've not known it yet." ")"); do { *((volatile int*)__null) = 4955; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4956 | } | |||
4957 | #endif // #ifdef DEBUG | |||
4958 | ||||
4959 | if (!useInputEvent) { | |||
4960 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4960); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput" ")"); do { *((volatile int*)__null) = 4960; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4961 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4961); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown" ")"); do { *((volatile int*)__null) = 4961; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4962 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4962); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { *((volatile int*)__null) = 4962; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4963 | // Dispatch "input" event with Event instance. | |||
4964 | WidgetEvent widgetEvent(true, eUnidentifiedEvent); | |||
4965 | widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput; | |||
4966 | widgetEvent.mFlags.mCancelable = false; | |||
4967 | widgetEvent.mFlags.mComposed = true; | |||
4968 | return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement, | |||
4969 | widgetEvent, aEventStatus); | |||
4970 | } | |||
4971 | ||||
4972 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { *((volatile int*)__null) = 4973; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
4973 | !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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { *((volatile int*)__null) = 4973; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
4974 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
4975 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
4976 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText" ")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
4977 | ||||
4978 | nsCOMPtr<nsIWidget> widget; | |||
4979 | if (aEditorBase) { | |||
4980 | widget = aEditorBase->GetWidget(); | |||
4981 | if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4981)) { | |||
4982 | return NS_ERROR_FAILURE; | |||
4983 | } | |||
4984 | } else { | |||
4985 | Document* document = aEventTargetElement->OwnerDoc(); | |||
4986 | if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4986)) { | |||
4987 | return NS_ERROR_FAILURE; | |||
4988 | } | |||
4989 | // If we're running xpcshell tests, we fail to get presShell here. | |||
4990 | // Even in such case, we need to dispatch "input" event without widget. | |||
4991 | PresShell* presShell = document->GetPresShell(); | |||
4992 | if (presShell) { | |||
4993 | nsPresContext* presContext = presShell->GetPresContext(); | |||
4994 | if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4994)) { | |||
4995 | return NS_ERROR_FAILURE; | |||
4996 | } | |||
4997 | widget = presContext->GetRootWidget(); | |||
4998 | if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 4998)) { | |||
4999 | return NS_ERROR_FAILURE; | |||
5000 | } | |||
5001 | } | |||
5002 | } | |||
5003 | ||||
5004 | // Dispatch "input" event with InputEvent instance. | |||
5005 | InternalEditorInputEvent inputEvent(true, aEventMessage, widget); | |||
5006 | ||||
5007 | inputEvent.mFlags.mCancelable = | |||
5008 | !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput && | |||
5009 | IsCancelableBeforeInputEvent(aEditorInputType); | |||
5010 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus" ")"); do { *((volatile int*)__null) = 5010; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5011 | ||||
5012 | // If there is an editor, set isComposing to true when it has composition. | |||
5013 | // Note that EditorBase::IsIMEComposing() may return false even when we | |||
5014 | // need to set it to true. | |||
5015 | // Otherwise, i.e., editor hasn't been created for the element yet, | |||
5016 | // we should set isComposing to false since the element can never has | |||
5017 | // composition without editor. | |||
5018 | inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition(); | |||
5019 | ||||
5020 | if (!aEditorBase || aEditorBase->IsTextEditor()) { | |||
5021 | if (IsDataAvailableOnTextEditor(aEditorInputType)) { | |||
5022 | inputEvent.mData = std::move(aOptions.mData); | |||
5023 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile int*)__null) = 5024; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) | |||
5024 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile int*)__null) = 5024; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5025 | } | |||
5026 | #ifdef DEBUG1 | |||
5027 | else { | |||
5028 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()" ") (" "inputEvent.mData should be void" ")"); do { *((volatile int*)__null) = 5028; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5029 | } | |||
5030 | #endif // #ifdef DEBUG | |||
5031 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
5032 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
5033 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges for <input> and <textarea> should always be empty" ")"); do { *((volatile int*)__null) = 5033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5034 | } else { | |||
5035 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()" ")"); do { *((volatile int*)__null) = 5035; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5036 | if (IsDataAvailableOnHTMLEditor(aEditorInputType)) { | |||
5037 | inputEvent.mData = std::move(aOptions.mData); | |||
5038 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile int*)__null) = 5039; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) | |||
5039 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()" ") (" "inputEvent.mData shouldn't be void" ")"); do { *((volatile int*)__null) = 5039; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5040 | } else { | |||
5041 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()" ") (" "inputEvent.mData should be void" ")"); do { *((volatile int*)__null) = 5041; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5042 | if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) { | |||
5043 | inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer); | |||
5044 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do { *((volatile int*)__null) = 5045; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
5045 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do { *((volatile int*)__null) = 5045; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
5046 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()" ") (" "inputEvent.mDataTransfer should be read only" ")"); do { *((volatile int*)__null) = 5047; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
5047 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()" ") (" "inputEvent.mDataTransfer should be read only" ")"); do { *((volatile int*)__null) = 5047; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
5048 | } | |||
5049 | #ifdef DEBUG1 | |||
5050 | else { | |||
5051 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer should be nullptr" ")"); do { *((volatile int*)__null) = 5052; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
5052 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer" ") (" "inputEvent.mDataTransfer should be nullptr" ")"); do { *((volatile int*)__null) = 5052; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
5053 | } | |||
5054 | #endif // #ifdef DEBUG | |||
5055 | } | |||
5056 | if (aEventMessage == eEditorBeforeInput && | |||
5057 | MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) { | |||
5058 | inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges); | |||
5059 | } | |||
5060 | #ifdef DEBUG1 | |||
5061 | else { | |||
5062 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges shouldn't be set for the dispatching event" ")"); do { *((volatile int*)__null) = 5063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
5063 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()" ") (" "Target ranges shouldn't be set for the dispatching event" ")"); do { *((volatile int*)__null) = 5063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5064 | } | |||
5065 | #endif // #ifdef DEBUG | |||
5066 | } | |||
5067 | ||||
5068 | inputEvent.mInputType = aEditorInputType; | |||
5069 | ||||
5070 | // If we cannot dispatch an event right now, we cannot make it cancelable. | |||
5071 | if (!nsContentUtils::IsSafeToRunScript()) { | |||
5072 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5074); MOZ_PretendNoReturn(); } } while (0) | |||
5073 | !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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5074); MOZ_PretendNoReturn(); } } while (0) | |||
5074 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5074); MOZ_PretendNoReturn(); } } while (0); | |||
5075 | inputEvent.mFlags.mCancelable = false; | |||
5076 | } | |||
5077 | return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement, | |||
5078 | inputEvent, aEventStatus); | |||
5079 | } | |||
5080 | ||||
5081 | nsresult nsContentUtils::DispatchChromeEvent( | |||
5082 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
5083 | CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) { | |||
5084 | if (!aDoc || !aTarget) { | |||
5085 | return NS_ERROR_INVALID_ARG; | |||
5086 | } | |||
5087 | ||||
5088 | if (!aDoc->GetWindow()) { | |||
5089 | return NS_ERROR_INVALID_ARG; | |||
5090 | } | |||
5091 | ||||
5092 | EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget(); | |||
5093 | if (!piTarget) { | |||
5094 | return NS_ERROR_INVALID_ARG; | |||
5095 | } | |||
5096 | ||||
5097 | ErrorResult err; | |||
5098 | RefPtr<Event> event = | |||
5099 | GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
5100 | Composed::eDefault, Trusted::eYes, err); | |||
5101 | if (err.Failed()) { | |||
5102 | return err.StealNSResult(); | |||
5103 | } | |||
5104 | ||||
5105 | bool defaultActionEnabled = | |||
5106 | piTarget->DispatchEvent(*event, CallerType::System, err); | |||
5107 | if (aDefaultAction) { | |||
5108 | *aDefaultAction = defaultActionEnabled; | |||
5109 | } | |||
5110 | return err.StealNSResult(); | |||
5111 | } | |||
5112 | ||||
5113 | void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise, | |||
5114 | CallerType aCallerType) { | |||
5115 | RefPtr<Element> target = &aFrameElement; | |||
5116 | bool defaultAction = true; | |||
5117 | if (aCanRaise) { | |||
5118 | DispatchEventOnlyToChrome(target->OwnerDoc(), target, | |||
5119 | u"framefocusrequested"_ns, CanBubble::eYes, | |||
5120 | Cancelable::eYes, &defaultAction); | |||
5121 | } | |||
5122 | if (!defaultAction) { | |||
5123 | return; | |||
5124 | } | |||
5125 | ||||
5126 | RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager(); | |||
5127 | if (!fm) { | |||
5128 | return; | |||
5129 | } | |||
5130 | ||||
5131 | uint32_t flags = nsIFocusManager::FLAG_NOSCROLL; | |||
5132 | if (aCanRaise) { | |||
5133 | flags |= nsIFocusManager::FLAG_RAISE; | |||
5134 | } | |||
5135 | ||||
5136 | if (aCallerType == CallerType::NonSystem) { | |||
5137 | flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER; | |||
5138 | } | |||
5139 | ||||
5140 | fm->SetFocus(target, flags); | |||
5141 | } | |||
5142 | ||||
5143 | nsresult nsContentUtils::DispatchEventOnlyToChrome( | |||
5144 | Document* aDoc, EventTarget* aTarget, const nsAString& aEventName, | |||
5145 | CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed, | |||
5146 | bool* aDefaultAction) { | |||
5147 | return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable, | |||
5148 | aComposed, Trusted::eYes, aDefaultAction, | |||
5149 | ChromeOnlyDispatch::eYes); | |||
5150 | } | |||
5151 | ||||
5152 | /* static */ | |||
5153 | Element* nsContentUtils::MatchElementId(nsIContent* aContent, | |||
5154 | const nsAtom* aId) { | |||
5155 | for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) { | |||
5156 | if (aId == cur->GetID()) { | |||
5157 | return cur->AsElement(); | |||
5158 | } | |||
5159 | } | |||
5160 | ||||
5161 | return nullptr; | |||
5162 | } | |||
5163 | ||||
5164 | /* static */ | |||
5165 | Element* nsContentUtils::MatchElementId(nsIContent* aContent, | |||
5166 | const nsAString& aId) { | |||
5167 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()" ") (" "Will match random elements" ")"); do { *((volatile int *)__null) = 5167; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5168 | ||||
5169 | // ID attrs are generally stored as atoms, so just atomize this up front | |||
5170 | RefPtr<nsAtom> id(NS_Atomize(aId)); | |||
5171 | if (!id) { | |||
5172 | // OOM, so just bail | |||
5173 | return nullptr; | |||
5174 | } | |||
5175 | ||||
5176 | return MatchElementId(aContent, id); | |||
5177 | } | |||
5178 | ||||
5179 | /* static */ | |||
5180 | void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) { | |||
5181 | nsCOMPtr<nsIObserverService> observerService = | |||
5182 | mozilla::services::GetObserverService(); | |||
5183 | if (observerService) { | |||
5184 | observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", | |||
5185 | false); | |||
5186 | } | |||
5187 | } | |||
5188 | ||||
5189 | /* static */ | |||
5190 | void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) { | |||
5191 | nsCOMPtr<nsIObserverService> observerService = | |||
5192 | mozilla::services::GetObserverService(); | |||
5193 | if (observerService) { | |||
5194 | observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown"); | |||
5195 | } | |||
5196 | } | |||
5197 | ||||
5198 | /* static */ | |||
5199 | bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, | |||
5200 | int32_t aNameSpaceID, nsAtom* aName) { | |||
5201 | static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr}; | |||
5202 | return aContent->IsElement() && | |||
5203 | aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings, | |||
5204 | eCaseMatters) == | |||
5205 | AttrArray::ATTR_VALUE_NO_MATCH; | |||
5206 | } | |||
5207 | ||||
5208 | /* static */ | |||
5209 | bool nsContentUtils::WantMutationEvents(nsINode* aNode, uint32_t aType, | |||
5210 | nsINode* aTargetForSubtreeModified) { | |||
5211 | Document* doc = aNode->OwnerDoc(); | |||
5212 | if (!doc->FireMutationEvents()) { | |||
5213 | return false; | |||
5214 | } | |||
5215 | ||||
5216 | // global object will be null for documents that don't have windows. | |||
5217 | nsPIDOMWindowInner* window = doc->GetInnerWindow(); | |||
5218 | // This relies on EventListenerManager::AddEventListener, which sets | |||
5219 | // all mutation bits when there is a listener for DOMSubtreeModified event. | |||
5220 | if (window && !window->HasMutationListeners(aType)) { | |||
5221 | return false; | |||
5222 | } | |||
5223 | ||||
5224 | if (aNode->ChromeOnlyAccess() || aNode->IsInShadowTree()) { | |||
5225 | return false; | |||
5226 | } | |||
5227 | ||||
5228 | doc->MayDispatchMutationEvent(aTargetForSubtreeModified); | |||
5229 | ||||
5230 | // If we have a window, we can check it for mutation listeners now. | |||
5231 | if (aNode->IsInUncomposedDoc()) { | |||
5232 | nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window)); | |||
5233 | if (piTarget) { | |||
5234 | EventListenerManager* manager = piTarget->GetExistingListenerManager(); | |||
5235 | if (manager && manager->HasMutationListeners()) { | |||
5236 | return true; | |||
5237 | } | |||
5238 | } | |||
5239 | } | |||
5240 | ||||
5241 | // If we have a window, we know a mutation listener is registered, but it | |||
5242 | // might not be in our chain. If we don't have a window, we might have a | |||
5243 | // mutation listener. Check quickly to see. | |||
5244 | while (aNode) { | |||
5245 | EventListenerManager* manager = aNode->GetExistingListenerManager(); | |||
5246 | if (manager && manager->HasMutationListeners()) { | |||
5247 | return true; | |||
5248 | } | |||
5249 | ||||
5250 | aNode = aNode->GetParentNode(); | |||
5251 | } | |||
5252 | ||||
5253 | return false; | |||
5254 | } | |||
5255 | ||||
5256 | /* static */ | |||
5257 | bool nsContentUtils::HasMutationListeners(Document* aDocument, uint32_t aType) { | |||
5258 | nsPIDOMWindowInner* window = | |||
5259 | aDocument ? aDocument->GetInnerWindow() : nullptr; | |||
5260 | ||||
5261 | // This relies on EventListenerManager::AddEventListener, which sets | |||
5262 | // all mutation bits when there is a listener for DOMSubtreeModified event. | |||
5263 | return !window || window->HasMutationListeners(aType); | |||
5264 | } | |||
5265 | ||||
5266 | void nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent) { | |||
5267 | MOZ_ASSERT(aChild, "Missing child")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChild)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aChild))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild" " (" "Missing child" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") (" "Missing child" ")"); do { *((volatile int*)__null) = 5267; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
5268 | MOZ_ASSERT(aChild->GetParentNode() == aParent, "Wrong parent")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChild->GetParentNode() == aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(aChild->GetParentNode() == aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->GetParentNode() == aParent" " (" "Wrong parent" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode() == aParent" ") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5268 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5269 | MOZ_ASSERT(aChild->OwnerDoc() == aParent->OwnerDoc(), "Wrong owner-doc")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChild->OwnerDoc() == aParent->OwnerDoc())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChild->OwnerDoc() == aParent->OwnerDoc()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->OwnerDoc() == aParent->OwnerDoc()" " (" "Wrong owner-doc" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->OwnerDoc() == aParent->OwnerDoc()" ") (" "Wrong owner-doc" ")"); do { *((volatile int*)__null) = 5269; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5270 | ||||
5271 | // Having an explicit check here since it's an easy mistake to fall into, | |||
5272 | // and there might be existing code with problems. We'd rather be safe | |||
5273 | // than fire DOMNodeRemoved in all corner cases. We also rely on it for | |||
5274 | // nsAutoScriptBlockerSuppressNodeRemoved. | |||
5275 | if (!IsSafeToRunScript()) { | |||
5276 | // This checks that IsSafeToRunScript is true since we don't want to fire | |||
5277 | // events when that is false. We can't rely on EventDispatcher to assert | |||
5278 | // this in this situation since most of the time there are no mutation | |||
5279 | // event listeners, in which case we won't even attempt to dispatch events. | |||
5280 | // However this also allows for two exceptions. First off, we don't assert | |||
5281 | // if the mutation happens to native anonymous content since we never fire | |||
5282 | // mutation events on such content anyway. | |||
5283 | // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since | |||
5284 | // that is a know case when we'd normally fire a mutation event, but can't | |||
5285 | // make that safe and so we suppress it at this time. Ideally this should | |||
5286 | // go away eventually. | |||
5287 | if (!aChild->IsInNativeAnonymousSubtree() && | |||
5288 | !sDOMNodeRemovedSuppressCount) { | |||
5289 | NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire DOMNodeRemoved event, but it's not safe" , "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5289); MOZ_PretendNoReturn(); } while (0); | |||
5290 | WarnScriptWasIgnored(aChild->OwnerDoc()); | |||
5291 | } | |||
5292 | return; | |||
5293 | } | |||
5294 | ||||
5295 | { | |||
5296 | Document* doc = aParent->OwnerDoc(); | |||
5297 | if (MOZ_UNLIKELY(doc->DevToolsWatchingDOMMutations())(__builtin_expect(!!(doc->DevToolsWatchingDOMMutations()), 0)) && | |||
5298 | aChild->IsInComposedDoc() && !aChild->ChromeOnlyAccess()) { | |||
5299 | DispatchChromeEvent(doc, aChild, u"devtoolschildremoved"_ns, | |||
5300 | CanBubble::eNo, Cancelable::eNo); | |||
5301 | } | |||
5302 | } | |||
5303 | ||||
5304 | if (WantMutationEvents(aChild, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04, aParent)) { | |||
5305 | InternalMutationEvent mutation(true, eLegacyNodeRemoved); | |||
5306 | mutation.mRelatedNode = aParent; | |||
5307 | ||||
5308 | mozAutoSubtreeModified subtree(aParent->OwnerDoc(), aParent); | |||
5309 | EventDispatcher::Dispatch(aChild, nullptr, &mutation); | |||
5310 | } | |||
5311 | } | |||
5312 | ||||
5313 | void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() { | |||
5314 | if (!sEventListenerManagersHash) { | |||
5315 | return; | |||
5316 | } | |||
5317 | ||||
5318 | for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) { | |||
5319 | auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get()); | |||
5320 | nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget()); | |||
5321 | if (n && n->IsInComposedDoc() && | |||
5322 | nsCCUncollectableMarker::InGeneration( | |||
5323 | n->OwnerDoc()->GetMarkedCCGeneration())) { | |||
5324 | entry->mListenerManager->MarkForCC(); | |||
5325 | } | |||
5326 | } | |||
5327 | } | |||
5328 | ||||
5329 | /* static */ | |||
5330 | void nsContentUtils::TraverseListenerManager( | |||
5331 | nsINode* aNode, nsCycleCollectionTraversalCallback& cb) { | |||
5332 | if (!sEventListenerManagersHash) { | |||
5333 | // We're already shut down, just return. | |||
5334 | return; | |||
5335 | } | |||
5336 | ||||
5337 | auto entry = static_cast<EventListenerManagerMapEntry*>( | |||
5338 | sEventListenerManagersHash->Search(aNode)); | |||
5339 | if (entry) { | |||
5340 | CycleCollectionNoteChild(cb, entry->mListenerManager.get(), | |||
5341 | "[via hash] mListenerManager"); | |||
5342 | } | |||
5343 | } | |||
5344 | ||||
5345 | EventListenerManager* nsContentUtils::GetListenerManagerForNode( | |||
5346 | nsINode* aNode) { | |||
5347 | if (!sEventListenerManagersHash) { | |||
5348 | // We're already shut down, don't bother creating an event listener | |||
5349 | // manager. | |||
5350 | ||||
5351 | return nullptr; | |||
5352 | } | |||
5353 | ||||
5354 | auto entry = static_cast<EventListenerManagerMapEntry*>( | |||
5355 | sEventListenerManagersHash->Add(aNode, fallible)); | |||
5356 | ||||
5357 | if (!entry) { | |||
5358 | return nullptr; | |||
5359 | } | |||
5360 | ||||
5361 | if (!entry->mListenerManager) { | |||
5362 | entry->mListenerManager = new EventListenerManager(aNode); | |||
5363 | ||||
5364 | aNode->SetFlags(NODE_HAS_LISTENERMANAGER); | |||
5365 | } | |||
5366 | ||||
5367 | return entry->mListenerManager; | |||
5368 | } | |||
5369 | ||||
5370 | EventListenerManager* nsContentUtils::GetExistingListenerManagerForNode( | |||
5371 | const nsINode* aNode) { | |||
5372 | if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) { | |||
5373 | return nullptr; | |||
5374 | } | |||
5375 | ||||
5376 | if (!sEventListenerManagersHash) { | |||
5377 | // We're already shut down, don't bother creating an event listener | |||
5378 | // manager. | |||
5379 | ||||
5380 | return nullptr; | |||
5381 | } | |||
5382 | ||||
5383 | auto entry = static_cast<EventListenerManagerMapEntry*>( | |||
5384 | sEventListenerManagersHash->Search(aNode)); | |||
5385 | if (entry) { | |||
5386 | return entry->mListenerManager; | |||
5387 | } | |||
5388 | ||||
5389 | return nullptr; | |||
5390 | } | |||
5391 | ||||
5392 | void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode, | |||
5393 | DOMArena* aDOMArena) { | |||
5394 | MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType< decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()" ")"); do { *((volatile int*)__null) = 5394; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5395 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)" ")"); do { *((volatile int*)__null) = 5395; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
5396 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)" ")"); do { *((volatile int*)__null) = 5396; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5397 | if (!sDOMArenaHashtable) { | |||
5398 | sDOMArenaHashtable = | |||
5399 | new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>(); | |||
5400 | } | |||
5401 | aNode->SetFlags(NODE_KEEPS_DOMARENA); | |||
5402 | sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena)); | |||
5403 | } | |||
5404 | ||||
5405 | already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable( | |||
5406 | const nsINode* aNode) { | |||
5407 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)" ")"); do { *((volatile int*)__null) = 5407; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5408 | MOZ_ASSERT(StaticPrefs::dom_arena_allocator_enabled_AtStartup())do { static_assert( mozilla::detail::AssertionConditionType< decltype(StaticPrefs::dom_arena_allocator_enabled_AtStartup() )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(StaticPrefs::dom_arena_allocator_enabled_AtStartup() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "StaticPrefs::dom_arena_allocator_enabled_AtStartup()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::dom_arena_allocator_enabled_AtStartup()" ")"); do { *((volatile int*)__null) = 5408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5409 | RefPtr<DOMArena> arena; | |||
5410 | sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena)); | |||
5411 | return arena.forget(); | |||
5412 | } | |||
5413 | ||||
5414 | /* static */ | |||
5415 | void nsContentUtils::RemoveListenerManager(nsINode* aNode) { | |||
5416 | if (sEventListenerManagersHash) { | |||
5417 | auto entry = static_cast<EventListenerManagerMapEntry*>( | |||
5418 | sEventListenerManagersHash->Search(aNode)); | |||
5419 | if (entry) { | |||
5420 | RefPtr<EventListenerManager> listenerManager; | |||
5421 | listenerManager.swap(entry->mListenerManager); | |||
5422 | // Remove the entry and *then* do operations that could cause further | |||
5423 | // modification of sEventListenerManagersHash. See bug 334177. | |||
5424 | sEventListenerManagersHash->RawRemove(entry); | |||
5425 | if (listenerManager) { | |||
5426 | listenerManager->Disconnect(); | |||
5427 | } | |||
5428 | } | |||
5429 | } | |||
5430 | } | |||
5431 | ||||
5432 | /* static */ | |||
5433 | bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix, | |||
5434 | int32_t aNamespaceID) { | |||
5435 | if (aNamespaceID == kNameSpaceID_Unknown-1) { | |||
5436 | return false; | |||
5437 | } | |||
5438 | ||||
5439 | if (!aPrefix) { | |||
5440 | // If the prefix is null, then either the QName must be xmlns or the | |||
5441 | // namespace must not be XMLNS. | |||
5442 | return (aLocalName == nsGkAtoms::xmlns) == | |||
5443 | (aNamespaceID == kNameSpaceID_XMLNS1); | |||
5444 | } | |||
5445 | ||||
5446 | // If the prefix is non-null then the namespace must not be null. | |||
5447 | if (aNamespaceID == kNameSpaceID_None) { | |||
5448 | return false; | |||
5449 | } | |||
5450 | ||||
5451 | // If the namespace is the XMLNS namespace then the prefix must be xmlns, | |||
5452 | // but the localname must not be xmlns. | |||
5453 | if (aNamespaceID == kNameSpaceID_XMLNS1) { | |||
5454 | return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns; | |||
5455 | } | |||
5456 | ||||
5457 | // If the namespace is not the XMLNS namespace then the prefix must not be | |||
5458 | // xmlns. | |||
5459 | // If the namespace is the XML namespace then the prefix can be anything. | |||
5460 | // If the namespace is not the XML namespace then the prefix must not be xml. | |||
5461 | return aPrefix != nsGkAtoms::xmlns && | |||
5462 | (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml); | |||
5463 | } | |||
5464 | ||||
5465 | already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment( | |||
5466 | nsINode* aContextNode, const nsAString& aFragment, | |||
5467 | bool aPreventScriptExecution, ErrorResult& aRv) { | |||
5468 | if (!aContextNode) { | |||
5469 | aRv.Throw(NS_ERROR_INVALID_ARG); | |||
5470 | return nullptr; | |||
5471 | } | |||
5472 | ||||
5473 | // If we don't have a document here, we can't get the right security context | |||
5474 | // for compiling event handlers... so just bail out. | |||
5475 | RefPtr<Document> document = aContextNode->OwnerDoc(); | |||
5476 | bool isHTML = document->IsHTMLDocument(); | |||
5477 | ||||
5478 | if (isHTML) { | |||
5479 | RefPtr<DocumentFragment> frag = new (document->NodeInfoManager()) | |||
5480 | DocumentFragment(document->NodeInfoManager()); | |||
5481 | ||||
5482 | Element* element = aContextNode->GetAsElementOrParentElement(); | |||
5483 | if (element && !element->IsHTMLElement(nsGkAtoms::html)) { | |||
5484 | aRv = ParseFragmentHTML( | |||
5485 | aFragment, frag, element->NodeInfo()->NameAtom(), | |||
5486 | element->GetNameSpaceID(), | |||
5487 | (document->GetCompatibilityMode() == eCompatibility_NavQuirks), | |||
5488 | aPreventScriptExecution); | |||
5489 | } else { | |||
5490 | aRv = ParseFragmentHTML( | |||
5491 | aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3, | |||
5492 | (document->GetCompatibilityMode() == eCompatibility_NavQuirks), | |||
5493 | aPreventScriptExecution); | |||
5494 | } | |||
5495 | ||||
5496 | return frag.forget(); | |||
5497 | } | |||
5498 | ||||
5499 | AutoTArray<nsString, 32> tagStack; | |||
5500 | nsAutoString uriStr, nameStr; | |||
5501 | for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) { | |||
5502 | nsString& tagName = *tagStack.AppendElement(); | |||
5503 | // It mostly doesn't actually matter what tag name we use here: XML doesn't | |||
5504 | // have parsing that depends on the open tag stack, apart from namespace | |||
5505 | // declarations. So this whole tagStack bit is just there to get the right | |||
5506 | // namespace declarations to the XML parser. That said, the parser _is_ | |||
5507 | // going to create elements with the tag names we provide here, so we need | |||
5508 | // to make sure they are not names that can trigger custom element | |||
5509 | // constructors. Just make up a name that is never going to be a valid | |||
5510 | // custom element name. | |||
5511 | // | |||
5512 | // The principled way to do this would probably be to add a new FromParser | |||
5513 | // value and make sure we use it when creating the context elements, then | |||
5514 | // make sure we teach all FromParser consumers (and in particular the custom | |||
5515 | // element code) about it as needed. But right now the XML parser never | |||
5516 | // actually uses FromParser values other than NOT_FROM_PARSER, and changing | |||
5517 | // that is pretty complicated. | |||
5518 | tagName.AssignLiteral("notacustomelement"); | |||
5519 | ||||
5520 | // see if we need to add xmlns declarations | |||
5521 | uint32_t count = element->GetAttrCount(); | |||
5522 | bool setDefaultNamespace = false; | |||
5523 | if (count > 0) { | |||
5524 | uint32_t index; | |||
5525 | ||||
5526 | for (index = 0; index < count; index++) { | |||
5527 | const BorrowedAttrInfo info = element->GetAttrInfoAt(index); | |||
5528 | const nsAttrName* name = info.mName; | |||
5529 | if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) { | |||
5530 | info.mValue->ToString(uriStr); | |||
5531 | ||||
5532 | // really want something like nsXMLContentSerializer::SerializeAttr | |||
5533 | tagName.AppendLiteral(" xmlns"); // space important | |||
5534 | if (name->GetPrefix()) { | |||
5535 | tagName.Append(char16_t(':')); | |||
5536 | name->LocalName()->ToString(nameStr); | |||
5537 | tagName.Append(nameStr); | |||
5538 | } else { | |||
5539 | setDefaultNamespace = true; | |||
5540 | } | |||
5541 | tagName.AppendLiteral(R"(=")"); | |||
5542 | tagName.Append(uriStr); | |||
5543 | tagName.Append('"'); | |||
5544 | } | |||
5545 | } | |||
5546 | } | |||
5547 | ||||
5548 | if (!setDefaultNamespace) { | |||
5549 | mozilla::dom::NodeInfo* info = element->NodeInfo(); | |||
5550 | if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) { | |||
5551 | // We have no namespace prefix, but have a namespace ID. Push | |||
5552 | // default namespace attr in, so that our kids will be in our | |||
5553 | // namespace. | |||
5554 | info->GetNamespaceURI(uriStr); | |||
5555 | tagName.AppendLiteral(R"( xmlns=")"); | |||
5556 | tagName.Append(uriStr); | |||
5557 | tagName.Append('"'); | |||
5558 | } | |||
5559 | } | |||
5560 | } | |||
5561 | ||||
5562 | RefPtr<DocumentFragment> frag; | |||
5563 | aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution, | |||
5564 | -1, getter_AddRefs(frag)); | |||
5565 | return frag.forget(); | |||
5566 | } | |||
5567 | ||||
5568 | /* static */ | |||
5569 | void nsContentUtils::DropFragmentParsers() { | |||
5570 | NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release (); (sHTMLFragmentParser) = 0; } } while (0); | |||
5571 | NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release (); (sXMLFragmentParser) = 0; } } while (0); | |||
5572 | NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release() ; (sXMLFragmentSink) = 0; } } while (0); | |||
5573 | } | |||
5574 | ||||
5575 | /* static */ | |||
5576 | void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); } | |||
5577 | ||||
5578 | /* Helper function to compuate Sanitization Flags for ParseFramentHTML/XML */ | |||
5579 | uint32_t computeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) { | |||
5580 | uint32_t sanitizationFlags = 0; | |||
5581 | if (aPrincipal->IsSystemPrincipal()) { | |||
5582 | if (aFlags < 0) { | |||
5583 | // if this is a chrome-privileged document and no explicit flags | |||
5584 | // were passed, then use this sanitization flags. | |||
5585 | sanitizationFlags = nsIParserUtils::SanitizerAllowStyle | | |||
5586 | nsIParserUtils::SanitizerAllowComments | | |||
5587 | nsIParserUtils::SanitizerDropForms | | |||
5588 | nsIParserUtils::SanitizerLogRemovals; | |||
5589 | } else { | |||
5590 | // if the caller explicitly passes flags, then we use those | |||
5591 | // flags but additionally drop forms. | |||
5592 | sanitizationFlags = aFlags | nsIParserUtils::SanitizerDropForms; | |||
5593 | } | |||
5594 | } else if (aFlags >= 0) { | |||
5595 | // aFlags by default is -1 and is only ever non equal to -1 if the | |||
5596 | // caller of ParseFragmentHTML/ParseFragmentXML is | |||
5597 | // ParserUtils::ParseFragment(). Only in that case we should use | |||
5598 | // the sanitization flags passed within aFlags. | |||
5599 | sanitizationFlags = aFlags; | |||
5600 | } | |||
5601 | return sanitizationFlags; | |||
5602 | } | |||
5603 | ||||
5604 | /* static */ | |||
5605 | void nsContentUtils::SetHTMLUnsafe(FragmentOrElement* aTarget, | |||
5606 | Element* aContext, | |||
5607 | const nsAString& aSource) { | |||
5608 | RefPtr<DocumentFragment> fragment; | |||
5609 | { | |||
5610 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive" ") (" "Re-entrant fragment parsing attempted." ")"); do { *( (volatile int*)__null) = 5611; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) | |||
5611 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive" ") (" "Re-entrant fragment parsing attempted." ")"); do { *( (volatile int*)__null) = 5611; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); | |||
5612 | mozilla::AutoRestore<bool> guard(sFragmentParsingActive); | |||
5613 | sFragmentParsingActive = true; | |||
5614 | if (!sHTMLFragmentParser) { | |||
5615 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
5616 | // Now sHTMLFragmentParser owns the object | |||
5617 | } | |||
5618 | ||||
5619 | nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom(); | |||
5620 | int32_t contextNameSpaceID = aContext->GetNameSpaceID(); | |||
5621 | ||||
5622 | RefPtr<Document> doc = aTarget->OwnerDoc(); | |||
5623 | fragment = doc->CreateDocumentFragment(); | |||
5624 | nsresult rv = sHTMLFragmentParser->ParseFragment( | |||
5625 | aSource, fragment, contextLocalName, contextNameSpaceID, | |||
5626 | fragment->OwnerDoc()->GetCompatibilityMode() == | |||
5627 | eCompatibility_NavQuirks, | |||
5628 | true, true); | |||
5629 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
5630 | NS_WARNING("Failed to parse fragment for SetHTMLUnsafe")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse fragment for SetHTMLUnsafe" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5630); | |||
5631 | } | |||
5632 | } | |||
5633 | ||||
5634 | aTarget->ReplaceChildren(fragment, IgnoreErrors()); | |||
5635 | } | |||
5636 | ||||
5637 | /* static */ | |||
5638 | nsresult nsContentUtils::ParseFragmentHTML( | |||
5639 | const nsAString& aSourceBuffer, nsIContent* aTargetNode, | |||
5640 | nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks, | |||
5641 | bool aPreventScriptExecution, int32_t aFlags) { | |||
5642 | if (nsContentUtils::sFragmentParsingActive) { | |||
5643 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { *((volatile int*)__null) = 5643; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5644 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
5645 | } | |||
5646 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
5647 | nsContentUtils::sFragmentParsingActive = true; | |||
5648 | if (!sHTMLFragmentParser) { | |||
5649 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
5650 | // Now sHTMLFragmentParser owns the object | |||
5651 | } | |||
5652 | ||||
5653 | nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal(); | |||
5654 | ||||
5655 | #ifdef DEBUG1 | |||
5656 | // aFlags should always be -1 unless the caller of ParseFragmentHTML | |||
5657 | // is ParserUtils::ParseFragment() which is the only caller that intends | |||
5658 | // sanitization. For all other callers we need to ensure to call | |||
5659 | // AuditParsingOfHTMLXMLFragments. | |||
5660 | if (aFlags < 0) { | |||
5661 | DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal, | |||
5662 | aSourceBuffer); | |||
5663 | } | |||
5664 | #endif | |||
5665 | ||||
5666 | nsIContent* target = aTargetNode; | |||
5667 | ||||
5668 | RefPtr<Document> doc = aTargetNode->OwnerDoc(); | |||
5669 | RefPtr<DocumentFragment> fragment; | |||
5670 | // We sanitize if the fragment occurs in a system privileged | |||
5671 | // context, an about: page, or if there are explicit sanitization flags. | |||
5672 | // Please note that about:blank and about:srcdoc inherit the security | |||
5673 | // context from the embedding context and hence are not loaded using | |||
5674 | // an about: scheme principal. | |||
5675 | bool shouldSanitize = nodePrincipal->IsSystemPrincipal() || | |||
5676 | nodePrincipal->SchemeIs("about") || aFlags >= 0; | |||
5677 | if (shouldSanitize) { | |||
5678 | if (!doc->IsLoadedAsData()) { | |||
5679 | doc = nsContentUtils::CreateInertHTMLDocument(doc); | |||
5680 | if (!doc) { | |||
5681 | return NS_ERROR_FAILURE; | |||
5682 | } | |||
5683 | } | |||
5684 | fragment = | |||
5685 | new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager()); | |||
5686 | target = fragment; | |||
5687 | } | |||
5688 | ||||
5689 | nsresult rv = sHTMLFragmentParser->ParseFragment( | |||
5690 | aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks, | |||
5691 | aPreventScriptExecution, false); | |||
5692 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5692); return rv; } } while (false); | |||
5693 | ||||
5694 | if (fragment) { | |||
5695 | uint32_t sanitizationFlags = | |||
5696 | computeSanitizationFlags(nodePrincipal, aFlags); | |||
5697 | // Don't fire mutation events for nodes removed by the sanitizer. | |||
5698 | nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; | |||
5699 | nsTreeSanitizer sanitizer(sanitizationFlags); | |||
5700 | sanitizer.Sanitize(fragment); | |||
5701 | ||||
5702 | ErrorResult error; | |||
5703 | aTargetNode->AppendChild(*fragment, error); | |||
5704 | rv = error.StealNSResult(); | |||
5705 | } | |||
5706 | ||||
5707 | return rv; | |||
5708 | } | |||
5709 | ||||
5710 | /* static */ | |||
5711 | nsresult nsContentUtils::ParseDocumentHTML( | |||
5712 | const nsAString& aSourceBuffer, Document* aTargetDocument, | |||
5713 | bool aScriptingEnabledForNoscriptParsing) { | |||
5714 | if (nsContentUtils::sFragmentParsingActive) { | |||
5715 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { *((volatile int*)__null) = 5715; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5716 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
5717 | } | |||
5718 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
5719 | nsContentUtils::sFragmentParsingActive = true; | |||
5720 | if (!sHTMLFragmentParser) { | |||
5721 | NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef( ); | |||
5722 | // Now sHTMLFragmentParser owns the object | |||
5723 | } | |||
5724 | nsresult rv = sHTMLFragmentParser->ParseDocument( | |||
5725 | aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing); | |||
5726 | return rv; | |||
5727 | } | |||
5728 | ||||
5729 | /* static */ | |||
5730 | nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer, | |||
5731 | Document* aDocument, | |||
5732 | nsTArray<nsString>& aTagStack, | |||
5733 | bool aPreventScriptExecution, | |||
5734 | int32_t aFlags, | |||
5735 | DocumentFragment** aReturn) { | |||
5736 | if (nsContentUtils::sFragmentParsingActive) { | |||
5737 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted." ")"); do { *((volatile int*)__null) = 5737; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5738 | return NS_ERROR_DOM_INVALID_STATE_ERR; | |||
5739 | } | |||
5740 | mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); | |||
5741 | nsContentUtils::sFragmentParsingActive = true; | |||
5742 | if (!sXMLFragmentParser) { | |||
5743 | RefPtr<nsParser> parser = new nsParser(); | |||
5744 | parser.forget(&sXMLFragmentParser); | |||
5745 | // sXMLFragmentParser now owns the parser | |||
5746 | } | |||
5747 | if (!sXMLFragmentSink) { | |||
5748 | NS_NewXMLFragmentContentSink(&sXMLFragmentSink); | |||
5749 | // sXMLFragmentSink now owns the sink | |||
5750 | } | |||
5751 | nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink); | |||
5752 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink" ") (" "Sink doesn't QI to nsIContentSink!" ")"); do { *((volatile int*)__null) = 5752; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
5753 | sXMLFragmentParser->SetContentSink(contentsink); | |||
5754 | ||||
5755 | RefPtr<Document> doc; | |||
5756 | nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal(); | |||
5757 | ||||
5758 | #ifdef DEBUG1 | |||
5759 | // aFlags should always be -1 unless the caller of ParseFragmentXML | |||
5760 | // is ParserUtils::ParseFragment() which is the only caller that intends | |||
5761 | // sanitization. For all other callers we need to ensure to call | |||
5762 | // AuditParsingOfHTMLXMLFragments. | |||
5763 | if (aFlags < 0) { | |||
5764 | DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal, | |||
5765 | aSourceBuffer); | |||
5766 | } | |||
5767 | #endif | |||
5768 | ||||
5769 | // We sanitize if the fragment occurs in a system privileged | |||
5770 | // context, an about: page, or if there are explicit sanitization flags. | |||
5771 | // Please note that about:blank and about:srcdoc inherit the security | |||
5772 | // context from the embedding context and hence are not loaded using | |||
5773 | // an about: scheme principal. | |||
5774 | bool shouldSanitize = nodePrincipal->IsSystemPrincipal() || | |||
5775 | nodePrincipal->SchemeIs("about") || aFlags >= 0; | |||
5776 | if (shouldSanitize && !aDocument->IsLoadedAsData()) { | |||
5777 | doc = nsContentUtils::CreateInertXMLDocument(aDocument); | |||
5778 | } else { | |||
5779 | doc = aDocument; | |||
5780 | } | |||
5781 | ||||
5782 | sXMLFragmentSink->SetTargetDocument(doc); | |||
5783 | sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); | |||
5784 | ||||
5785 | nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); | |||
5786 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
5787 | // Drop the fragment parser and sink that might be in an inconsistent state | |||
5788 | NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release (); (sXMLFragmentParser) = 0; } } while (0); | |||
5789 | NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release() ; (sXMLFragmentSink) = 0; } } while (0); | |||
5790 | return rv; | |||
5791 | } | |||
5792 | ||||
5793 | rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); | |||
5794 | ||||
5795 | sXMLFragmentParser->Reset(); | |||
5796 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5796); return rv; } } while (false); | |||
5797 | ||||
5798 | if (shouldSanitize) { | |||
5799 | uint32_t sanitizationFlags = | |||
5800 | computeSanitizationFlags(nodePrincipal, aFlags); | |||
5801 | // Don't fire mutation events for nodes removed by the sanitizer. | |||
5802 | nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; | |||
5803 | nsTreeSanitizer sanitizer(sanitizationFlags); | |||
5804 | sanitizer.Sanitize(*aReturn); | |||
5805 | } | |||
5806 | ||||
5807 | return rv; | |||
5808 | } | |||
5809 | ||||
5810 | /* static */ | |||
5811 | nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer, | |||
5812 | nsAString& aResultBuffer, | |||
5813 | uint32_t aFlags, | |||
5814 | uint32_t aWrapCol) { | |||
5815 | RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr); | |||
5816 | if (!document) { | |||
5817 | return NS_ERROR_FAILURE; | |||
5818 | } | |||
5819 | ||||
5820 | nsresult rv = nsContentUtils::ParseDocumentHTML( | |||
5821 | aSourceBuffer, document, | |||
5822 | !(aFlags & nsIDocumentEncoder::OutputNoScriptContent)); | |||
5823 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5823); return rv; } } while (false); | |||
5824 | ||||
5825 | nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain"); | |||
5826 | ||||
5827 | rv = encoder->Init(document, u"text/plain"_ns, aFlags); | |||
5828 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5828); return rv; } } while (false); | |||
5829 | ||||
5830 | encoder->SetWrapColumn(aWrapCol); | |||
5831 | ||||
5832 | return encoder->EncodeToString(aResultBuffer); | |||
5833 | } | |||
5834 | ||||
5835 | static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate, | |||
5836 | DocumentFlavor aFlavor) { | |||
5837 | if (aTemplate) { | |||
5838 | bool hasHad = true; | |||
5839 | nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad); | |||
5840 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5840); return nullptr; } } while (false); | |||
5841 | ||||
5842 | nsCOMPtr<Document> doc; | |||
5843 | nsresult rv = NS_NewDOMDocument( | |||
5844 | getter_AddRefs(doc), u""_ns, u""_ns, nullptr, | |||
5845 | aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(), | |||
5846 | aTemplate->NodePrincipal(), true, sgo, aFlavor); | |||
5847 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
5848 | return nullptr; | |||
5849 | } | |||
5850 | return doc.forget(); | |||
5851 | } | |||
5852 | nsCOMPtr<nsIURI> uri; | |||
5853 | NS_NewURI(getter_AddRefs(uri), "about:blank"_ns); | |||
5854 | if (!uri) { | |||
5855 | return nullptr; | |||
5856 | } | |||
5857 | ||||
5858 | RefPtr<NullPrincipal> nullPrincipal = | |||
5859 | NullPrincipal::CreateWithoutOriginAttributes(); | |||
5860 | if (!nullPrincipal) { | |||
5861 | return nullptr; | |||
5862 | } | |||
5863 | ||||
5864 | nsCOMPtr<Document> doc; | |||
5865 | nsresult rv = | |||
5866 | NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri, | |||
5867 | nullPrincipal, true, nullptr, aFlavor); | |||
5868 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
5869 | return nullptr; | |||
5870 | } | |||
5871 | return doc.forget(); | |||
5872 | } | |||
5873 | ||||
5874 | /* static */ | |||
5875 | already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument( | |||
5876 | const Document* aTemplate) { | |||
5877 | return CreateInertDocument(aTemplate, DocumentFlavorXML); | |||
5878 | } | |||
5879 | ||||
5880 | /* static */ | |||
5881 | already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument( | |||
5882 | const Document* aTemplate) { | |||
5883 | return CreateInertDocument(aTemplate, DocumentFlavorHTML); | |||
5884 | } | |||
5885 | ||||
5886 | /* static */ | |||
5887 | nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent, | |||
5888 | const nsAString& aValue, | |||
5889 | bool aTryReuse) { | |||
5890 | // Fire DOMNodeRemoved mutation events before we do anything else. | |||
5891 | nsCOMPtr<nsIContent> owningContent; | |||
5892 | ||||
5893 | // Batch possible DOMSubtreeModified events. | |||
5894 | mozAutoSubtreeModified subtree(nullptr, nullptr); | |||
5895 | ||||
5896 | // Scope firing mutation events so that we don't carry any state that | |||
5897 | // might be stale | |||
5898 | { | |||
5899 | // We're relying on mozAutoSubtreeModified to keep a strong reference if | |||
5900 | // needed. | |||
5901 | Document* doc = aContent->OwnerDoc(); | |||
5902 | ||||
5903 | // Optimize the common case of there being no observers | |||
5904 | if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED0x04)) { | |||
5905 | subtree.UpdateTarget(doc, nullptr); | |||
5906 | owningContent = aContent; | |||
5907 | nsCOMPtr<nsINode> child; | |||
5908 | bool skipFirst = aTryReuse; | |||
5909 | for (child = aContent->GetFirstChild(); | |||
5910 | child && child->GetParentNode() == aContent; | |||
5911 | child = child->GetNextSibling()) { | |||
5912 | if (skipFirst && child->IsText()) { | |||
5913 | skipFirst = false; | |||
5914 | continue; | |||
5915 | } | |||
5916 | nsContentUtils::MaybeFireNodeRemoved(child, aContent); | |||
5917 | } | |||
5918 | } | |||
5919 | } | |||
5920 | ||||
5921 | // Might as well stick a batch around this since we're performing several | |||
5922 | // mutations. | |||
5923 | mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true); | |||
5924 | nsAutoMutationBatch mb; | |||
5925 | ||||
5926 | if (aTryReuse && !aValue.IsEmpty()) { | |||
5927 | // Let's remove nodes until we find a eTEXT. | |||
5928 | while (aContent->HasChildren()) { | |||
5929 | nsIContent* child = aContent->GetFirstChild(); | |||
5930 | if (child->IsText()) { | |||
5931 | break; | |||
5932 | } | |||
5933 | aContent->RemoveChildNode(child, true); | |||
5934 | } | |||
5935 | ||||
5936 | // If we have a node, it must be a eTEXT and we reuse it. | |||
5937 | if (aContent->HasChildren()) { | |||
5938 | nsIContent* child = aContent->GetFirstChild(); | |||
5939 | nsresult rv = child->AsText()->SetText(aValue, true); | |||
5940 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 5940); return rv; } } while (false); | |||
5941 | ||||
5942 | // All the following nodes, if they exist, must be deleted. | |||
5943 | while (nsIContent* nextChild = child->GetNextSibling()) { | |||
5944 | aContent->RemoveChildNode(nextChild, true); | |||
5945 | } | |||
5946 | } | |||
5947 | ||||
5948 | if (aContent->HasChildren()) { | |||
5949 | return NS_OK; | |||
5950 | } | |||
5951 | } else { | |||
5952 | mb.Init(aContent, true, false); | |||
5953 | while (aContent->HasChildren()) { | |||
5954 | aContent->RemoveChildNode(aContent->GetFirstChild(), true); | |||
5955 | } | |||
5956 | } | |||
5957 | mb.RemovalDone(); | |||
5958 | ||||
5959 | if (aValue.IsEmpty()) { | |||
5960 | return NS_OK; | |||
5961 | } | |||
5962 | ||||
5963 | RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager()) | |||
5964 | nsTextNode(aContent->NodeInfo()->NodeInfoManager()); | |||
5965 | ||||
5966 | textContent->SetText(aValue, true); | |||
5967 | ||||
5968 | ErrorResult rv; | |||
5969 | aContent->AppendChildTo(textContent, true, rv); | |||
5970 | mb.NodesAdded(); | |||
5971 | return rv.StealNSResult(); | |||
5972 | } | |||
5973 | ||||
5974 | static bool AppendNodeTextContentsRecurse(const nsINode* aNode, | |||
5975 | nsAString& aResult, | |||
5976 | const fallible_t& aFallible) { | |||
5977 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
5978 | child = child->GetNextSibling()) { | |||
5979 | if (child->IsElement()) { | |||
5980 | bool ok = AppendNodeTextContentsRecurse(child, aResult, aFallible); | |||
5981 | if (!ok) { | |||
5982 | return false; | |||
5983 | } | |||
5984 | } else if (Text* text = child->GetAsText()) { | |||
5985 | bool ok = text->AppendTextTo(aResult, aFallible); | |||
5986 | if (!ok) { | |||
5987 | return false; | |||
5988 | } | |||
5989 | } | |||
5990 | } | |||
5991 | ||||
5992 | return true; | |||
5993 | } | |||
5994 | ||||
5995 | /* static */ | |||
5996 | bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep, | |||
5997 | nsAString& aResult, | |||
5998 | const fallible_t& aFallible) { | |||
5999 | if (const Text* text = aNode->GetAsText()) { | |||
6000 | return text->AppendTextTo(aResult, aFallible); | |||
6001 | } | |||
6002 | if (aDeep) { | |||
6003 | return AppendNodeTextContentsRecurse(aNode, aResult, aFallible); | |||
6004 | } | |||
6005 | ||||
6006 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
6007 | child = child->GetNextSibling()) { | |||
6008 | if (Text* text = child->GetAsText()) { | |||
6009 | bool ok = text->AppendTextTo(aResult, fallible); | |||
6010 | if (!ok) { | |||
6011 | return false; | |||
6012 | } | |||
6013 | } | |||
6014 | } | |||
6015 | return true; | |||
6016 | } | |||
6017 | ||||
6018 | bool nsContentUtils::HasNonEmptyTextContent( | |||
6019 | nsINode* aNode, TextContentDiscoverMode aDiscoverMode) { | |||
6020 | for (nsIContent* child = aNode->GetFirstChild(); child; | |||
6021 | child = child->GetNextSibling()) { | |||
6022 | if (child->IsText() && child->TextLength() > 0) { | |||
6023 | return true; | |||
6024 | } | |||
6025 | ||||
6026 | if (aDiscoverMode == eRecurseIntoChildren && | |||
6027 | HasNonEmptyTextContent(child, aDiscoverMode)) { | |||
6028 | return true; | |||
6029 | } | |||
6030 | } | |||
6031 | ||||
6032 | return false; | |||
6033 | } | |||
6034 | ||||
6035 | /* static */ | |||
6036 | bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode, | |||
6037 | const nsINode* aOtherNode) { | |||
6038 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "Must have a node to work with" ")"); do { *((volatile int*) __null) = 6038; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
6039 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode" ") (" "Must have a content to work with" ")"); do { *((volatile int*)__null) = 6039; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6040 | ||||
6041 | const bool anon = aNode->IsInNativeAnonymousSubtree(); | |||
6042 | if (anon != aOtherNode->IsInNativeAnonymousSubtree()) { | |||
6043 | return false; | |||
6044 | } | |||
6045 | ||||
6046 | if (anon) { | |||
6047 | return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() == | |||
6048 | aNode->GetClosestNativeAnonymousSubtreeRoot(); | |||
6049 | } | |||
6050 | ||||
6051 | // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't | |||
6052 | // use to either. Maybe that's fine. | |||
6053 | return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow(); | |||
6054 | } | |||
6055 | ||||
6056 | /* static */ | |||
6057 | bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement, | |||
6058 | const Element* aStop) { | |||
6059 | const Element* element = aElement; | |||
6060 | while (element && element != aStop) { | |||
6061 | if (element->IsInteractiveHTMLContent()) { | |||
6062 | return true; | |||
6063 | } | |||
6064 | element = element->GetFlattenedTreeParentElement(); | |||
6065 | } | |||
6066 | return false; | |||
6067 | } | |||
6068 | ||||
6069 | /* static */ | |||
6070 | void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) { | |||
6071 | IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling); | |||
6072 | } | |||
6073 | ||||
6074 | /* static */ | |||
6075 | bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) { | |||
6076 | nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI); | |||
6077 | NS_ENSURE_TRUE(baseURI, false)do { if ((__builtin_expect(!!(!(baseURI)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "baseURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6077); return false; } } while (false); | |||
6078 | return baseURI->SchemeIs(aScheme); | |||
6079 | } | |||
6080 | ||||
6081 | bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) { | |||
6082 | return aPrincipal && aPrincipal->GetIsExpandedPrincipal(); | |||
6083 | } | |||
6084 | ||||
6085 | bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) { | |||
6086 | return (aPrincipal && aPrincipal->IsSystemPrincipal()) || | |||
6087 | IsExpandedPrincipal(aPrincipal); | |||
6088 | } | |||
6089 | ||||
6090 | nsIPrincipal* nsContentUtils::GetSystemPrincipal() { | |||
6091 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { *((volatile int*)__null) = 6091; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6092 | return sSystemPrincipal; | |||
6093 | } | |||
6094 | ||||
6095 | bool nsContentUtils::CombineResourcePrincipals( | |||
6096 | nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) { | |||
6097 | if (!aExtraPrincipal) { | |||
6098 | return false; | |||
6099 | } | |||
6100 | if (!*aResourcePrincipal) { | |||
6101 | *aResourcePrincipal = aExtraPrincipal; | |||
6102 | return true; | |||
6103 | } | |||
6104 | if (*aResourcePrincipal == aExtraPrincipal) { | |||
6105 | return false; | |||
6106 | } | |||
6107 | bool subsumes; | |||
6108 | if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal )->Subsumes(aExtraPrincipal, &subsumes))), 1))) | |||
6109 | (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal )->Subsumes(aExtraPrincipal, &subsumes))), 1))) && | |||
6110 | subsumes) { | |||
6111 | return false; | |||
6112 | } | |||
6113 | *aResourcePrincipal = sSystemPrincipal; | |||
6114 | return true; | |||
6115 | } | |||
6116 | ||||
6117 | /* static */ | |||
6118 | void nsContentUtils::TriggerLink(nsIContent* aContent, nsIURI* aLinkURI, | |||
6119 | const nsString& aTargetSpec, bool aClick, | |||
6120 | bool aIsTrusted) { | |||
6121 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI" ")"); do { *((volatile int*)__null) = 6121; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
6122 | ||||
6123 | if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) { | |||
6124 | return; | |||
6125 | } | |||
6126 | ||||
6127 | nsCOMPtr<nsIDocShell> docShell = aContent->OwnerDoc()->GetDocShell(); | |||
6128 | if (!docShell) { | |||
6129 | return; | |||
6130 | } | |||
6131 | ||||
6132 | if (!aClick) { | |||
6133 | nsDocShell::Cast(docShell)->OnOverLink(aContent, aLinkURI, aTargetSpec); | |||
6134 | return; | |||
6135 | } | |||
6136 | ||||
6137 | // Check that this page is allowed to load this URI. | |||
6138 | nsresult proceed = NS_OK; | |||
6139 | ||||
6140 | if (sSecurityManager) { | |||
6141 | uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD); | |||
6142 | proceed = sSecurityManager->CheckLoadURIWithPrincipal( | |||
6143 | aContent->NodePrincipal(), aLinkURI, flag, | |||
6144 | aContent->OwnerDoc()->InnerWindowID()); | |||
6145 | } | |||
6146 | ||||
6147 | // Only pass off the click event if the script security manager says it's ok. | |||
6148 | // We need to rest aTargetSpec for forced downloads. | |||
6149 | if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) { | |||
6150 | // A link/area element with a download attribute is allowed to set | |||
6151 | // a pseudo Content-Disposition header. | |||
6152 | // For security reasons we only allow websites to declare same-origin | |||
6153 | // resources as downloadable. If this check fails we will just do the normal | |||
6154 | // thing (i.e. navigate to the resource). | |||
6155 | nsAutoString fileName; | |||
6156 | if ((!aContent->IsHTMLElement(nsGkAtoms::a) && | |||
6157 | !aContent->IsHTMLElement(nsGkAtoms::area) && | |||
6158 | !aContent->IsSVGElement(nsGkAtoms::a)) || | |||
6159 | !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) || | |||
6160 | NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal ()->CheckMayLoad(aLinkURI, true))), 0)))) { | |||
6161 | fileName.SetIsVoid(true); // No actionable download attribute was found. | |||
6162 | } | |||
6163 | ||||
6164 | nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal(); | |||
6165 | nsCOMPtr<nsIContentSecurityPolicy> csp = aContent->GetCsp(); | |||
6166 | ||||
6167 | // Sanitize fileNames containing null characters by replacing them with | |||
6168 | // underscores. | |||
6169 | if (!fileName.IsVoid()) { | |||
6170 | fileName.ReplaceChar(char16_t(0), '_'); | |||
6171 | } | |||
6172 | nsDocShell::Cast(docShell)->OnLinkClick( | |||
6173 | aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName, | |||
6174 | nullptr, nullptr, UserActivation::IsHandlingUserInput(), aIsTrusted, | |||
6175 | triggeringPrincipal, csp); | |||
6176 | } | |||
6177 | } | |||
6178 | ||||
6179 | /* static */ | |||
6180 | void nsContentUtils::GetLinkLocation(Element* aElement, | |||
6181 | nsString& aLocationString) { | |||
6182 | nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI(); | |||
6183 | if (hrefURI) { | |||
6184 | nsAutoCString specUTF8; | |||
6185 | nsresult rv = hrefURI->GetSpec(specUTF8); | |||
6186 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString); | |||
6187 | } | |||
6188 | } | |||
6189 | ||||
6190 | /* static */ | |||
6191 | nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) { | |||
6192 | if (!aWidget) return nullptr; | |||
6193 | ||||
6194 | return aWidget->GetTopLevelWidget(); | |||
6195 | } | |||
6196 | ||||
6197 | /* static */ | |||
6198 | const nsDependentString nsContentUtils::GetLocalizedEllipsis() { | |||
6199 | static char16_t sBuf[4] = {0, 0, 0, 0}; | |||
6200 | if (!sBuf[0]) { | |||
6201 | if (!SpoofLocaleEnglish()) { | |||
6202 | nsAutoString tmp; | |||
6203 | Preferences::GetLocalizedString("intl.ellipsis", tmp); | |||
6204 | uint32_t len = | |||
6205 | std::min(uint32_t(tmp.Length()), uint32_t(ArrayLength(sBuf) - 1)); | |||
6206 | CopyUnicodeTo(tmp, 0, sBuf, len); | |||
6207 | } | |||
6208 | if (!sBuf[0]) sBuf[0] = char16_t(0x2026); | |||
6209 | } | |||
6210 | return nsDependentString(sBuf); | |||
6211 | } | |||
6212 | ||||
6213 | /* static */ | |||
6214 | void nsContentUtils::AddScriptBlocker() { | |||
6215 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 6215; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6216 | if (!sScriptBlockerCount) { | |||
6217 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0" ") (" "Should not already have a count" ")"); do { *((volatile int*)__null) = 6218; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) | |||
6218 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0" ") (" "Should not already have a count" ")"); do { *((volatile int*)__null) = 6218; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6219 | sRunnersCountAtFirstBlocker = | |||
6220 | sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0; | |||
6221 | } | |||
6222 | ++sScriptBlockerCount; | |||
6223 | } | |||
6224 | ||||
6225 | #ifdef DEBUG1 | |||
6226 | static bool sRemovingScriptBlockers = false; | |||
6227 | #endif | |||
6228 | ||||
6229 | /* static */ | |||
6230 | void nsContentUtils::RemoveScriptBlocker() { | |||
6231 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 6231; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6232 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sRemovingScriptBlockers" ")"); do { *((volatile int*)__null) = 6232; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6233 | NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers")do { if (!(sScriptBlockerCount != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Negative script blockers", "sScriptBlockerCount != 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6233); MOZ_PretendNoReturn(); } } while (0); | |||
6234 | --sScriptBlockerCount; | |||
6235 | if (sScriptBlockerCount) { | |||
6236 | return; | |||
6237 | } | |||
6238 | ||||
6239 | if (!sBlockedScriptRunners) { | |||
6240 | return; | |||
6241 | } | |||
6242 | ||||
6243 | uint32_t firstBlocker = sRunnersCountAtFirstBlocker; | |||
6244 | uint32_t lastBlocker = sBlockedScriptRunners->Length(); | |||
6245 | uint32_t originalFirstBlocker = firstBlocker; | |||
6246 | uint32_t blockersCount = lastBlocker - firstBlocker; | |||
6247 | sRunnersCountAtFirstBlocker = 0; | |||
6248 | NS_ASSERTION(firstBlocker <= lastBlocker, "bad sRunnersCountAtFirstBlocker")do { if (!(firstBlocker <= lastBlocker)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "bad sRunnersCountAtFirstBlocker", "firstBlocker <= lastBlocker" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6248); MOZ_PretendNoReturn(); } } while (0); | |||
6249 | ||||
6250 | while (firstBlocker < lastBlocker) { | |||
6251 | nsCOMPtr<nsIRunnable> runnable; | |||
6252 | runnable.swap((*sBlockedScriptRunners)[firstBlocker]); | |||
6253 | ++firstBlocker; | |||
6254 | ||||
6255 | // Calling the runnable can reenter us | |||
6256 | { | |||
6257 | AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker ; if (profiler_thread_is_being_profiled_for_markers()) { raiiRunnableMarker .emplace(runnable); }; | |||
6258 | runnable->Run(); | |||
6259 | } | |||
6260 | // So can dropping the reference to the runnable | |||
6261 | runnable = nullptr; | |||
6262 | ||||
6263 | NS_ASSERTION(sRunnersCountAtFirstBlocker == 0, "Bad count")do { if (!(sRunnersCountAtFirstBlocker == 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Bad count", "sRunnersCountAtFirstBlocker == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6263); MOZ_PretendNoReturn(); } } while (0); | |||
6264 | NS_ASSERTION(!sScriptBlockerCount, "This is really bad")do { if (!(!sScriptBlockerCount)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "This is really bad", "!sScriptBlockerCount", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6264); MOZ_PretendNoReturn(); } } while (0); | |||
6265 | } | |||
6266 | #ifdef DEBUG1 | |||
6267 | AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers); | |||
6268 | sRemovingScriptBlockers = true; | |||
6269 | #endif | |||
6270 | sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount); | |||
6271 | } | |||
6272 | ||||
6273 | /* static */ | |||
6274 | already_AddRefed<nsPIDOMWindowOuter> | |||
6275 | nsContentUtils::GetMostRecentNonPBWindow() { | |||
6276 | nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1"); | |||
6277 | ||||
6278 | nsCOMPtr<mozIDOMWindowProxy> window; | |||
6279 | wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window)); | |||
6280 | nsCOMPtr<nsPIDOMWindowOuter> pwindow; | |||
6281 | pwindow = do_QueryInterface(window); | |||
6282 | ||||
6283 | return pwindow.forget(); | |||
6284 | } | |||
6285 | ||||
6286 | /* static */ | |||
6287 | void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) { | |||
6288 | nsAutoString msg; | |||
6289 | bool privateBrowsing = false; | |||
6290 | bool chromeContext = false; | |||
6291 | ||||
6292 | if (aDocument) { | |||
6293 | nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI(); | |||
6294 | if (uri) { | |||
6295 | msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault())); | |||
6296 | msg.AppendLiteral(" : "); | |||
6297 | } | |||
6298 | privateBrowsing = | |||
6299 | aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing(); | |||
6300 | chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal(); | |||
6301 | } | |||
6302 | ||||
6303 | msg.AppendLiteral( | |||
6304 | "Unable to run script because scripts are blocked internally."); | |||
6305 | LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext); | |||
6306 | } | |||
6307 | ||||
6308 | /* static */ | |||
6309 | void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) { | |||
6310 | nsCOMPtr<nsIRunnable> runnable = aRunnable; | |||
6311 | if (!runnable) { | |||
6312 | return; | |||
6313 | } | |||
6314 | ||||
6315 | if (sScriptBlockerCount) { | |||
6316 | sBlockedScriptRunners->AppendElement(runnable.forget()); | |||
6317 | return; | |||
6318 | } | |||
6319 | ||||
6320 | AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker ; if (profiler_thread_is_being_profiled_for_markers()) { raiiRunnableMarker .emplace(runnable); }; | |||
6321 | runnable->Run(); | |||
6322 | } | |||
6323 | ||||
6324 | /* static */ | |||
6325 | void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) { | |||
6326 | nsCOMPtr<nsIRunnable> runnable = aRunnable; | |||
6327 | AddScriptRunner(runnable.forget()); | |||
6328 | } | |||
6329 | ||||
6330 | /* static */ bool nsContentUtils::IsSafeToRunScript() { | |||
6331 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "This static variable only makes sense on the main thread!" ")"); do { *((volatile int*)__null) = 6332; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
6332 | "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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "This static variable only makes sense on the main thread!" ")"); do { *((volatile int*)__null) = 6332; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6333 | return sScriptBlockerCount == 0; | |||
6334 | } | |||
6335 | ||||
6336 | /* static */ | |||
6337 | void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) { | |||
6338 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { *((volatile int *)__null) = 6338; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6339 | CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable)); | |||
6340 | } | |||
6341 | ||||
6342 | /* static */ | |||
6343 | void nsContentUtils::AddPendingIDBTransaction( | |||
6344 | already_AddRefed<nsIRunnable> aTransaction) { | |||
6345 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { *((volatile int *)__null) = 6345; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6346 | CycleCollectedJSContext::Get()->AddPendingIDBTransaction( | |||
6347 | std::move(aTransaction)); | |||
6348 | } | |||
6349 | ||||
6350 | /* static */ | |||
6351 | bool nsContentUtils::IsInStableOrMetaStableState() { | |||
6352 | 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!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()" ") (" "Must be on a script thread!" ")"); do { *((volatile int *)__null) = 6352; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6353 | return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState(); | |||
6354 | } | |||
6355 | ||||
6356 | /* static */ | |||
6357 | void nsContentUtils::HidePopupsInDocument(Document* aDocument) { | |||
6358 | RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance(); | |||
6359 | if (!pm || !aDocument) { | |||
6360 | return; | |||
6361 | } | |||
6362 | nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell(); | |||
6363 | if (docShellToHide) { | |||
6364 | pm->HidePopupsInDocShell(docShellToHide); | |||
6365 | } | |||
6366 | } | |||
6367 | ||||
6368 | /* static */ | |||
6369 | already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession( | |||
6370 | nsIWidget* aWidget) { | |||
6371 | nsCOMPtr<nsIDragSession> dragSession; | |||
6372 | nsCOMPtr<nsIDragService> dragService = | |||
6373 | do_GetService("@mozilla.org/widget/dragservice;1"); | |||
6374 | if (dragService) { | |||
6375 | dragSession = dragService->GetCurrentSession(aWidget); | |||
6376 | } | |||
6377 | return dragSession.forget(); | |||
6378 | } | |||
6379 | ||||
6380 | /* static */ | |||
6381 | already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession( | |||
6382 | nsPresContext* aPC) { | |||
6383 | return GetDragSession(aPC->GetRootWidget()); | |||
6384 | } | |||
6385 | ||||
6386 | /* static */ | |||
6387 | nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) { | |||
6388 | if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) { | |||
6389 | return NS_OK; | |||
6390 | } | |||
6391 | ||||
6392 | // For dragstart events, the data transfer object is | |||
6393 | // created before the event fires, so it should already be set. For other | |||
6394 | // drag events, get the object from the drag session. | |||
6395 | NS_ASSERTION(aDragEvent->mMessage != eDragStart,do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer" , "aDragEvent->mMessage != eDragStart", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6396); MOZ_PretendNoReturn(); } } while (0) | |||
6396 | "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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6396); MOZ_PretendNoReturn(); } } while (0); | |||
6397 | ||||
6398 | nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget); | |||
6399 | NS_ENSURE_TRUE(dragSession, NS_OK)do { if ((__builtin_expect(!!(!(dragSession)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "dragSession" ") failed" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6399); return NS_OK; } } while (false); // no drag in progress | |||
6400 | ||||
6401 | RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer(); | |||
6402 | if (!initialDataTransfer) { | |||
6403 | // A dataTransfer won't exist when a drag was started by some other | |||
6404 | // means, for instance calling the drag service directly, or a drag | |||
6405 | // from another application. In either case, a new dataTransfer should | |||
6406 | // be created that reflects the data. | |||
6407 | initialDataTransfer = new DataTransfer( | |||
6408 | aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing()); | |||
6409 | ||||
6410 | // now set it in the drag session so we don't need to create it again | |||
6411 | dragSession->SetDataTransfer(initialDataTransfer); | |||
6412 | } | |||
6413 | ||||
6414 | bool isCrossDomainSubFrameDrop = false; | |||
6415 | if (aDragEvent->mMessage == eDrop) { | |||
6416 | isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent); | |||
6417 | } | |||
6418 | ||||
6419 | // each event should use a clone of the original dataTransfer. | |||
6420 | initialDataTransfer->Clone( | |||
6421 | aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled, | |||
6422 | isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer)); | |||
6423 | if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6423)) { | |||
6424 | return NS_ERROR_OUT_OF_MEMORY; | |||
6425 | } | |||
6426 | ||||
6427 | // for the dragenter and dragover events, initialize the drop effect | |||
6428 | // from the drop action, which platform specific widget code sets before | |||
6429 | // the event is fired based on the keyboard state. | |||
6430 | if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) { | |||
6431 | uint32_t action; | |||
6432 | dragSession->GetDragAction(&action); | |||
6433 | uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt(); | |||
6434 | aDragEvent->mDataTransfer->SetDropEffectInt( | |||
6435 | FilterDropEffect(action, effectAllowed)); | |||
6436 | } else if (aDragEvent->mMessage == eDrop || | |||
6437 | aDragEvent->mMessage == eDragEnd) { | |||
6438 | // For the drop and dragend events, set the drop effect based on the | |||
6439 | // last value that the dropEffect had. This will have been set in | |||
6440 | // EventStateManager::PostHandleEvent for the last dragenter or | |||
6441 | // dragover event. | |||
6442 | aDragEvent->mDataTransfer->SetDropEffectInt( | |||
6443 | initialDataTransfer->DropEffectInt()); | |||
6444 | } | |||
6445 | ||||
6446 | return NS_OK; | |||
6447 | } | |||
6448 | ||||
6449 | /* static */ | |||
6450 | uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction, | |||
6451 | uint32_t aEffectAllowed) { | |||
6452 | // It is possible for the drag action to include more than one action, but | |||
6453 | // the widget code which sets the action from the keyboard state should only | |||
6454 | // be including one. If multiple actions were set, we just consider them in | |||
6455 | // the following order: | |||
6456 | // copy, link, move | |||
6457 | if (aAction & nsIDragService::DRAGDROP_ACTION_COPY) | |||
6458 | aAction = nsIDragService::DRAGDROP_ACTION_COPY; | |||
6459 | else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK) | |||
6460 | aAction = nsIDragService::DRAGDROP_ACTION_LINK; | |||
6461 | else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE) | |||
6462 | aAction = nsIDragService::DRAGDROP_ACTION_MOVE; | |||
6463 | ||||
6464 | // Filter the action based on the effectAllowed. If the effectAllowed | |||
6465 | // doesn't include the action, then that action cannot be done, so adjust | |||
6466 | // the action to something that is allowed. For a copy, adjust to move or | |||
6467 | // link. For a move, adjust to copy or link. For a link, adjust to move or | |||
6468 | // link. Otherwise, use none. | |||
6469 | if (aAction & aEffectAllowed || | |||
6470 | aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) | |||
6471 | return aAction; | |||
6472 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE) | |||
6473 | return nsIDragService::DRAGDROP_ACTION_MOVE; | |||
6474 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY) | |||
6475 | return nsIDragService::DRAGDROP_ACTION_COPY; | |||
6476 | if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK) | |||
6477 | return nsIDragService::DRAGDROP_ACTION_LINK; | |||
6478 | return nsIDragService::DRAGDROP_ACTION_NONE; | |||
6479 | } | |||
6480 | ||||
6481 | /* static */ | |||
6482 | bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession, | |||
6483 | WidgetDragEvent* aDropEvent) { | |||
6484 | nsCOMPtr<nsIContent> target = | |||
6485 | nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget); | |||
6486 | if (!target) { | |||
6487 | return true; | |||
6488 | } | |||
6489 | ||||
6490 | // Always allow dropping onto chrome shells. | |||
6491 | BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext(); | |||
6492 | if (targetBC->IsChrome()) { | |||
6493 | return false; | |||
6494 | } | |||
6495 | ||||
6496 | WindowContext* targetWC = target->OwnerDoc()->GetWindowContext(); | |||
6497 | ||||
6498 | // If there is no source browsing context, then this is a drag from another | |||
6499 | // application, which should be allowed. | |||
6500 | RefPtr<WindowContext> sourceWC; | |||
6501 | aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC)); | |||
6502 | if (sourceWC) { | |||
6503 | // Get each successive parent of the source document and compare it to | |||
6504 | // the drop document. If they match, then this is a drag from a child frame. | |||
6505 | for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC; | |||
6506 | sourceWC = sourceWC->GetParentWindowContext()) { | |||
6507 | // If the source and the target match, then the drag started in a | |||
6508 | // descendant frame. If the source is discarded, err on the side of | |||
6509 | // caution and treat it as a subframe drag. | |||
6510 | if (sourceWC == targetWC || sourceWC->IsDiscarded()) { | |||
6511 | return true; | |||
6512 | } | |||
6513 | } | |||
6514 | } | |||
6515 | ||||
6516 | return false; | |||
6517 | } | |||
6518 | ||||
6519 | /* static */ | |||
6520 | bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) { | |||
6521 | bool isFile; | |||
6522 | nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service(); | |||
6523 | ||||
6524 | // Important: we do NOT test the entire URI chain here! | |||
6525 | return util && | |||
6526 | NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags ( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))) , 1))) | |||
6527 | aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags ( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))) , 1))) && | |||
6528 | isFile; | |||
6529 | } | |||
6530 | ||||
6531 | /* static */ | |||
6532 | JSContext* nsContentUtils::GetCurrentJSContext() { | |||
6533 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { *((volatile int*)__null) = 6533; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6534 | if (!IsJSAPIActive()) { | |||
6535 | return nullptr; | |||
6536 | } | |||
6537 | return danger::GetJSContext(); | |||
6538 | } | |||
6539 | ||||
6540 | template <typename StringType, typename CharType> | |||
6541 | void _ASCIIToLowerInSitu(StringType& aStr) { | |||
6542 | CharType* iter = aStr.BeginWriting(); | |||
6543 | CharType* end = aStr.EndWriting(); | |||
6544 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end" ")"); do { *((volatile int*)__null) = 6544; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6545 | ||||
6546 | while (iter != end) { | |||
6547 | CharType c = *iter; | |||
6548 | if (c >= 'A' && c <= 'Z') { | |||
6549 | *iter = c + ('a' - 'A'); | |||
6550 | } | |||
6551 | ++iter; | |||
6552 | } | |||
6553 | } | |||
6554 | ||||
6555 | /* static */ | |||
6556 | void nsContentUtils::ASCIIToLower(nsAString& aStr) { | |||
6557 | return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr); | |||
6558 | } | |||
6559 | ||||
6560 | /* static */ | |||
6561 | void nsContentUtils::ASCIIToLower(nsACString& aStr) { | |||
6562 | return _ASCIIToLowerInSitu<nsACString, char>(aStr); | |||
6563 | } | |||
6564 | ||||
6565 | template <typename StringType, typename CharType> | |||
6566 | void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) { | |||
6567 | uint32_t len = aSource.Length(); | |||
6568 | aDest.SetLength(len); | |||
6569 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { *((volatile int*)__null) = 6569; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6570 | ||||
6571 | CharType* dest = aDest.BeginWriting(); | |||
6572 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")"); do { *((volatile int*)__null) = 6572; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6573 | ||||
6574 | const CharType* iter = aSource.BeginReading(); | |||
6575 | const CharType* end = aSource.EndReading(); | |||
6576 | while (iter != end) { | |||
6577 | CharType c = *iter; | |||
6578 | *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; | |||
6579 | ++iter; | |||
6580 | ++dest; | |||
6581 | } | |||
6582 | } | |||
6583 | ||||
6584 | /* static */ | |||
6585 | void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) { | |||
6586 | return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest); | |||
6587 | } | |||
6588 | ||||
6589 | /* static */ | |||
6590 | void nsContentUtils::ASCIIToLower(const nsACString& aSource, | |||
6591 | nsACString& aDest) { | |||
6592 | return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest); | |||
6593 | } | |||
6594 | ||||
6595 | template <typename StringType, typename CharType> | |||
6596 | void _ASCIIToUpperInSitu(StringType& aStr) { | |||
6597 | CharType* iter = aStr.BeginWriting(); | |||
6598 | CharType* end = aStr.EndWriting(); | |||
6599 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter && end" ")"); do { *((volatile int*)__null) = 6599; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6600 | ||||
6601 | while (iter != end) { | |||
6602 | CharType c = *iter; | |||
6603 | if (c >= 'a' && c <= 'z') { | |||
6604 | *iter = c + ('A' - 'a'); | |||
6605 | } | |||
6606 | ++iter; | |||
6607 | } | |||
6608 | } | |||
6609 | ||||
6610 | /* static */ | |||
6611 | void nsContentUtils::ASCIIToUpper(nsAString& aStr) { | |||
6612 | return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr); | |||
6613 | } | |||
6614 | ||||
6615 | /* static */ | |||
6616 | void nsContentUtils::ASCIIToUpper(nsACString& aStr) { | |||
6617 | return _ASCIIToUpperInSitu<nsACString, char>(aStr); | |||
6618 | } | |||
6619 | ||||
6620 | template <typename StringType, typename CharType> | |||
6621 | void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) { | |||
6622 | uint32_t len = aSource.Length(); | |||
6623 | aDest.SetLength(len); | |||
6624 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { *((volatile int*)__null) = 6624; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6625 | ||||
6626 | CharType* dest = aDest.BeginWriting(); | |||
6627 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")"); do { *((volatile int*)__null) = 6627; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6628 | ||||
6629 | const CharType* iter = aSource.BeginReading(); | |||
6630 | const CharType* end = aSource.EndReading(); | |||
6631 | while (iter != end) { | |||
6632 | CharType c = *iter; | |||
6633 | *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c; | |||
6634 | ++iter; | |||
6635 | ++dest; | |||
6636 | } | |||
6637 | } | |||
6638 | ||||
6639 | /* static */ | |||
6640 | void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) { | |||
6641 | return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest); | |||
6642 | } | |||
6643 | ||||
6644 | /* static */ | |||
6645 | void nsContentUtils::ASCIIToUpper(const nsACString& aSource, | |||
6646 | nsACString& aDest) { | |||
6647 | return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest); | |||
6648 | } | |||
6649 | ||||
6650 | /* static */ | |||
6651 | bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) { | |||
6652 | if (aAtom1 == aAtom2) { | |||
6653 | return true; | |||
6654 | } | |||
6655 | ||||
6656 | // If both are ascii lowercase already, we know that the slow comparison | |||
6657 | // below is going to return false. | |||
6658 | if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) { | |||
6659 | return false; | |||
6660 | } | |||
6661 | ||||
6662 | return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1), | |||
6663 | nsDependentAtomString(aAtom2)); | |||
6664 | } | |||
6665 | ||||
6666 | /* static */ | |||
6667 | bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, | |||
6668 | const nsAString& aStr2) { | |||
6669 | uint32_t len = aStr1.Length(); | |||
6670 | if (len != aStr2.Length()) { | |||
6671 | return false; | |||
6672 | } | |||
6673 | ||||
6674 | const char16_t* str1 = aStr1.BeginReading(); | |||
6675 | const char16_t* str2 = aStr2.BeginReading(); | |||
6676 | const char16_t* end = str1 + len; | |||
6677 | ||||
6678 | while (str1 < end) { | |||
6679 | char16_t c1 = *str1++; | |||
6680 | char16_t c2 = *str2++; | |||
6681 | ||||
6682 | // First check if any bits other than the 0x0020 differs | |||
6683 | if ((c1 ^ c2) & 0xffdf) { | |||
6684 | return false; | |||
6685 | } | |||
6686 | ||||
6687 | // We know they can only differ in the 0x0020 bit. | |||
6688 | // Likely the two chars are the same, so check that first | |||
6689 | if (c1 != c2) { | |||
6690 | // They do differ, but since it's only in the 0x0020 bit, check if it's | |||
6691 | // the same ascii char, but just differing in case | |||
6692 | char16_t c1Upper = c1 & 0xffdf; | |||
6693 | if (!('A' <= c1Upper && c1Upper <= 'Z')) { | |||
6694 | return false; | |||
6695 | } | |||
6696 | } | |||
6697 | } | |||
6698 | ||||
6699 | return true; | |||
6700 | } | |||
6701 | ||||
6702 | /* static */ | |||
6703 | bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) { | |||
6704 | const char16_t* iter = aStr.BeginReading(); | |||
6705 | const char16_t* end = aStr.EndReading(); | |||
6706 | while (iter != end) { | |||
6707 | char16_t c = *iter; | |||
6708 | if (c >= 'A' && c <= 'Z') { | |||
6709 | return true; | |||
6710 | } | |||
6711 | ++iter; | |||
6712 | } | |||
6713 | ||||
6714 | return false; | |||
6715 | } | |||
6716 | ||||
6717 | /* static */ | |||
6718 | nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() { | |||
6719 | if (!sSameOriginChecker) { | |||
6720 | sSameOriginChecker = new SameOriginCheckerImpl(); | |||
6721 | NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef(); | |||
6722 | } | |||
6723 | return sSameOriginChecker; | |||
6724 | } | |||
6725 | ||||
6726 | /* static */ | |||
6727 | nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel, | |||
6728 | nsIChannel* aNewChannel) { | |||
6729 | if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE; | |||
6730 | ||||
6731 | nsCOMPtr<nsIPrincipal> oldPrincipal; | |||
6732 | nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( | |||
6733 | aOldChannel, getter_AddRefs(oldPrincipal)); | |||
6734 | ||||
6735 | nsCOMPtr<nsIURI> newURI; | |||
6736 | aNewChannel->GetURI(getter_AddRefs(newURI)); | |||
6737 | nsCOMPtr<nsIURI> newOriginalURI; | |||
6738 | aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI)); | |||
6739 | ||||
6740 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6740); return NS_ERROR_UNEXPECTED; } } while (false); | |||
6741 | ||||
6742 | nsresult rv = oldPrincipal->CheckMayLoad(newURI, false); | |||
6743 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) { | |||
6744 | rv = oldPrincipal->CheckMayLoad(newOriginalURI, false); | |||
6745 | } | |||
6746 | ||||
6747 | return rv; | |||
6748 | } | |||
6749 | ||||
6750 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 6751; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 6751; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 6751 ; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 6751; __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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); 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((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr , table); return rv; } | |||
6751 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 6751; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 6751; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 6751 ; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 6751; __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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6751); 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((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr , table); return rv; } | |||
6752 | ||||
6753 | NS_IMETHODIMPnsresult | |||
6754 | SameOriginCheckerImpl::AsyncOnChannelRedirect( | |||
6755 | nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags, | |||
6756 | nsIAsyncVerifyRedirectCallback* cb) { | |||
6757 | 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel" ") (" "Redirecting to null channel?" ")"); do { *((volatile int *)__null) = 6757; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
6758 | ||||
6759 | nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel); | |||
6760 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
6761 | cb->OnRedirectVerifyCallback(NS_OK); | |||
6762 | } | |||
6763 | ||||
6764 | return rv; | |||
6765 | } | |||
6766 | ||||
6767 | NS_IMETHODIMPnsresult | |||
6768 | SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) { | |||
6769 | return QueryInterface(aIID, aResult); | |||
6770 | } | |||
6771 | ||||
6772 | /* static */ | |||
6773 | nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI, | |||
6774 | nsACString& aOrigin) { | |||
6775 | nsresult rv; | |||
6776 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "missing uri" ")"); do { *((volatile int*)__null) = 6776; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
6777 | ||||
6778 | // For Blob URI, the path is the URL of the owning page. | |||
6779 | if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) { | |||
6780 | nsAutoCString path; | |||
6781 | rv = aURI->GetPathQueryRef(path); | |||
6782 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6782); return rv; } } while (false); | |||
6783 | ||||
6784 | nsCOMPtr<nsIURI> uri; | |||
6785 | rv = NS_NewURI(getter_AddRefs(uri), path); | |||
6786 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
6787 | aOrigin.AssignLiteral("null"); | |||
6788 | return NS_OK; | |||
6789 | } | |||
6790 | ||||
6791 | if ( | |||
6792 | // Schemes in spec. https://url.spec.whatwg.org/#origin | |||
6793 | !uri->SchemeIs("http") && !uri->SchemeIs("https") && | |||
6794 | !uri->SchemeIs("file") && !uri->SchemeIs("resource") && | |||
6795 | // Our own schemes. | |||
6796 | !uri->SchemeIs("moz-extension")) { | |||
6797 | aOrigin.AssignLiteral("null"); | |||
6798 | return NS_OK; | |||
6799 | } | |||
6800 | ||||
6801 | return GetWebExposedOriginSerialization(uri, aOrigin); | |||
6802 | } | |||
6803 | ||||
6804 | nsAutoCString scheme; | |||
6805 | aURI->GetScheme(scheme); | |||
6806 | ||||
6807 | // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then | |||
6808 | // return "null" as the origin serialization. | |||
6809 | // We make an exception for "ftp" since we don't have a protocol handler | |||
6810 | // for this scheme | |||
6811 | uint32_t flags = 0; | |||
6812 | nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv); | |||
6813 | if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && | |||
6814 | NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags (scheme.get(), &flags))), 1)))) { | |||
6815 | if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) { | |||
6816 | aOrigin.AssignLiteral("null"); | |||
6817 | return NS_OK; | |||
6818 | } | |||
6819 | } | |||
6820 | ||||
6821 | aOrigin.Truncate(); | |||
6822 | ||||
6823 | nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI); | |||
6824 | NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(uri)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "uri" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6824); return NS_ERROR_UNEXPECTED; } } while (false); | |||
6825 | ||||
6826 | nsAutoCString host; | |||
6827 | rv = uri->GetAsciiHost(host); | |||
6828 | ||||
6829 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) { | |||
6830 | nsAutoCString userPass; | |||
6831 | uri->GetUserPass(userPass); | |||
6832 | ||||
6833 | nsAutoCString prePath; | |||
6834 | if (!userPass.IsEmpty()) { | |||
6835 | rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri); | |||
6836 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6836); return rv; } } while (false); | |||
6837 | } | |||
6838 | ||||
6839 | rv = uri->GetPrePath(prePath); | |||
6840 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6840); return rv; } } while (false); | |||
6841 | ||||
6842 | aOrigin = prePath; | |||
6843 | } else { | |||
6844 | aOrigin.AssignLiteral("null"); | |||
6845 | } | |||
6846 | ||||
6847 | return NS_OK; | |||
6848 | } | |||
6849 | ||||
6850 | /* static */ | |||
6851 | nsresult nsContentUtils::GetWebExposedOriginSerialization( | |||
6852 | nsIPrincipal* aPrincipal, nsAString& aOrigin) { | |||
6853 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ") (" "missing principal" ")"); do { *((volatile int*)__null ) = 6853; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
6854 | ||||
6855 | aOrigin.Truncate(); | |||
6856 | nsAutoCString webExposedOriginSerialization; | |||
6857 | ||||
6858 | nsresult rv = aPrincipal->GetWebExposedOriginSerialization( | |||
6859 | webExposedOriginSerialization); | |||
6860 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
6861 | webExposedOriginSerialization.AssignLiteral("null"); | |||
6862 | } | |||
6863 | ||||
6864 | CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin); | |||
6865 | return NS_OK; | |||
6866 | } | |||
6867 | ||||
6868 | /* static */ | |||
6869 | nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI, | |||
6870 | nsAString& aOrigin) { | |||
6871 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "missing uri" ")"); do { *((volatile int*)__null) = 6871; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
6872 | nsresult rv; | |||
6873 | ||||
6874 | #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) | |||
6875 | // Check if either URI has a special origin. | |||
6876 | nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = | |||
6877 | do_QueryInterface(aURI); | |||
6878 | if (uriWithSpecialOrigin) { | |||
6879 | nsCOMPtr<nsIURI> origin; | |||
6880 | rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin)); | |||
6881 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6881); return rv; } } while (false); | |||
6882 | ||||
6883 | return GetWebExposedOriginSerialization(origin, aOrigin); | |||
6884 | } | |||
6885 | #endif | |||
6886 | ||||
6887 | nsAutoCString webExposedOriginSerialization; | |||
6888 | rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization); | |||
6889 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6889); return rv; } } while (false); | |||
6890 | ||||
6891 | CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin); | |||
6892 | return NS_OK; | |||
6893 | } | |||
6894 | ||||
6895 | /* static */ | |||
6896 | bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, | |||
6897 | nsIChannel* aChannel, | |||
6898 | bool aAllowIfInheritsPrincipal) { | |||
6899 | nsCOMPtr<nsIURI> channelURI; | |||
6900 | nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); | |||
6901 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6901); return false; } } while (false); | |||
6902 | ||||
6903 | return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad (channelURI, aAllowIfInheritsPrincipal))), 1))) | |||
6904 | aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad (channelURI, aAllowIfInheritsPrincipal))), 1))); | |||
6905 | } | |||
6906 | ||||
6907 | /* static */ | |||
6908 | bool nsContentUtils::CanAccessNativeAnon() { | |||
6909 | return LegacyIsCallerChromeOrNativeCode(); | |||
6910 | } | |||
6911 | ||||
6912 | /* static */ | |||
6913 | nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted, | |||
6914 | Event* aSourceEvent, | |||
6915 | PresShell* aPresShell, bool aCtrl, | |||
6916 | bool aAlt, bool aShift, bool aMeta, | |||
6917 | uint16_t aInputSource, | |||
6918 | int16_t aButton) { | |||
6919 | NS_ENSURE_STATE(aTarget)do { if ((__builtin_expect(!!(!(aTarget)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTarget" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6919); return NS_ERROR_UNEXPECTED; } } while (false); | |||
6920 | Document* doc = aTarget->OwnerDoc(); | |||
6921 | nsPresContext* presContext = doc->GetPresContext(); | |||
6922 | ||||
6923 | RefPtr<XULCommandEvent> xulCommand = | |||
6924 | new XULCommandEvent(doc, presContext, nullptr); | |||
6925 | xulCommand->InitCommandEvent(u"command"_ns, true, true, | |||
6926 | nsGlobalWindowInner::Cast(doc->GetInnerWindow()), | |||
6927 | 0, aCtrl, aAlt, aShift, aMeta, aButton, | |||
6928 | aSourceEvent, aInputSource, IgnoreErrors()); | |||
6929 | ||||
6930 | if (aPresShell) { | |||
6931 | nsEventStatus status = nsEventStatus_eIgnore; | |||
6932 | return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status); | |||
6933 | } | |||
6934 | ||||
6935 | ErrorResult rv; | |||
6936 | aTarget->DispatchEvent(*xulCommand, rv); | |||
6937 | return rv.StealNSResult(); | |||
6938 | } | |||
6939 | ||||
6940 | // static | |||
6941 | nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native, | |||
6942 | nsWrapperCache* cache, const nsIID* aIID, | |||
6943 | JS::MutableHandle<JS::Value> vp, | |||
6944 | bool aAllowWrapping) { | |||
6945 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()" ")"); do { *((volatile int*)__null) = 6945; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6946 | ||||
6947 | if (!native) { | |||
6948 | vp.setNull(); | |||
6949 | ||||
6950 | return NS_OK; | |||
6951 | } | |||
6952 | ||||
6953 | JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp); | |||
6954 | if (wrapper) { | |||
6955 | return NS_OK; | |||
6956 | } | |||
6957 | ||||
6958 | NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(sXPConnect)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sXPConnect" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6958); return NS_ERROR_UNEXPECTED; } } while (false); | |||
6959 | ||||
6960 | if (!NS_IsMainThread()) { | |||
6961 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 6961); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 6961; __attribute__((nomerge)) ::abort(); } while (false); } while (false); | |||
6962 | } | |||
6963 | ||||
6964 | JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx)); | |||
6965 | nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID, | |||
6966 | aAllowWrapping, vp); | |||
6967 | return rv; | |||
6968 | } | |||
6969 | ||||
6970 | void nsContentUtils::StripNullChars(const nsAString& aInStr, | |||
6971 | nsAString& aOutStr) { | |||
6972 | // In common cases where we don't have nulls in the | |||
6973 | // string we can simple simply bypass the checking code. | |||
6974 | int32_t firstNullPos = aInStr.FindChar('\0'); | |||
6975 | if (firstNullPos == kNotFound) { | |||
6976 | aOutStr.Assign(aInStr); | |||
6977 | return; | |||
6978 | } | |||
6979 | ||||
6980 | aOutStr.SetCapacity(aInStr.Length() - 1); | |||
6981 | nsAString::const_iterator start, end; | |||
6982 | aInStr.BeginReading(start); | |||
6983 | aInStr.EndReading(end); | |||
6984 | while (start != end) { | |||
6985 | if (*start != '\0') aOutStr.Append(*start); | |||
6986 | ++start; | |||
6987 | } | |||
6988 | } | |||
6989 | ||||
6990 | struct ClassMatchingInfo { | |||
6991 | AtomArray mClasses; | |||
6992 | nsCaseTreatment mCaseTreatment; | |||
6993 | }; | |||
6994 | ||||
6995 | // static | |||
6996 | bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID, | |||
6997 | nsAtom* aAtom, void* aData) { | |||
6998 | // We can't match if there are no class names | |||
6999 | const nsAttrValue* classAttr = aElement->GetClasses(); | |||
7000 | if (!classAttr) { | |||
7001 | return false; | |||
7002 | } | |||
7003 | ||||
7004 | // need to match *all* of the classes | |||
7005 | ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData); | |||
7006 | uint32_t length = info->mClasses.Length(); | |||
7007 | if (!length) { | |||
7008 | // If we actually had no classes, don't match. | |||
7009 | return false; | |||
7010 | } | |||
7011 | uint32_t i; | |||
7012 | for (i = 0; i < length; ++i) { | |||
7013 | if (!classAttr->Contains(info->mClasses[i], info->mCaseTreatment)) { | |||
7014 | return false; | |||
7015 | } | |||
7016 | } | |||
7017 | ||||
7018 | return true; | |||
7019 | } | |||
7020 | ||||
7021 | // static | |||
7022 | void nsContentUtils::DestroyClassNameArray(void* aData) { | |||
7023 | ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData); | |||
7024 | delete info; | |||
7025 | } | |||
7026 | ||||
7027 | // static | |||
7028 | void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode, | |||
7029 | const nsString* aClasses) { | |||
7030 | nsAttrValue attrValue; | |||
7031 | attrValue.ParseAtomArray(*aClasses); | |||
7032 | // nsAttrValue::Equals is sensitive to order, so we'll send an array | |||
7033 | auto* info = new ClassMatchingInfo; | |||
7034 | if (attrValue.Type() == nsAttrValue::eAtomArray) { | |||
7035 | info->mClasses = attrValue.GetAtomArrayValue()->mArray.Clone(); | |||
7036 | } else if (attrValue.Type() == nsAttrValue::eAtom) { | |||
7037 | info->mClasses.AppendElement(attrValue.GetAtomValue()); | |||
7038 | } | |||
7039 | ||||
7040 | info->mCaseTreatment = | |||
7041 | aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks | |||
7042 | ? eIgnoreCase | |||
7043 | : eCaseMatters; | |||
7044 | return info; | |||
7045 | } | |||
7046 | ||||
7047 | bool nsContentUtils::HasScrollgrab(nsIContent* aContent) { | |||
7048 | // If we ever standardize this feature we'll want to hook this up properly | |||
7049 | // again. For now we're removing all the DOM-side code related to it but | |||
7050 | // leaving the layout and APZ handling for it in place. | |||
7051 | return false; | |||
7052 | } | |||
7053 | ||||
7054 | void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) { | |||
7055 | if (!aWindow) { | |||
7056 | return; | |||
7057 | } | |||
7058 | ||||
7059 | // Note that because FlushPendingNotifications flushes parents, this | |||
7060 | // is O(N^2) in docshell tree depth. However, the docshell tree is | |||
7061 | // usually pretty shallow. | |||
7062 | ||||
7063 | if (RefPtr<Document> doc = aWindow->GetDoc()) { | |||
7064 | doc->FlushPendingNotifications(FlushType::Layout); | |||
7065 | } | |||
7066 | ||||
7067 | if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) { | |||
7068 | int32_t i = 0, i_end; | |||
7069 | docShell->GetInProcessChildCount(&i_end); | |||
7070 | for (; i < i_end; ++i) { | |||
7071 | nsCOMPtr<nsIDocShellTreeItem> item; | |||
7072 | if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK && | |||
7073 | item) { | |||
7074 | if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) { | |||
7075 | FlushLayoutForTree(win); | |||
7076 | } | |||
7077 | } | |||
7078 | } | |||
7079 | } | |||
7080 | } | |||
7081 | ||||
7082 | void nsContentUtils::RemoveNewlines(nsString& aString) { aString.StripCRLF(); } | |||
7083 | ||||
7084 | void nsContentUtils::PlatformToDOMLineBreaks(nsString& aString) { | |||
7085 | if (!PlatformToDOMLineBreaks(aString, fallible)) { | |||
7086 | aString.AllocFailed(aString.Length()); | |||
7087 | } | |||
7088 | } | |||
7089 | ||||
7090 | bool nsContentUtils::PlatformToDOMLineBreaks(nsString& aString, | |||
7091 | const fallible_t& aFallible) { | |||
7092 | if (aString.FindChar(char16_t('\r')) != -1) { | |||
7093 | // Windows linebreaks: Map CRLF to LF: | |||
7094 | if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) { | |||
7095 | return false; | |||
7096 | } | |||
7097 | ||||
7098 | // Mac linebreaks: Map any remaining CR to LF: | |||
7099 | if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) { | |||
7100 | return false; | |||
7101 | } | |||
7102 | } | |||
7103 | ||||
7104 | return true; | |||
7105 | } | |||
7106 | ||||
7107 | already_AddRefed<nsContentList> nsContentUtils::GetElementsByClassName( | |||
7108 | nsINode* aRootNode, const nsAString& aClasses) { | |||
7109 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") (" "Must have root node" ")"); do { *((volatile int*)__null) = 7109 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
7110 | ||||
7111 | return GetFuncStringContentList<nsCacheableFuncStringHTMLCollection>( | |||
7112 | aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo, | |||
7113 | aClasses); | |||
7114 | } | |||
7115 | ||||
7116 | PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) { | |||
7117 | const Document* doc = aDocument; | |||
7118 | Document* displayDoc = doc->GetDisplayDocument(); | |||
7119 | if (displayDoc) { | |||
7120 | doc = displayDoc; | |||
7121 | } | |||
7122 | ||||
7123 | PresShell* presShell = doc->GetPresShell(); | |||
7124 | if (presShell) { | |||
7125 | return presShell; | |||
7126 | } | |||
7127 | ||||
7128 | nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell(); | |||
7129 | while (docShellTreeItem) { | |||
7130 | // We may be in a display:none subdocument, or we may not have a presshell | |||
7131 | // created yet. | |||
7132 | // Walk the docshell tree to find the nearest container that has a | |||
7133 | // presshell, and return that. | |||
7134 | nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem); | |||
7135 | if (PresShell* presShell = docShell->GetPresShell()) { | |||
7136 | return presShell; | |||
7137 | } | |||
7138 | nsCOMPtr<nsIDocShellTreeItem> parent; | |||
7139 | docShellTreeItem->GetInProcessParent(getter_AddRefs(parent)); | |||
7140 | docShellTreeItem = parent; | |||
7141 | } | |||
7142 | ||||
7143 | return nullptr; | |||
7144 | } | |||
7145 | ||||
7146 | /* static */ | |||
7147 | nsPresContext* nsContentUtils::FindPresContextForDocument( | |||
7148 | const Document* aDocument) { | |||
7149 | if (PresShell* presShell = FindPresShellForDocument(aDocument)) { | |||
7150 | return presShell->GetPresContext(); | |||
7151 | } | |||
7152 | return nullptr; | |||
7153 | } | |||
7154 | ||||
7155 | nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) { | |||
7156 | PresShell* presShell = FindPresShellForDocument(aDocument); | |||
7157 | if (!presShell) { | |||
7158 | return nullptr; | |||
7159 | } | |||
7160 | nsViewManager* vm = presShell->GetViewManager(); | |||
7161 | if (!vm) { | |||
7162 | return nullptr; | |||
7163 | } | |||
7164 | nsView* rootView = vm->GetRootView(); | |||
7165 | if (!rootView) { | |||
7166 | return nullptr; | |||
7167 | } | |||
7168 | nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView); | |||
7169 | if (!displayRoot) { | |||
7170 | return nullptr; | |||
7171 | } | |||
7172 | return displayRoot->GetNearestWidget(nullptr); | |||
7173 | } | |||
7174 | ||||
7175 | nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) { | |||
7176 | nsIFrame* frame = aContent->GetPrimaryFrame(); | |||
7177 | if (frame) { | |||
7178 | frame = nsLayoutUtils::GetDisplayRootFrame(frame); | |||
7179 | ||||
7180 | nsView* view = frame->GetView(); | |||
7181 | if (view) { | |||
7182 | return view->GetWidget(); | |||
7183 | } | |||
7184 | } | |||
7185 | ||||
7186 | return nullptr; | |||
7187 | } | |||
7188 | ||||
7189 | WindowRenderer* nsContentUtils::WindowRendererForContent( | |||
7190 | const nsIContent* aContent) { | |||
7191 | nsIWidget* widget = nsContentUtils::WidgetForContent(aContent); | |||
7192 | if (widget) { | |||
7193 | return widget->GetWindowRenderer(); | |||
7194 | } | |||
7195 | ||||
7196 | return nullptr; | |||
7197 | } | |||
7198 | ||||
7199 | WindowRenderer* nsContentUtils::WindowRendererForDocument( | |||
7200 | const Document* aDoc) { | |||
7201 | nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc); | |||
7202 | if (widget) { | |||
7203 | return widget->GetWindowRenderer(); | |||
7204 | } | |||
7205 | ||||
7206 | return nullptr; | |||
7207 | } | |||
7208 | ||||
7209 | bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) { | |||
7210 | if (!aPrincipal) { | |||
7211 | return false; | |||
7212 | } | |||
7213 | ||||
7214 | if (aPrincipal->IsSystemPrincipal()) { | |||
7215 | return true; | |||
7216 | } | |||
7217 | ||||
7218 | return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns); | |||
7219 | } | |||
7220 | ||||
7221 | bool nsContentUtils::IsPDFJSEnabled() { | |||
7222 | nsCOMPtr<nsIStreamConverter> conv = do_CreateInstance( | |||
7223 | "@mozilla.org/streamconv;1?from=application/pdf&to=text/html"); | |||
7224 | return conv; | |||
7225 | } | |||
7226 | ||||
7227 | bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) { | |||
7228 | if (!aPrincipal || !aPrincipal->SchemeIs("resource")) { | |||
7229 | return false; | |||
7230 | } | |||
7231 | nsAutoCString spec; | |||
7232 | nsresult rv = aPrincipal->GetAsciiSpec(spec); | |||
7233 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7233); return false; } } while (false); | |||
7234 | return spec.EqualsLiteral("resource://pdf.js/web/viewer.html"); | |||
7235 | } | |||
7236 | ||||
7237 | bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) { | |||
7238 | nsIPrincipal* principal = SubjectPrincipal(aCx); | |||
7239 | return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal)); | |||
7240 | } | |||
7241 | ||||
7242 | bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx, | |||
7243 | JSObject* aGlobal) { | |||
7244 | nsIPrincipal* principal = SubjectPrincipal(aCx); | |||
7245 | return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, | |||
7246 | aGlobal) || | |||
7247 | (principal && principal->GetIsAddonOrExpandedAddonPrincipal()); | |||
7248 | } | |||
7249 | ||||
7250 | already_AddRefed<nsIDocumentLoaderFactory> | |||
7251 | nsContentUtils::FindInternalDocumentViewer(const nsACString& aType, | |||
7252 | DocumentViewerType* aLoaderType) { | |||
7253 | if (aLoaderType) { | |||
7254 | *aLoaderType = TYPE_UNSUPPORTED; | |||
7255 | } | |||
7256 | ||||
7257 | // one helper factory, please | |||
7258 | nsCOMPtr<nsICategoryManager> catMan( | |||
7259 | do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1")); | |||
7260 | if (!catMan) return nullptr; | |||
7261 | ||||
7262 | nsCOMPtr<nsIDocumentLoaderFactory> docFactory; | |||
7263 | ||||
7264 | nsCString contractID; | |||
7265 | nsresult rv = | |||
7266 | catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID); | |||
7267 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
7268 | docFactory = do_GetService(contractID.get()); | |||
7269 | if (docFactory && aLoaderType) { | |||
7270 | if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1")) | |||
7271 | *aLoaderType = TYPE_CONTENT; | |||
7272 | else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID"@mozilla.org/content/plugin/document-loader-factory;1")) | |||
7273 | *aLoaderType = TYPE_FALLBACK; | |||
7274 | else | |||
7275 | *aLoaderType = TYPE_UNKNOWN; | |||
7276 | } | |||
7277 | return docFactory.forget(); | |||
7278 | } | |||
7279 | ||||
7280 | // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's | |||
7281 | // another type which we may dynamically support, such as `text/*` types or | |||
7282 | // video document types. These types are all backed by the nsContentDLF. | |||
7283 | if (IsPlainTextType(aType) || | |||
7284 | DecoderTraits::IsSupportedInVideoDocument(aType)) { | |||
7285 | docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"); | |||
7286 | if (docFactory && aLoaderType) { | |||
7287 | *aLoaderType = TYPE_CONTENT; | |||
7288 | } | |||
7289 | return docFactory.forget(); | |||
7290 | } | |||
7291 | ||||
7292 | return nullptr; | |||
7293 | } | |||
7294 | ||||
7295 | static void ReportPatternCompileFailure(nsAString& aPattern, | |||
7296 | const JS::RegExpFlags& aFlags, | |||
7297 | const Document* aDocument, | |||
7298 | JS::MutableHandle<JS::Value> error, | |||
7299 | JSContext* cx) { | |||
7300 | AutoTArray<nsString, 3> strings; | |||
7301 | ||||
7302 | strings.AppendElement(aPattern); | |||
7303 | ||||
7304 | std::stringstream flag_ss; | |||
7305 | flag_ss << aFlags; | |||
7306 | nsString* flagstr = strings.AppendElement(); | |||
7307 | AppendUTF8toUTF16(flag_ss.str(), *flagstr); | |||
7308 | ||||
7309 | JS::AutoSaveExceptionState savedExc(cx); | |||
7310 | JS::Rooted<JSObject*> exnObj(cx, &error.toObject()); | |||
7311 | JS::Rooted<JS::Value> messageVal(cx); | |||
7312 | if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) { | |||
7313 | return; | |||
7314 | } | |||
7315 | JS::Rooted<JSString*> messageStr(cx, messageVal.toString()); | |||
7316 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr" ")"); do { *((volatile int*)__null) = 7316; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7317 | if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) { | |||
7318 | return; | |||
7319 | } | |||
7320 | ||||
7321 | nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns, | |||
7322 | aDocument, nsContentUtils::eDOM_PROPERTIES, | |||
7323 | "PatternAttributeCompileFailurev2", strings); | |||
7324 | savedExc.drop(); | |||
7325 | } | |||
7326 | ||||
7327 | // static | |||
7328 | Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue, | |||
7329 | nsString&& aPattern, | |||
7330 | const Document* aDocument, | |||
7331 | bool aHasMultiple, | |||
7332 | JS::RegExpFlags aFlags) { | |||
7333 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7333); MOZ_PretendNoReturn(); } } while (0); | |||
7334 | ||||
7335 | // The fact that we're using a JS regexp under the hood should not be visible | |||
7336 | // to things like window onerror handlers, so we don't initialize our JSAPI | |||
7337 | // with the document's window (which may not exist anyway). | |||
7338 | AutoJSAPI jsapi; | |||
7339 | jsapi.Init(); | |||
7340 | JSContext* cx = jsapi.cx(); | |||
7341 | AutoDisableJSInterruptCallback disabler(cx); | |||
7342 | ||||
7343 | // We can use the junk scope here, because we're just using it for regexp | |||
7344 | // evaluation, not actual script execution, and we disable statics so that the | |||
7345 | // evaluation does not interact with the execution global. | |||
7346 | JSAutoRealm ar(cx, xpc::PrivilegedJunkScope()); | |||
7347 | ||||
7348 | // Check if the pattern by itself is valid first, and not that it only becomes | |||
7349 | // valid once we add ^(?: and )$. | |||
7350 | JS::Rooted<JS::Value> error(cx); | |||
7351 | if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(), | |||
7352 | aFlags, &error)) { | |||
7353 | return Nothing(); | |||
7354 | } | |||
7355 | ||||
7356 | if (!error.isUndefined()) { | |||
7357 | ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx); | |||
7358 | return Some(true); | |||
7359 | } | |||
7360 | ||||
7361 | // The pattern has to match the entire value. | |||
7362 | aPattern.InsertLiteral(u"^(?:", 0); | |||
7363 | aPattern.AppendLiteral(")$"); | |||
7364 | ||||
7365 | JS::Rooted<JSObject*> re( | |||
7366 | cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(), | |||
7367 | aFlags)); | |||
7368 | if (!re) { | |||
7369 | return Nothing(); | |||
7370 | } | |||
7371 | ||||
7372 | JS::Rooted<JS::Value> rval(cx, JS::NullValue()); | |||
7373 | if (!aHasMultiple) { | |||
7374 | size_t idx = 0; | |||
7375 | if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(), | |||
7376 | aValue.Length(), &idx, true, &rval)) { | |||
7377 | return Nothing(); | |||
7378 | } | |||
7379 | return Some(!rval.isNull()); | |||
7380 | } | |||
7381 | ||||
7382 | HTMLSplitOnSpacesTokenizer tokenizer(aValue, ','); | |||
7383 | while (tokenizer.hasMoreTokens()) { | |||
7384 | const nsAString& value = tokenizer.nextToken(); | |||
7385 | size_t idx = 0; | |||
7386 | if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(), | |||
7387 | value.Length(), &idx, true, &rval)) { | |||
7388 | return Nothing(); | |||
7389 | } | |||
7390 | if (rval.isNull()) { | |||
7391 | return Some(false); | |||
7392 | } | |||
7393 | } | |||
7394 | return Some(true); | |||
7395 | } | |||
7396 | ||||
7397 | // static | |||
7398 | nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI, | |||
7399 | bool* aResult) { | |||
7400 | // Note: about:blank URIs do NOT inherit the security context from the | |||
7401 | // current document, which is what this function tests for... | |||
7402 | return NS_URIChainHasFlags( | |||
7403 | aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult); | |||
7404 | } | |||
7405 | ||||
7406 | // static | |||
7407 | bool nsContentUtils::ChannelShouldInheritPrincipal( | |||
7408 | nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank, | |||
7409 | bool aForceInherit) { | |||
7410 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Can not check inheritance without a principal" ")"); do { *((volatile int*)__null) = 7411; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) | |||
7411 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal" ") (" "Can not check inheritance without a principal" ")"); do { *((volatile int*)__null) = 7411; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); | |||
7412 | ||||
7413 | // Only tell the channel to inherit if it can't provide its own security | |||
7414 | // context. | |||
7415 | // | |||
7416 | // XXX: If this is ever changed, check all callers for what owners | |||
7417 | // they're passing in. In particular, see the code and | |||
7418 | // comments in nsDocShell::LoadURI where we fall back on | |||
7419 | // inheriting the owner if called from chrome. That would be | |||
7420 | // very wrong if this code changed anything but channels that | |||
7421 | // can't provide their own security context! | |||
7422 | // | |||
7423 | // If aForceInherit is true, we will inherit, even for a channel that | |||
7424 | // can provide its own security context. This is used for srcdoc loads. | |||
7425 | bool inherit = aForceInherit; | |||
7426 | if (!inherit) { | |||
7427 | bool uriInherits; | |||
7428 | // We expect URIInheritsSecurityContext to return success for an | |||
7429 | // about:blank URI, so don't call NS_IsAboutBlank() if this call fails. | |||
7430 | // This condition needs to match the one in nsDocShell::InternalLoad where | |||
7431 | // we're checking for things that will use the owner. | |||
7432 | inherit = | |||
7433 | (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext (aURI, &uriInherits))), 1))) && | |||
7434 | (uriInherits || (aInheritForAboutBlank && | |||
7435 | NS_IsAboutBlankAllowQueryAndFragment(aURI)))) || | |||
7436 | // | |||
7437 | // file: uri special-casing | |||
7438 | // | |||
7439 | // If this is a file: load opened from another file: then it may need | |||
7440 | // to inherit the owner from the referrer so they can script each other. | |||
7441 | // If we don't set the owner explicitly then each file: gets an owner | |||
7442 | // based on its own codebase later. | |||
7443 | // | |||
7444 | (URIIsLocalFile(aURI) && | |||
7445 | NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal ->CheckMayLoad(aURI, false))), 1))) && | |||
7446 | // One more check here. CheckMayLoad will always return true for the | |||
7447 | // system principal, but we do NOT want to inherit in that case. | |||
7448 | !aLoadingPrincipal->IsSystemPrincipal()); | |||
7449 | } | |||
7450 | return inherit; | |||
7451 | } | |||
7452 | ||||
7453 | /* static */ | |||
7454 | bool nsContentUtils::IsCutCopyAllowed(Document* aDocument, | |||
7455 | nsIPrincipal& aSubjectPrincipal) { | |||
7456 | if (StaticPrefs::dom_allow_cut_copy() && aDocument && | |||
7457 | aDocument->HasValidTransientUserGestureActivation()) { | |||
7458 | return true; | |||
7459 | } | |||
7460 | ||||
7461 | return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite); | |||
7462 | } | |||
7463 | ||||
7464 | /* static */ | |||
7465 | bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) { | |||
7466 | if (!aDoc1 || !aDoc2) { | |||
7467 | return false; | |||
7468 | } | |||
7469 | bool principalsEqual = false; | |||
7470 | aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual); | |||
7471 | return principalsEqual; | |||
7472 | } | |||
7473 | ||||
7474 | /* static */ | |||
7475 | void nsContentUtils::FireMutationEventsForDirectParsing( | |||
7476 | Document* aDoc, nsIContent* aDest, int32_t aOldChildCount) { | |||
7477 | // Fire mutation events. Optimize for the case when there are no listeners | |||
7478 | int32_t newChildCount = aDest->GetChildCount(); | |||
7479 | if (newChildCount && nsContentUtils::HasMutationListeners( | |||
7480 | aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED0x02)) { | |||
7481 | AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes; | |||
7482 | NS_ASSERTION(newChildCount - aOldChildCount >= 0,do { if (!(newChildCount - aOldChildCount >= 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "What, some unexpected dom mutation has happened?" , "newChildCount - aOldChildCount >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7483); MOZ_PretendNoReturn(); } } while (0) | |||
7483 | "What, some unexpected dom mutation has happened?")do { if (!(newChildCount - aOldChildCount >= 0)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "What, some unexpected dom mutation has happened?" , "newChildCount - aOldChildCount >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7483); MOZ_PretendNoReturn(); } } while (0); | |||
7484 | childNodes.SetCapacity(newChildCount - aOldChildCount); | |||
7485 | for (nsIContent* child = aDest->GetFirstChild(); child; | |||
7486 | child = child->GetNextSibling()) { | |||
7487 | childNodes.AppendElement(child); | |||
7488 | } | |||
7489 | FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes); | |||
7490 | } | |||
7491 | } | |||
7492 | ||||
7493 | /* static */ | |||
7494 | const Document* nsContentUtils::GetInProcessSubtreeRootDocument( | |||
7495 | const Document* aDoc) { | |||
7496 | if (!aDoc) { | |||
7497 | return nullptr; | |||
7498 | } | |||
7499 | const Document* doc = aDoc; | |||
7500 | while (doc->GetInProcessParentDocument()) { | |||
7501 | doc = doc->GetInProcessParentDocument(); | |||
7502 | } | |||
7503 | return doc; | |||
7504 | } | |||
7505 | ||||
7506 | // static | |||
7507 | int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame, | |||
7508 | int32_t aOffset) { | |||
7509 | // The structure of the anonymous frames within a text control frame is | |||
7510 | // an optional block frame, followed by an optional br frame. | |||
7511 | ||||
7512 | // If the offset frame has a child, then this frame is the block which | |||
7513 | // has the text frames (containing the content) as its children. This will | |||
7514 | // be the case if we click to the right of any of the text frames, or at the | |||
7515 | // bottom of the text area. | |||
7516 | nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild(); | |||
7517 | if (firstChild) { | |||
7518 | // In this case, the passed-in offset is incorrect, and we want the length | |||
7519 | // of the entire content in the text control frame. | |||
7520 | return firstChild->GetContent()->Length(); | |||
7521 | } | |||
7522 | ||||
7523 | if (aOffsetFrame->GetPrevSibling() && !aOffsetFrame->GetNextSibling()) { | |||
7524 | // In this case, we're actually within the last frame, which is a br | |||
7525 | // frame. Our offset should therefore be the length of the first child of | |||
7526 | // our parent. | |||
7527 | int32_t aOutOffset = aOffsetFrame->GetParent() | |||
7528 | ->PrincipalChildList() | |||
7529 | .FirstChild() | |||
7530 | ->GetContent() | |||
7531 | ->Length(); | |||
7532 | return aOutOffset; | |||
7533 | } | |||
7534 | ||||
7535 | // Otherwise, we're within one of the text frames, in which case our offset | |||
7536 | // has already been correctly calculated. | |||
7537 | return aOffset; | |||
7538 | } | |||
7539 | ||||
7540 | // static | |||
7541 | bool nsContentUtils::IsPointInSelection( | |||
7542 | const mozilla::dom::Selection& aSelection, const nsINode& aNode, | |||
7543 | const uint32_t aOffset, const bool aAllowCrossShadowBoundary) { | |||
7544 | const bool selectionIsCollapsed = | |||
7545 | !aAllowCrossShadowBoundary | |||
7546 | ? aSelection.IsCollapsed() | |||
7547 | : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed(); | |||
7548 | if (selectionIsCollapsed) { | |||
7549 | return false; | |||
7550 | } | |||
7551 | ||||
7552 | const uint32_t rangeCount = aSelection.RangeCount(); | |||
7553 | for (const uint32_t i : IntegerRange(rangeCount)) { | |||
7554 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount" ")"); do { *((volatile int*)__null) = 7554; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7555 | RefPtr<const nsRange> range = aSelection.GetRangeAt(i); | |||
7556 | if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7556)) { | |||
7557 | // Don't bail yet, iterate through them all | |||
7558 | continue; | |||
7559 | } | |||
7560 | ||||
7561 | // Done when we find a range that we are in | |||
7562 | if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(), | |||
7563 | aAllowCrossShadowBoundary)) { | |||
7564 | return true; | |||
7565 | } | |||
7566 | } | |||
7567 | ||||
7568 | return false; | |||
7569 | } | |||
7570 | ||||
7571 | // static | |||
7572 | void nsContentUtils::GetSelectionInTextControl(Selection* aSelection, | |||
7573 | Element* aRoot, | |||
7574 | uint32_t& aOutStartOffset, | |||
7575 | uint32_t& aOutEndOffset) { | |||
7576 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSelection && aRoot" ")"); do { *((volatile int*)__null) = 7576; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7577 | ||||
7578 | // We don't care which end of this selection is anchor and which is focus. In | |||
7579 | // fact, we explicitly want to know which is the _start_ and which is the | |||
7580 | // _end_, not anchor vs focus. | |||
7581 | const nsRange* range = aSelection->GetAnchorFocusRange(); | |||
7582 | if (!range) { | |||
7583 | // Nothing selected | |||
7584 | aOutStartOffset = aOutEndOffset = 0; | |||
7585 | return; | |||
7586 | } | |||
7587 | ||||
7588 | // All the node pointers here are raw pointers for performance. We shouldn't | |||
7589 | // be doing anything in this function that invalidates the node tree. | |||
7590 | nsINode* startContainer = range->GetStartContainer(); | |||
7591 | uint32_t startOffset = range->StartOffset(); | |||
7592 | nsINode* endContainer = range->GetEndContainer(); | |||
7593 | uint32_t endOffset = range->EndOffset(); | |||
7594 | ||||
7595 | // We have at most two children, consisting of an optional text node followed | |||
7596 | // by an optional <br>. | |||
7597 | NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children")do { if (!(aRoot->GetChildCount() <= 2)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Unexpected children", "aRoot->GetChildCount() <= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7597); MOZ_PretendNoReturn(); } } while (0); | |||
7598 | nsIContent* firstChild = aRoot->GetFirstChild(); | |||
7599 | #ifdef DEBUG1 | |||
7600 | nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild(); | |||
7601 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7603); MOZ_PretendNoReturn(); } } while (0) | |||
7602 | startContainer == lastChild,do { if (!(startContainer == aRoot || startContainer == firstChild || startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7603); MOZ_PretendNoReturn(); } } while (0) | |||
7603 | "Unexpected startContainer")do { if (!(startContainer == aRoot || startContainer == firstChild || startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7603); MOZ_PretendNoReturn(); } } while (0); | |||
7604 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7606); MOZ_PretendNoReturn(); } } while (0) | |||
7605 | endContainer == lastChild,do { if (!(endContainer == aRoot || endContainer == firstChild || endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7606); MOZ_PretendNoReturn(); } } while (0) | |||
7606 | "Unexpected endContainer")do { if (!(endContainer == aRoot || endContainer == firstChild || endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7606); MOZ_PretendNoReturn(); } } while (0); | |||
7607 | // firstChild is either text or a <br> (hence an element). | |||
7608 | 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()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()" ")"); do { *((volatile int*)__null) = 7608; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
7609 | #endif | |||
7610 | if (!firstChild || firstChild->IsElement()) { | |||
7611 | // No text node, so everything is 0 | |||
7612 | startOffset = endOffset = 0; | |||
7613 | } else { | |||
7614 | // First child is text. If the start/end is already in the text node, | |||
7615 | // or the start of the root node, no change needed. If it's in the root | |||
7616 | // node but not the start, or in the trailing <br>, we need to set the | |||
7617 | // offset to the end. | |||
7618 | if ((startContainer == aRoot && startOffset != 0) || | |||
7619 | (startContainer != aRoot && startContainer != firstChild)) { | |||
7620 | startOffset = firstChild->Length(); | |||
7621 | } | |||
7622 | if ((endContainer == aRoot && endOffset != 0) || | |||
7623 | (endContainer != aRoot && endContainer != firstChild)) { | |||
7624 | endOffset = firstChild->Length(); | |||
7625 | } | |||
7626 | } | |||
7627 | ||||
7628 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 7628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startOffset <= endOffset" ")"); do { *((volatile int*)__null) = 7628; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7629 | aOutStartOffset = startOffset; | |||
7630 | aOutEndOffset = endOffset; | |||
7631 | } | |||
7632 | ||||
7633 | // static | |||
7634 | HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) { | |||
7635 | if (!aPresContext) { | |||
7636 | return nullptr; | |||
7637 | } | |||
7638 | return GetHTMLEditor(aPresContext->GetDocShell()); | |||
7639 | } | |||
7640 | ||||
7641 | // static | |||
7642 | HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) { | |||
7643 | bool isEditable; | |||
7644 | if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable (&isEditable))), 0))) || | |||
7645 | !isEditable) { | |||
7646 | return nullptr; | |||
7647 | } | |||
7648 | return aDocShell->GetHTMLEditor(); | |||
7649 | } | |||
7650 | ||||
7651 | // static | |||
7652 | EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) { | |||
7653 | if (!aPresContext) { | |||
7654 | return nullptr; | |||
7655 | } | |||
7656 | ||||
7657 | return GetActiveEditor(aPresContext->Document()->GetWindow()); | |||
7658 | } | |||
7659 | ||||
7660 | // static | |||
7661 | EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) { | |||
7662 | if (!aWindow || !aWindow->GetExtantDoc()) { | |||
7663 | return nullptr; | |||
7664 | } | |||
7665 | ||||
7666 | // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor | |||
7667 | // handles all events. I.e., it's focused editor in this case. | |||
7668 | if (aWindow->GetExtantDoc()->IsInDesignMode()) { | |||
7669 | return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell())); | |||
7670 | } | |||
7671 | ||||
7672 | // If focused element is associated with TextEditor, it must be <input> | |||
7673 | // element or <textarea> element. Let's return it even if it's in a | |||
7674 | // contenteditable element. | |||
7675 | nsCOMPtr<nsPIDOMWindowOuter> focusedWindow; | |||
7676 | if (Element* focusedElement = nsFocusManager::GetFocusedDescendant( | |||
7677 | aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow, | |||
7678 | getter_AddRefs(focusedWindow))) { | |||
7679 | if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) { | |||
7680 | return textEditor; | |||
7681 | } | |||
7682 | } | |||
7683 | ||||
7684 | // Otherwise, HTMLEditor may handle inputs even non-editable element has | |||
7685 | // focus or nobody has focus. | |||
7686 | return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell())); | |||
7687 | } | |||
7688 | ||||
7689 | // static | |||
7690 | TextEditor* nsContentUtils::GetTextEditorFromAnonymousNodeWithoutCreation( | |||
7691 | const nsIContent* aAnonymousContent) { | |||
7692 | if (!aAnonymousContent) { | |||
7693 | return nullptr; | |||
7694 | } | |||
7695 | nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent(); | |||
7696 | if (!parent || parent == aAnonymousContent) { | |||
7697 | return nullptr; | |||
7698 | } | |||
7699 | if (HTMLInputElement* inputElement = | |||
7700 | HTMLInputElement::FromNodeOrNull(parent)) { | |||
7701 | return inputElement->GetTextEditorWithoutCreation(); | |||
7702 | } | |||
7703 | if (HTMLTextAreaElement* textareaElement = | |||
7704 | HTMLTextAreaElement::FromNodeOrNull(parent)) { | |||
7705 | return textareaElement->GetTextEditorWithoutCreation(); | |||
7706 | } | |||
7707 | return nullptr; | |||
7708 | } | |||
7709 | ||||
7710 | // static | |||
7711 | bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) { | |||
7712 | while (aNode) { | |||
7713 | if (aNode->IsEditable()) { | |||
7714 | return true; | |||
7715 | } | |||
7716 | aNode = aNode->GetParent(); | |||
7717 | } | |||
7718 | return false; | |||
7719 | } | |||
7720 | ||||
7721 | // static | |||
7722 | bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader, | |||
7723 | const nsACString& aValue) { | |||
7724 | if (IsForbiddenSystemRequestHeader(aHeader)) { | |||
7725 | return true; | |||
7726 | } | |||
7727 | ||||
7728 | if ((nsContentUtils::IsOverrideMethodHeader(aHeader) && | |||
7729 | nsContentUtils::ContainsForbiddenMethod(aValue))) { | |||
7730 | return true; | |||
7731 | } | |||
7732 | ||||
7733 | if (StringBeginsWith(aHeader, "proxy-"_ns, | |||
7734 | nsCaseInsensitiveCStringComparator) || | |||
7735 | StringBeginsWith(aHeader, "sec-"_ns, | |||
7736 | nsCaseInsensitiveCStringComparator)) { | |||
7737 | return true; | |||
7738 | } | |||
7739 | ||||
7740 | return false; | |||
7741 | } | |||
7742 | ||||
7743 | // static | |||
7744 | bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) { | |||
7745 | static const char* kInvalidHeaders[] = {"accept-charset", | |||
7746 | "accept-encoding", | |||
7747 | "access-control-request-headers", | |||
7748 | "access-control-request-method", | |||
7749 | "connection", | |||
7750 | "content-length", | |||
7751 | "cookie", | |||
7752 | "cookie2", | |||
7753 | "date", | |||
7754 | "dnt", | |||
7755 | "expect", | |||
7756 | "host", | |||
7757 | "keep-alive", | |||
7758 | "origin", | |||
7759 | "referer", | |||
7760 | "set-cookie", | |||
7761 | "te", | |||
7762 | "trailer", | |||
7763 | "transfer-encoding", | |||
7764 | "upgrade", | |||
7765 | "via"}; | |||
7766 | for (auto& kInvalidHeader : kInvalidHeaders) { | |||
7767 | if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) { | |||
7768 | return true; | |||
7769 | } | |||
7770 | } | |||
7771 | return false; | |||
7772 | } | |||
7773 | ||||
7774 | // static | |||
7775 | bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) { | |||
7776 | return (aHeader.LowerCaseEqualsASCII("set-cookie") || | |||
7777 | aHeader.LowerCaseEqualsASCII("set-cookie2")); | |||
7778 | } | |||
7779 | ||||
7780 | // static | |||
7781 | bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) { | |||
7782 | return headerName.EqualsIgnoreCase("x-http-method-override") || | |||
7783 | headerName.EqualsIgnoreCase("x-http-method") || | |||
7784 | headerName.EqualsIgnoreCase("x-method-override"); | |||
7785 | } | |||
7786 | ||||
7787 | // static | |||
7788 | bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) { | |||
7789 | bool hasInsecureMethod = false; | |||
7790 | nsCCharSeparatedTokenizer tokenizer(headerValue, ','); | |||
7791 | ||||
7792 | while (tokenizer.hasMoreTokens()) { | |||
7793 | const nsDependentCSubstring& value = tokenizer.nextToken(); | |||
7794 | ||||
7795 | if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") || | |||
7796 | value.EqualsIgnoreCase("track")) { | |||
7797 | hasInsecureMethod = true; | |||
7798 | break; | |||
7799 | } | |||
7800 | } | |||
7801 | ||||
7802 | return hasInsecureMethod; | |||
7803 | } | |||
7804 | ||||
7805 | Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest( | |||
7806 | const nsACString& aHeaderValue, bool aAllowWhitespace) { | |||
7807 | // See https://fetch.spec.whatwg.org/#simple-range-header-value | |||
7808 | mozilla::Tokenizer p(aHeaderValue); | |||
7809 | Maybe<uint64_t> rangeStart; | |||
7810 | Maybe<uint64_t> rangeEnd; | |||
7811 | ||||
7812 | // Step 2 and 3 | |||
7813 | if (!p.CheckWord("bytes")) { | |||
7814 | return Nothing(); | |||
7815 | } | |||
7816 | ||||
7817 | // Step 4 | |||
7818 | if (aAllowWhitespace) { | |||
7819 | p.SkipWhites(); | |||
7820 | } | |||
7821 | ||||
7822 | // Step 5 and 6 | |||
7823 | if (!p.CheckChar('=')) { | |||
7824 | return Nothing(); | |||
7825 | } | |||
7826 | ||||
7827 | // Step 7 | |||
7828 | if (aAllowWhitespace) { | |||
7829 | p.SkipWhites(); | |||
7830 | } | |||
7831 | ||||
7832 | // Step 8 and 9 | |||
7833 | uint64_t res; | |||
7834 | if (p.ReadInteger(&res)) { | |||
7835 | rangeStart = Some(res); | |||
7836 | } | |||
7837 | ||||
7838 | // Step 10 | |||
7839 | if (aAllowWhitespace) { | |||
7840 | p.SkipWhites(); | |||
7841 | } | |||
7842 | ||||
7843 | // Step 11 | |||
7844 | if (!p.CheckChar('-')) { | |||
7845 | return Nothing(); | |||
7846 | } | |||
7847 | ||||
7848 | // Step 13 | |||
7849 | if (aAllowWhitespace) { | |||
7850 | p.SkipWhites(); | |||
7851 | } | |||
7852 | ||||
7853 | // Step 14 and 15 | |||
7854 | if (p.ReadInteger(&res)) { | |||
7855 | rangeEnd = Some(res); | |||
7856 | } | |||
7857 | ||||
7858 | // Step 16 | |||
7859 | if (!p.CheckEOF()) { | |||
7860 | return Nothing(); | |||
7861 | } | |||
7862 | ||||
7863 | // Step 17 | |||
7864 | if (!rangeStart && !rangeEnd) { | |||
7865 | return Nothing(); | |||
7866 | } | |||
7867 | ||||
7868 | // Step 18 | |||
7869 | if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) { | |||
7870 | return Nothing(); | |||
7871 | } | |||
7872 | ||||
7873 | return Some(ParsedRange(rangeStart, rangeEnd)); | |||
7874 | } | |||
7875 | ||||
7876 | // static | |||
7877 | bool nsContentUtils::IsCorsUnsafeRequestHeaderValue( | |||
7878 | const nsACString& aHeaderValue) { | |||
7879 | const char* cur = aHeaderValue.BeginReading(); | |||
7880 | const char* end = aHeaderValue.EndReading(); | |||
7881 | ||||
7882 | while (cur != end) { | |||
7883 | // Implementation of | |||
7884 | // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less | |||
7885 | // than a space but not a horizontal tab | |||
7886 | if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' || | |||
7887 | *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' || | |||
7888 | *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' || | |||
7889 | *cur == ']' || *cur == '{' || *cur == '}' || | |||
7890 | *cur == 0x7F) { // 0x75 is DEL | |||
7891 | return true; | |||
7892 | } | |||
7893 | cur++; | |||
7894 | } | |||
7895 | return false; | |||
7896 | } | |||
7897 | ||||
7898 | // static | |||
7899 | bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) { | |||
7900 | if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) { | |||
7901 | return false; | |||
7902 | } | |||
7903 | return true; | |||
7904 | } | |||
7905 | ||||
7906 | // static | |||
7907 | bool nsContentUtils::IsAllowedNonCorsContentType( | |||
7908 | const nsACString& aHeaderValue) { | |||
7909 | nsAutoCString contentType; | |||
7910 | nsAutoCString unused; | |||
7911 | ||||
7912 | if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) { | |||
7913 | return false; | |||
7914 | } | |||
7915 | ||||
7916 | nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused); | |||
7917 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
7918 | return false; | |||
7919 | } | |||
7920 | ||||
7921 | return contentType.LowerCaseEqualsLiteral("text/plain") || | |||
7922 | contentType.LowerCaseEqualsLiteral( | |||
7923 | "application/x-www-form-urlencoded") || | |||
7924 | contentType.LowerCaseEqualsLiteral("multipart/form-data"); | |||
7925 | } | |||
7926 | ||||
7927 | // static | |||
7928 | bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) { | |||
7929 | const char* cur = aHeaderValue.BeginReading(); | |||
7930 | const char* end = aHeaderValue.EndReading(); | |||
7931 | ||||
7932 | while (cur != end) { | |||
7933 | if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') || | |||
7934 | (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' || | |||
7935 | *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' || | |||
7936 | *cur == '=') { | |||
7937 | cur++; | |||
7938 | continue; | |||
7939 | } | |||
7940 | return false; | |||
7941 | } | |||
7942 | return true; | |||
7943 | } | |||
7944 | ||||
7945 | bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) { | |||
7946 | Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false); | |||
7947 | if (!parsedRange) { | |||
7948 | return false; | |||
7949 | } | |||
7950 | ||||
7951 | if (!parsedRange->Start()) { | |||
7952 | return false; | |||
7953 | } | |||
7954 | ||||
7955 | return true; | |||
7956 | } | |||
7957 | ||||
7958 | // static | |||
7959 | bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName, | |||
7960 | const nsACString& aValue) { | |||
7961 | // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header | |||
7962 | if (aValue.Length() > 128) { | |||
7963 | return false; | |||
7964 | } | |||
7965 | return (aName.LowerCaseEqualsLiteral("accept") && | |||
7966 | nsContentUtils::IsAllowedNonCorsAccept(aValue)) || | |||
7967 | (aName.LowerCaseEqualsLiteral("accept-language") && | |||
7968 | nsContentUtils::IsAllowedNonCorsLanguage(aValue)) || | |||
7969 | (aName.LowerCaseEqualsLiteral("content-language") && | |||
7970 | nsContentUtils::IsAllowedNonCorsLanguage(aValue)) || | |||
7971 | (aName.LowerCaseEqualsLiteral("content-type") && | |||
7972 | nsContentUtils::IsAllowedNonCorsContentType(aValue)) || | |||
7973 | (aName.LowerCaseEqualsLiteral("range") && | |||
7974 | nsContentUtils::IsAllowedNonCorsRange(aValue)); | |||
7975 | } | |||
7976 | ||||
7977 | mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() { | |||
7978 | return gResistFingerprintingLog; | |||
7979 | } | |||
7980 | mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; } | |||
7981 | ||||
7982 | bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
7983 | nsAString& aResult, | |||
7984 | const fallible_t& aFallible) { | |||
7985 | aResult.Truncate(); | |||
7986 | return AppendNodeTextContent(aNode, aDeep, aResult, aFallible); | |||
7987 | } | |||
7988 | ||||
7989 | void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep, | |||
7990 | nsAString& aResult) { | |||
7991 | if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) { | |||
7992 | NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size | |||
7993 | } | |||
7994 | } | |||
7995 | ||||
7996 | void nsContentUtils::DestroyMatchString(void* aData) { | |||
7997 | if (aData) { | |||
7998 | nsString* matchString = static_cast<nsString*>(aData); | |||
7999 | delete matchString; | |||
8000 | } | |||
8001 | } | |||
8002 | ||||
8003 | // Table ordered from most to least likely JS MIME types. | |||
8004 | static constexpr std::string_view kJavascriptMIMETypes[] = { | |||
8005 | "text/javascript", | |||
8006 | "text/ecmascript", | |||
8007 | "application/javascript", | |||
8008 | "application/ecmascript", | |||
8009 | "application/x-javascript", | |||
8010 | "application/x-ecmascript", | |||
8011 | "text/javascript1.0", | |||
8012 | "text/javascript1.1", | |||
8013 | "text/javascript1.2", | |||
8014 | "text/javascript1.3", | |||
8015 | "text/javascript1.4", | |||
8016 | "text/javascript1.5", | |||
8017 | "text/jscript", | |||
8018 | "text/livescript", | |||
8019 | "text/x-ecmascript", | |||
8020 | "text/x-javascript"}; | |||
8021 | ||||
8022 | bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) { | |||
8023 | for (std::string_view type : kJavascriptMIMETypes) { | |||
8024 | if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) { | |||
8025 | return true; | |||
8026 | } | |||
8027 | } | |||
8028 | return false; | |||
8029 | } | |||
8030 | ||||
8031 | bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) { | |||
8032 | for (std::string_view type : kJavascriptMIMETypes) { | |||
8033 | if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) { | |||
8034 | return true; | |||
8035 | } | |||
8036 | } | |||
8037 | return false; | |||
8038 | } | |||
8039 | ||||
8040 | bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) { | |||
8041 | // | |||
8042 | // SECURITY CHECK: disable prefetching and preloading from mailnews! | |||
8043 | // | |||
8044 | // walk up the docshell tree to see if any containing | |||
8045 | // docshell are of type MAIL. | |||
8046 | // | |||
8047 | ||||
8048 | if (!aDocShell) { | |||
8049 | return false; | |||
8050 | } | |||
8051 | ||||
8052 | nsCOMPtr<nsIDocShell> docshell = aDocShell; | |||
8053 | nsCOMPtr<nsIDocShellTreeItem> parentItem; | |||
8054 | ||||
8055 | do { | |||
8056 | auto appType = docshell->GetAppType(); | |||
8057 | if (appType == nsIDocShell::APP_TYPE_MAIL) { | |||
8058 | return false; // do not prefetch, preload, preconnect from mailnews | |||
8059 | } | |||
8060 | ||||
8061 | docshell->GetInProcessParent(getter_AddRefs(parentItem)); | |||
8062 | if (parentItem) { | |||
8063 | docshell = do_QueryInterface(parentItem); | |||
8064 | if (!docshell) { | |||
8065 | NS_ERROR("cannot get a docshell from a treeItem!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "cannot get a docshell from a treeItem!" , "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8065); MOZ_PretendNoReturn(); } while (0); | |||
8066 | return false; | |||
8067 | } | |||
8068 | } | |||
8069 | } while (parentItem); | |||
8070 | ||||
8071 | return true; | |||
8072 | } | |||
8073 | ||||
8074 | uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) { | |||
8075 | // can't do anything if there's no nsIRequest! | |||
8076 | if (!aRequest) { | |||
8077 | return 0; | |||
8078 | } | |||
8079 | ||||
8080 | nsCOMPtr<nsILoadGroup> loadGroup; | |||
8081 | nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup)); | |||
8082 | ||||
8083 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) { | |||
8084 | return 0; | |||
8085 | } | |||
8086 | ||||
8087 | return GetInnerWindowID(loadGroup); | |||
8088 | } | |||
8089 | ||||
8090 | uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) { | |||
8091 | if (!aLoadGroup) { | |||
8092 | return 0; | |||
8093 | } | |||
8094 | ||||
8095 | nsCOMPtr<nsIInterfaceRequestor> callbacks; | |||
8096 | nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); | |||
8097 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) { | |||
8098 | return 0; | |||
8099 | } | |||
8100 | ||||
8101 | nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); | |||
8102 | if (!loadContext) { | |||
8103 | return 0; | |||
8104 | } | |||
8105 | ||||
8106 | nsCOMPtr<mozIDOMWindowProxy> window; | |||
8107 | rv = loadContext->GetAssociatedWindow(getter_AddRefs(window)); | |||
8108 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) { | |||
8109 | return 0; | |||
8110 | } | |||
8111 | ||||
8112 | auto* pwindow = nsPIDOMWindowOuter::From(window); | |||
8113 | if (!pwindow) { | |||
8114 | return 0; | |||
8115 | } | |||
8116 | ||||
8117 | nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow(); | |||
8118 | return inner ? inner->WindowID() : 0; | |||
8119 | } | |||
8120 | ||||
8121 | // static | |||
8122 | void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) { | |||
8123 | if (aHost.FindChar(':') != -1) { // Escape IPv6 address | |||
8124 | MOZ_ASSERT(!aHost.Length() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aHost.Length() || (aHost[0] != '[' && aHost [aHost.Length() - 1] != ']'))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')" ")"); do { *((volatile int*)__null) = 8125; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
8125 | (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']'))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aHost.Length() || (aHost[0] != '[' && aHost [aHost.Length() - 1] != ']'))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aHost.Length() || (aHost[0] != '[' && aHost[aHost.Length() - 1] != ']')" ")"); do { *((volatile int*)__null) = 8125; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8126 | aHost.Insert('[', 0); | |||
8127 | aHost.Append(']'); | |||
8128 | } | |||
8129 | } | |||
8130 | ||||
8131 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, | |||
8132 | nsACString& aHost) { | |||
8133 | aHost.Truncate(); | |||
8134 | nsresult rv = aURI->GetHost(aHost); | |||
8135 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host | |||
8136 | return rv; | |||
8137 | } | |||
8138 | ||||
8139 | MaybeFixIPv6Host(aHost); | |||
8140 | ||||
8141 | return NS_OK; | |||
8142 | } | |||
8143 | ||||
8144 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, | |||
8145 | nsAString& aHost) { | |||
8146 | nsAutoCString hostname; | |||
8147 | nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname); | |||
8148 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
8149 | return rv; | |||
8150 | } | |||
8151 | CopyUTF8toUTF16(hostname, aHost); | |||
8152 | return NS_OK; | |||
8153 | } | |||
8154 | ||||
8155 | nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal, | |||
8156 | nsACString& aHost) { | |||
8157 | nsresult rv = aPrincipal->GetAsciiHost(aHost); | |||
8158 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host | |||
8159 | return rv; | |||
8160 | } | |||
8161 | ||||
8162 | MaybeFixIPv6Host(aHost); | |||
8163 | return NS_OK; | |||
8164 | } | |||
8165 | ||||
8166 | CallState nsContentUtils::CallOnAllRemoteChildren( | |||
8167 | MessageBroadcaster* aManager, | |||
8168 | const std::function<CallState(BrowserParent*)>& aCallback) { | |||
8169 | uint32_t browserChildCount = aManager->ChildCount(); | |||
8170 | for (uint32_t j = 0; j < browserChildCount; ++j) { | |||
8171 | RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j); | |||
8172 | if (!childMM) { | |||
8173 | continue; | |||
8174 | } | |||
8175 | ||||
8176 | RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM); | |||
8177 | if (nonLeafMM) { | |||
8178 | if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) { | |||
8179 | return CallState::Stop; | |||
8180 | } | |||
8181 | continue; | |||
8182 | } | |||
8183 | ||||
8184 | mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback(); | |||
8185 | if (cb) { | |||
8186 | nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb); | |||
8187 | BrowserParent* remote = BrowserParent::GetFrom(fl); | |||
8188 | if (remote && aCallback) { | |||
8189 | if (aCallback(remote) == CallState::Stop) { | |||
8190 | return CallState::Stop; | |||
8191 | } | |||
8192 | } | |||
8193 | } | |||
8194 | } | |||
8195 | ||||
8196 | return CallState::Continue; | |||
8197 | } | |||
8198 | ||||
8199 | void nsContentUtils::CallOnAllRemoteChildren( | |||
8200 | nsPIDOMWindowOuter* aWindow, | |||
8201 | const std::function<CallState(BrowserParent*)>& aCallback) { | |||
8202 | nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow); | |||
8203 | if (window->IsChromeWindow()) { | |||
8204 | RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager(); | |||
8205 | if (windowMM) { | |||
8206 | CallOnAllRemoteChildren(windowMM, aCallback); | |||
8207 | } | |||
8208 | } | |||
8209 | } | |||
8210 | ||||
8211 | bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor( | |||
8212 | const IPCTransferableDataItem& aItem) { | |||
8213 | // Unknown types are converted to kCustomTypesMime. | |||
8214 | if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) { | |||
8215 | return true; | |||
8216 | } | |||
8217 | ||||
8218 | for (const char* format : DataTransfer::kKnownFormats) { | |||
8219 | if (aItem.flavor().EqualsASCII(format)) { | |||
8220 | return true; | |||
8221 | } | |||
8222 | } | |||
8223 | ||||
8224 | return false; | |||
8225 | } | |||
8226 | ||||
8227 | nsresult nsContentUtils::IPCTransferableDataToTransferable( | |||
8228 | const IPCTransferableData& aTransferableData, bool aAddDataFlavor, | |||
8229 | nsITransferable* aTransferable, const bool aFilterUnknownFlavors) { | |||
8230 | nsresult rv; | |||
8231 | const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items(); | |||
8232 | for (const auto& item : items) { | |||
8233 | if (aFilterUnknownFlavors && !IPCTransferableDataItemHasKnownFlavor(item)) { | |||
8234 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8236) | |||
8235 | "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8236) | |||
8236 | "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in " "nsContentUtils::IPCTransferableDataToTransferable", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8236); | |||
8237 | continue; | |||
8238 | } | |||
8239 | ||||
8240 | if (aAddDataFlavor) { | |||
8241 | aTransferable->AddDataFlavor(item.flavor().get()); | |||
8242 | } | |||
8243 | ||||
8244 | nsCOMPtr<nsISupports> transferData; | |||
8245 | switch (item.data().type()) { | |||
8246 | case IPCTransferableDataType::TIPCTransferableDataString: { | |||
8247 | const auto& data = item.data().get_IPCTransferableDataString(); | |||
8248 | nsCOMPtr<nsISupportsString> dataWrapper = | |||
8249 | do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv); | |||
8250 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8250); return rv; } } while (false); | |||
8251 | rv = dataWrapper->SetData(nsDependentSubstring( | |||
8252 | reinterpret_cast<const char16_t*>(data.data().Data()), | |||
8253 | data.data().Size() / sizeof(char16_t))); | |||
8254 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8254); return rv; } } while (false); | |||
8255 | transferData = dataWrapper; | |||
8256 | break; | |||
8257 | } | |||
8258 | case IPCTransferableDataType::TIPCTransferableDataCString: { | |||
8259 | const auto& data = item.data().get_IPCTransferableDataCString(); | |||
8260 | nsCOMPtr<nsISupportsCString> dataWrapper = | |||
8261 | do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv); | |||
8262 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8262); return rv; } } while (false); | |||
8263 | rv = dataWrapper->SetData(nsDependentCSubstring( | |||
8264 | reinterpret_cast<const char*>(data.data().Data()), | |||
8265 | data.data().Size())); | |||
8266 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8266); return rv; } } while (false); | |||
8267 | transferData = dataWrapper; | |||
8268 | break; | |||
8269 | } | |||
8270 | case IPCTransferableDataType::TIPCTransferableDataInputStream: { | |||
8271 | const auto& data = item.data().get_IPCTransferableDataInputStream(); | |||
8272 | nsCOMPtr<nsIInputStream> stream; | |||
8273 | rv = NS_NewByteInputStream(getter_AddRefs(stream), | |||
8274 | AsChars(data.data().AsSpan()), | |||
8275 | NS_ASSIGNMENT_COPY); | |||
8276 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8276); return rv; } } while (false); | |||
8277 | transferData = stream.forget(); | |||
8278 | break; | |||
8279 | } | |||
8280 | case IPCTransferableDataType::TIPCTransferableDataImageContainer: { | |||
8281 | const auto& data = item.data().get_IPCTransferableDataImageContainer(); | |||
8282 | nsCOMPtr<imgIContainer> container; | |||
8283 | rv = DeserializeTransferableDataImageContainer( | |||
8284 | data, getter_AddRefs(container)); | |||
8285 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8285); return rv; } } while (false); | |||
8286 | transferData = container; | |||
8287 | break; | |||
8288 | } | |||
8289 | case IPCTransferableDataType::TIPCTransferableDataBlob: { | |||
8290 | const auto& data = item.data().get_IPCTransferableDataBlob(); | |||
8291 | transferData = IPCBlobUtils::Deserialize(data.blob()); | |||
8292 | break; | |||
8293 | } | |||
8294 | case IPCTransferableDataType::T__None: | |||
8295 | 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: " ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null ) = 8295; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
8296 | return NS_ERROR_FAILURE; | |||
8297 | } | |||
8298 | ||||
8299 | rv = aTransferable->SetTransferData(item.flavor().get(), transferData); | |||
8300 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8300); return rv; } } while (false); | |||
8301 | } | |||
8302 | return NS_OK; | |||
8303 | } | |||
8304 | ||||
8305 | nsresult nsContentUtils::IPCTransferableToTransferable( | |||
8306 | const IPCTransferable& aIPCTransferable, bool aAddDataFlavor, | |||
8307 | nsITransferable* aTransferable, const bool aFilterUnknownFlavors) { | |||
8308 | // Note that we need to set privacy status of transferable before adding any | |||
8309 | // data into it. | |||
8310 | aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData()); | |||
8311 | ||||
8312 | nsresult rv = | |||
8313 | IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor, | |||
8314 | aTransferable, aFilterUnknownFlavors); | |||
8315 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8315); return rv; } } while (false); | |||
8316 | ||||
8317 | if (aIPCTransferable.cookieJarSettings().isSome()) { | |||
8318 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings; | |||
8319 | net::CookieJarSettings::Deserialize( | |||
8320 | aIPCTransferable.cookieJarSettings().ref(), | |||
8321 | getter_AddRefs(cookieJarSettings)); | |||
8322 | aTransferable->SetCookieJarSettings(cookieJarSettings); | |||
8323 | } | |||
8324 | aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo()); | |||
8325 | aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal()); | |||
8326 | aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType()); | |||
8327 | ||||
8328 | return NS_OK; | |||
8329 | } | |||
8330 | ||||
8331 | nsresult nsContentUtils::IPCTransferableDataItemToVariant( | |||
8332 | const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) { | |||
8333 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")" ); do { *((volatile int*)__null) = 8333; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8334 | ||||
8335 | switch (aItem.data().type()) { | |||
8336 | case IPCTransferableDataType::TIPCTransferableDataString: { | |||
8337 | const auto& data = aItem.data().get_IPCTransferableDataString(); | |||
8338 | return aVariant->SetAsAString(nsDependentSubstring( | |||
8339 | reinterpret_cast<const char16_t*>(data.data().Data()), | |||
8340 | data.data().Size() / sizeof(char16_t))); | |||
8341 | } | |||
8342 | case IPCTransferableDataType::TIPCTransferableDataCString: { | |||
8343 | const auto& data = aItem.data().get_IPCTransferableDataCString(); | |||
8344 | return aVariant->SetAsACString(nsDependentCSubstring( | |||
8345 | reinterpret_cast<const char*>(data.data().Data()), | |||
8346 | data.data().Size())); | |||
8347 | } | |||
8348 | case IPCTransferableDataType::TIPCTransferableDataInputStream: { | |||
8349 | const auto& data = aItem.data().get_IPCTransferableDataInputStream(); | |||
8350 | nsCOMPtr<nsIInputStream> stream; | |||
8351 | nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), | |||
8352 | AsChars(data.data().AsSpan()), | |||
8353 | NS_ASSIGNMENT_COPY); | |||
8354 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8354); return rv; } } while (false); | |||
8355 | return aVariant->SetAsISupports(stream); | |||
8356 | } | |||
8357 | case IPCTransferableDataType::TIPCTransferableDataImageContainer: { | |||
8358 | const auto& data = aItem.data().get_IPCTransferableDataImageContainer(); | |||
8359 | nsCOMPtr<imgIContainer> container; | |||
8360 | nsresult rv = DeserializeTransferableDataImageContainer( | |||
8361 | data, getter_AddRefs(container)); | |||
8362 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8362); return rv; } } while (false); | |||
8363 | return aVariant->SetAsISupports(container); | |||
8364 | } | |||
8365 | case IPCTransferableDataType::TIPCTransferableDataBlob: { | |||
8366 | const auto& data = aItem.data().get_IPCTransferableDataBlob(); | |||
8367 | RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob()); | |||
8368 | return aVariant->SetAsISupports(blobImpl); | |||
8369 | } | |||
8370 | case IPCTransferableDataType::T__None: | |||
8371 | break; | |||
8372 | } | |||
8373 | ||||
8374 | 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: " ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " ")"); do { *((volatile int*)__null ) = 8374; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); | |||
8375 | return NS_ERROR_UNEXPECTED; | |||
8376 | } | |||
8377 | ||||
8378 | void nsContentUtils::TransferablesToIPCTransferableDatas( | |||
8379 | nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC, | |||
8380 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
8381 | aIPC.Clear(); | |||
8382 | if (aTransferables) { | |||
8383 | uint32_t transferableCount = 0; | |||
8384 | aTransferables->GetLength(&transferableCount); | |||
8385 | for (uint32_t i = 0; i < transferableCount; ++i) { | |||
8386 | IPCTransferableData* dt = aIPC.AppendElement(); | |||
8387 | nsCOMPtr<nsITransferable> transferable = | |||
8388 | do_QueryElementAt(aTransferables, i); | |||
8389 | TransferableToIPCTransferableData(transferable, dt, aInSyncMessage, | |||
8390 | aParent); | |||
8391 | } | |||
8392 | } | |||
8393 | } | |||
8394 | ||||
8395 | nsresult nsContentUtils::CalculateBufferSizeForImage( | |||
8396 | const uint32_t& aStride, const IntSize& aImageSize, | |||
8397 | const SurfaceFormat& aFormat, size_t* aMaxBufferSize, | |||
8398 | size_t* aUsedBufferSize) { | |||
8399 | CheckedInt32 requiredBytes = | |||
8400 | CheckedInt32(aStride) * CheckedInt32(aImageSize.height); | |||
8401 | ||||
8402 | CheckedInt32 usedBytes = | |||
8403 | requiredBytes - aStride + | |||
8404 | (CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat)); | |||
8405 | if (!usedBytes.isValid()) { | |||
8406 | return NS_ERROR_FAILURE; | |||
8407 | } | |||
8408 | ||||
8409 | MOZ_ASSERT(requiredBytes.isValid(), "usedBytes valid but not required?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(requiredBytes.isValid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(requiredBytes.isValid()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("requiredBytes.isValid()" " (" "usedBytes valid but not required?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "requiredBytes.isValid()" ") (" "usedBytes valid but not required?" ")"); do { *((volatile int*)__null) = 8409; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
8410 | *aMaxBufferSize = requiredBytes.value(); | |||
8411 | *aUsedBufferSize = usedBytes.value(); | |||
8412 | return NS_OK; | |||
8413 | } | |||
8414 | ||||
8415 | static already_AddRefed<DataSourceSurface> BigBufferToDataSurface( | |||
8416 | const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize, | |||
8417 | SurfaceFormat aFormat) { | |||
8418 | if (!aData.Size() || !aImageSize.width || !aImageSize.height) { | |||
8419 | return nullptr; | |||
8420 | } | |||
8421 | ||||
8422 | // Validate shared memory buffer size | |||
8423 | size_t imageBufLen = 0; | |||
8424 | size_t maxBufLen = 0; | |||
8425 | if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage ( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen ))), 0))) | |||
8426 | aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage ( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen ))), 0)))) { | |||
8427 | return nullptr; | |||
8428 | } | |||
8429 | if (imageBufLen > aData.Size()) { | |||
8430 | return nullptr; | |||
8431 | } | |||
8432 | return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(), | |||
8433 | aStride); | |||
8434 | } | |||
8435 | ||||
8436 | nsresult nsContentUtils::DeserializeTransferableDataImageContainer( | |||
8437 | const IPCTransferableDataImageContainer& aData, | |||
8438 | imgIContainer** aContainer) { | |||
8439 | RefPtr<DataSourceSurface> surface = IPCImageToSurface(aData.image()); | |||
8440 | if (!surface) { | |||
8441 | return NS_ERROR_FAILURE; | |||
8442 | } | |||
8443 | ||||
8444 | RefPtr<gfxDrawable> drawable = | |||
8445 | new gfxSurfaceDrawable(surface, surface->GetSize()); | |||
8446 | nsCOMPtr<imgIContainer> imageContainer = | |||
8447 | image::ImageOps::CreateFromDrawable(drawable); | |||
8448 | imageContainer.forget(aContainer); | |||
8449 | ||||
8450 | return NS_OK; | |||
8451 | } | |||
8452 | ||||
8453 | bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) { | |||
8454 | return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") || | |||
8455 | aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") || | |||
8456 | aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") || | |||
8457 | aFlavor.EqualsLiteral(kPNGImageMime"image/png") || | |||
8458 | aFlavor.EqualsLiteral(kGIFImageMime"image/gif"); | |||
8459 | } | |||
8460 | ||||
8461 | // FIXME: This can probably be removed once bug 1783240 lands, as `nsString` | |||
8462 | // will be implicitly serialized in shmem when sent over IPDL directly. | |||
8463 | static IPCTransferableDataString AsIPCTransferableDataString( | |||
8464 | Span<const char16_t> aInput) { | |||
8465 | return IPCTransferableDataString{BigBuffer(AsBytes(aInput))}; | |||
8466 | } | |||
8467 | ||||
8468 | // FIXME: This can probably be removed once bug 1783240 lands, as `nsCString` | |||
8469 | // will be implicitly serialized in shmem when sent over IPDL directly. | |||
8470 | static IPCTransferableDataCString AsIPCTransferableDataCString( | |||
8471 | Span<const char> aInput) { | |||
8472 | return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))}; | |||
8473 | } | |||
8474 | ||||
8475 | void nsContentUtils::TransferableToIPCTransferableData( | |||
8476 | nsITransferable* aTransferable, IPCTransferableData* aTransferableData, | |||
8477 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
8478 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")" ); do { *((volatile int*)__null) = 8478; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
8479 | ||||
8480 | if (aTransferable) { | |||
8481 | nsTArray<nsCString> flavorList; | |||
8482 | aTransferable->FlavorsTransferableCanExport(flavorList); | |||
8483 | ||||
8484 | for (uint32_t j = 0; j < flavorList.Length(); ++j) { | |||
8485 | nsCString& flavorStr = flavorList[j]; | |||
8486 | if (!flavorStr.Length()) { | |||
8487 | continue; | |||
8488 | } | |||
8489 | ||||
8490 | nsCOMPtr<nsISupports> data; | |||
8491 | nsresult rv = | |||
8492 | aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data)); | |||
8493 | ||||
8494 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) { | |||
8495 | if (aInSyncMessage) { | |||
8496 | // Can't do anything. | |||
8497 | // FIXME: This shouldn't be the case anymore! | |||
8498 | continue; | |||
8499 | } | |||
8500 | ||||
8501 | // This is a hack to support kFilePromiseMime. | |||
8502 | // On Windows there just needs to be an entry for it, | |||
8503 | // and for OSX we need to create | |||
8504 | // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider. | |||
8505 | if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) { | |||
8506 | IPCTransferableDataItem* item = | |||
8507 | aTransferableData->items().AppendElement(); | |||
8508 | item->flavor() = flavorStr; | |||
8509 | item->data() = | |||
8510 | AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr)); | |||
8511 | continue; | |||
8512 | } | |||
8513 | ||||
8514 | // Empty element, transfer only the flavor | |||
8515 | IPCTransferableDataItem* item = | |||
8516 | aTransferableData->items().AppendElement(); | |||
8517 | item->flavor() = flavorStr; | |||
8518 | item->data() = AsIPCTransferableDataString(EmptyString()); | |||
8519 | continue; | |||
8520 | } | |||
8521 | ||||
8522 | // We need to handle nsIInputStream before nsISupportsCString, otherwise | |||
8523 | // nsStringInputStream would be converted into a wrong type. | |||
8524 | if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) { | |||
8525 | IPCTransferableDataItem* item = | |||
8526 | aTransferableData->items().AppendElement(); | |||
8527 | item->flavor() = flavorStr; | |||
8528 | nsCString imageData; | |||
8529 | DebugOnly<nsresult> rv = | |||
8530 | NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData); | |||
8531 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
8532 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
8533 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK" ") (" "cannot use async input streams in nsITransferable right now" ")"); do { *((volatile int*)__null) = 8533; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8534 | // FIXME: This can probably be simplified once bug 1783240 lands, as | |||
8535 | // `nsCString` will be implicitly serialized in shmem when sent over | |||
8536 | // IPDL directly. | |||
8537 | item->data() = | |||
8538 | IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData)))); | |||
8539 | continue; | |||
8540 | } | |||
8541 | ||||
8542 | if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) { | |||
8543 | nsAutoString dataAsString; | |||
8544 | MOZ_ALWAYS_SUCCEEDS(text->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (text->GetData(dataAsString))), 1)))), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType<decltype (false)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(text->GetData(dataAsString))" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8544); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"); do { *((volatile int*)__null) = 8544; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); | |||
8545 | ||||
8546 | IPCTransferableDataItem* item = | |||
8547 | aTransferableData->items().AppendElement(); | |||
8548 | item->flavor() = flavorStr; | |||
8549 | item->data() = AsIPCTransferableDataString(dataAsString); | |||
8550 | continue; | |||
8551 | } | |||
8552 | ||||
8553 | if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) { | |||
8554 | nsAutoCString dataAsString; | |||
8555 | MOZ_ALWAYS_SUCCEEDS(ctext->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (ctext->GetData(dataAsString))), 1)))), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(ctext->GetData(dataAsString))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(ctext->GetData(dataAsString))" ")"); do { *((volatile int*)__null) = 8555; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); } } while (false ); | |||
8556 | ||||
8557 | IPCTransferableDataItem* item = | |||
8558 | aTransferableData->items().AppendElement(); | |||
8559 | item->flavor() = flavorStr; | |||
8560 | item->data() = AsIPCTransferableDataCString(dataAsString); | |||
8561 | continue; | |||
8562 | } | |||
8563 | ||||
8564 | if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) { | |||
8565 | // Images to be placed on the clipboard are imgIContainers. | |||
8566 | RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame( | |||
8567 | imgIContainer::FRAME_CURRENT, | |||
8568 | imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY); | |||
8569 | if (!surface) { | |||
8570 | continue; | |||
8571 | } | |||
8572 | RefPtr<mozilla::gfx::DataSourceSurface> dataSurface = | |||
8573 | surface->GetDataSurface(); | |||
8574 | if (!dataSurface) { | |||
8575 | continue; | |||
8576 | } | |||
8577 | ||||
8578 | auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface); | |||
8579 | if (!imageData) { | |||
8580 | continue; | |||
8581 | } | |||
8582 | ||||
8583 | IPCTransferableDataItem* item = | |||
8584 | aTransferableData->items().AppendElement(); | |||
8585 | item->flavor() = flavorStr; | |||
8586 | item->data() = IPCTransferableDataImageContainer(std::move(*imageData)); | |||
8587 | continue; | |||
8588 | } | |||
8589 | ||||
8590 | // Otherwise, handle this as a file. | |||
8591 | nsCOMPtr<BlobImpl> blobImpl; | |||
8592 | if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) { | |||
8593 | if (aParent) { | |||
8594 | bool isDir = false; | |||
8595 | if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory (&isDir))), 1))) && isDir) { | |||
8596 | nsAutoString path; | |||
8597 | 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))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8597)) { | |||
8598 | continue; | |||
8599 | } | |||
8600 | ||||
8601 | RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate(); | |||
8602 | fss->GrantAccessToContentProcess(aParent->ChildID(), path); | |||
8603 | } | |||
8604 | } | |||
8605 | ||||
8606 | blobImpl = new FileBlobImpl(file); | |||
8607 | ||||
8608 | IgnoredErrorResult rv; | |||
8609 | ||||
8610 | // Ensure that file data is cached no that the content process | |||
8611 | // has this data available to it when passed over: | |||
8612 | blobImpl->GetSize(rv); | |||
8613 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8613)) { | |||
8614 | continue; | |||
8615 | } | |||
8616 | ||||
8617 | blobImpl->GetLastModified(rv); | |||
8618 | if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8618)) { | |||
8619 | continue; | |||
8620 | } | |||
8621 | } else { | |||
8622 | if (aInSyncMessage) { | |||
8623 | // Can't do anything. | |||
8624 | // FIXME: This shouldn't be the case anymore! | |||
8625 | continue; | |||
8626 | } | |||
8627 | ||||
8628 | blobImpl = do_QueryInterface(data); | |||
8629 | } | |||
8630 | ||||
8631 | if (blobImpl) { | |||
8632 | // If we failed to create the blob actor, then this blob probably | |||
8633 | // can't get the file size for the underlying file, ignore it for | |||
8634 | // now. TODO pass this through anyway. | |||
8635 | IPCBlob ipcBlob; | |||
8636 | nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob); | |||
8637 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8637)) { | |||
8638 | continue; | |||
8639 | } | |||
8640 | ||||
8641 | IPCTransferableDataItem* item = | |||
8642 | aTransferableData->items().AppendElement(); | |||
8643 | item->flavor() = flavorStr; | |||
8644 | item->data() = IPCTransferableDataBlob(ipcBlob); | |||
8645 | } | |||
8646 | } | |||
8647 | } | |||
8648 | } | |||
8649 | ||||
8650 | void nsContentUtils::TransferableToIPCTransferable( | |||
8651 | nsITransferable* aTransferable, IPCTransferable* aIPCTransferable, | |||
8652 | bool aInSyncMessage, mozilla::dom::ContentParent* aParent) { | |||
8653 | IPCTransferableData ipcTransferableData; | |||
8654 | TransferableToIPCTransferableData(aTransferable, &ipcTransferableData, | |||
8655 | aInSyncMessage, aParent); | |||
8656 | ||||
8657 | Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs; | |||
8658 | if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings = | |||
8659 | aTransferable->GetCookieJarSettings()) { | |||
8660 | net::CookieJarSettingsArgs args; | |||
8661 | net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args); | |||
8662 | cookieJarSettingsArgs = Some(std::move(args)); | |||
8663 | } | |||
8664 | ||||
8665 | aIPCTransferable->data() = std::move(ipcTransferableData); | |||
8666 | aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData(); | |||
8667 | aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal(); | |||
8668 | aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs); | |||
8669 | aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType(); | |||
8670 | aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo(); | |||
8671 | } | |||
8672 | ||||
8673 | Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface, | |||
8674 | size_t* aLength, | |||
8675 | int32_t* aStride) { | |||
8676 | mozilla::gfx::DataSourceSurface::MappedSurface map; | |||
8677 | if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) { | |||
8678 | return Nothing(); | |||
8679 | } | |||
8680 | ||||
8681 | size_t bufLen = 0; | |||
8682 | size_t maxBufLen = 0; | |||
8683 | nsresult rv = nsContentUtils::CalculateBufferSizeForImage( | |||
8684 | map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen, | |||
8685 | &bufLen); | |||
8686 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
8687 | aSurface.Unmap(); | |||
8688 | return Nothing(); | |||
8689 | } | |||
8690 | ||||
8691 | BigBuffer surfaceData(maxBufLen); | |||
8692 | memcpy(surfaceData.Data(), map.mData, bufLen); | |||
8693 | memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen); | |||
8694 | ||||
8695 | *aLength = maxBufLen; | |||
8696 | *aStride = map.mStride; | |||
8697 | ||||
8698 | aSurface.Unmap(); | |||
8699 | return Some(std::move(surfaceData)); | |||
8700 | } | |||
8701 | ||||
8702 | Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) { | |||
8703 | size_t len = 0; | |||
8704 | int32_t stride = 0; | |||
8705 | auto mem = GetSurfaceData(aSurface, &len, &stride); | |||
8706 | if (!mem) { | |||
8707 | return Nothing(); | |||
8708 | } | |||
8709 | return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(), | |||
8710 | ImageIntSize::FromUnknownSize(aSurface.GetSize())}); | |||
8711 | } | |||
8712 | ||||
8713 | already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface( | |||
8714 | const IPCImage& aImage) { | |||
8715 | return BigBufferToDataSurface(aImage.data(), aImage.stride(), | |||
8716 | aImage.size().ToUnknownSize(), aImage.format()); | |||
8717 | } | |||
8718 | ||||
8719 | Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) { | |||
8720 | Modifiers result = 0; | |||
8721 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) { | |||
8722 | result |= mozilla::MODIFIER_SHIFT; | |||
8723 | } | |||
8724 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) { | |||
8725 | result |= mozilla::MODIFIER_CONTROL; | |||
8726 | } | |||
8727 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) { | |||
8728 | result |= mozilla::MODIFIER_ALT; | |||
8729 | } | |||
8730 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) { | |||
8731 | result |= mozilla::MODIFIER_META; | |||
8732 | } | |||
8733 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) { | |||
8734 | result |= mozilla::MODIFIER_ALTGRAPH; | |||
8735 | } | |||
8736 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) { | |||
8737 | result |= mozilla::MODIFIER_CAPSLOCK; | |||
8738 | } | |||
8739 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) { | |||
8740 | result |= mozilla::MODIFIER_FN; | |||
8741 | } | |||
8742 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) { | |||
8743 | result |= mozilla::MODIFIER_FNLOCK; | |||
8744 | } | |||
8745 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) { | |||
8746 | result |= mozilla::MODIFIER_NUMLOCK; | |||
8747 | } | |||
8748 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) { | |||
8749 | result |= mozilla::MODIFIER_SCROLLLOCK; | |||
8750 | } | |||
8751 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) { | |||
8752 | result |= mozilla::MODIFIER_SYMBOL; | |||
8753 | } | |||
8754 | if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) { | |||
8755 | result |= mozilla::MODIFIER_SYMBOLLOCK; | |||
8756 | } | |||
8757 | return result; | |||
8758 | } | |||
8759 | ||||
8760 | nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) { | |||
8761 | if (!aPresShell) { | |||
8762 | return nullptr; | |||
8763 | } | |||
8764 | nsIFrame* frame = aPresShell->GetRootFrame(); | |||
8765 | if (!frame) { | |||
8766 | return nullptr; | |||
8767 | } | |||
8768 | return frame->GetView()->GetNearestWidget(aOffset); | |||
8769 | } | |||
8770 | ||||
8771 | int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) { | |||
8772 | switch (aButton) { | |||
8773 | case -1: | |||
8774 | return MouseButtonsFlag::eNoButtons; | |||
8775 | case MouseButton::ePrimary: | |||
8776 | return MouseButtonsFlag::ePrimaryFlag; | |||
8777 | case MouseButton::eMiddle: | |||
8778 | return MouseButtonsFlag::eMiddleFlag; | |||
8779 | case MouseButton::eSecondary: | |||
8780 | return MouseButtonsFlag::eSecondaryFlag; | |||
8781 | case 3: | |||
8782 | return MouseButtonsFlag::e4thFlag; | |||
8783 | case 4: | |||
8784 | return MouseButtonsFlag::e5thFlag; | |||
8785 | case MouseButton::eEraser: | |||
8786 | return MouseButtonsFlag::eEraserFlag; | |||
8787 | default: | |||
8788 | NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8788); MOZ_PretendNoReturn(); } while (0); | |||
8789 | return 0; | |||
8790 | } | |||
8791 | } | |||
8792 | ||||
8793 | LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint( | |||
8794 | const CSSPoint& aPoint, const nsPoint& aOffset, | |||
8795 | nsPresContext* aPresContext) { | |||
8796 | nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset; | |||
8797 | nsPoint visualRelative = | |||
8798 | ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell()); | |||
8799 | return LayoutDeviceIntPoint::FromAppUnitsRounded( | |||
8800 | visualRelative, aPresContext->AppUnitsPerDevPixel()); | |||
8801 | } | |||
8802 | ||||
8803 | nsView* nsContentUtils::GetViewToDispatchEvent(nsPresContext* aPresContext, | |||
8804 | PresShell** aPresShell) { | |||
8805 | if (!aPresContext || !aPresShell) { | |||
8806 | return nullptr; | |||
8807 | } | |||
8808 | RefPtr<PresShell> presShell = aPresContext->PresShell(); | |||
8809 | if (NS_WARN_IF(!presShell)NS_warn_if_impl(!presShell, "!presShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8809)) { | |||
8810 | *aPresShell = nullptr; | |||
8811 | return nullptr; | |||
8812 | } | |||
8813 | nsViewManager* viewManager = presShell->GetViewManager(); | |||
8814 | if (!viewManager) { | |||
8815 | presShell.forget(aPresShell); // XXX Is this intentional? | |||
8816 | return nullptr; | |||
8817 | } | |||
8818 | presShell.forget(aPresShell); | |||
8819 | return viewManager->GetRootView(); | |||
8820 | } | |||
8821 | ||||
8822 | nsresult nsContentUtils::SendMouseEvent( | |||
8823 | mozilla::PresShell* aPresShell, const nsAString& aType, float aX, float aY, | |||
8824 | int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers, | |||
8825 | bool aIgnoreRootScrollFrame, float aPressure, | |||
8826 | unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, | |||
8827 | PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized, | |||
8828 | bool aIsWidgetEventSynthesized) { | |||
8829 | nsPoint offset; | |||
8830 | nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset); | |||
8831 | if (!widget) return NS_ERROR_FAILURE; | |||
8832 | ||||
8833 | EventMessage msg; | |||
8834 | Maybe<WidgetMouseEvent::ExitFrom> exitFrom; | |||
8835 | bool contextMenuKey = false; | |||
8836 | if (aType.EqualsLiteral("mousedown")) { | |||
8837 | msg = eMouseDown; | |||
8838 | } else if (aType.EqualsLiteral("mouseup")) { | |||
8839 | msg = eMouseUp; | |||
8840 | } else if (aType.EqualsLiteral("mousemove")) { | |||
8841 | msg = eMouseMove; | |||
8842 | } else if (aType.EqualsLiteral("mouseover")) { | |||
8843 | msg = eMouseEnterIntoWidget; | |||
8844 | } else if (aType.EqualsLiteral("mouseout")) { | |||
8845 | msg = eMouseExitFromWidget; | |||
8846 | exitFrom = Some(WidgetMouseEvent::ePlatformChild); | |||
8847 | } else if (aType.EqualsLiteral("mousecancel")) { | |||
8848 | msg = eMouseExitFromWidget; | |||
8849 | exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel | |||
8850 | : WidgetMouseEvent::ePuppet); | |||
8851 | } else if (aType.EqualsLiteral("mouselongtap")) { | |||
8852 | msg = eMouseLongTap; | |||
8853 | } else if (aType.EqualsLiteral("contextmenu")) { | |||
8854 | msg = eContextMenu; | |||
8855 | contextMenuKey = (aButton == 0); | |||
8856 | } else if (aType.EqualsLiteral("MozMouseHittest")) { | |||
8857 | msg = eMouseHitTest; | |||
8858 | } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) { | |||
8859 | msg = eMouseExploreByTouch; | |||
8860 | } else { | |||
8861 | return NS_ERROR_FAILURE; | |||
8862 | } | |||
8863 | ||||
8864 | if (aInputSourceArg == MouseEvent_Binding::MOZ_SOURCE_UNKNOWN) { | |||
8865 | aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE; | |||
8866 | } | |||
8867 | ||||
8868 | Maybe<WidgetPointerEvent> pointerEvent; | |||
8869 | Maybe<WidgetMouseEvent> mouseEvent; | |||
8870 | if (IsPointerEventMessage(msg)) { | |||
8871 | MOZ_ASSERT(!aIsWidgetEventSynthesized,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIsWidgetEventSynthesized)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIsWidgetEventSynthesized)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aIsWidgetEventSynthesized" " (" "The event shouldn't be dispatched as a synthesized event" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized" ") (" "The event shouldn't be dispatched as a synthesized event" ")"); do { *((volatile int*)__null) = 8872; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
8872 | "The event shouldn't be dispatched as a synthesized event")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIsWidgetEventSynthesized)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIsWidgetEventSynthesized)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aIsWidgetEventSynthesized" " (" "The event shouldn't be dispatched as a synthesized event" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsWidgetEventSynthesized" ") (" "The event shouldn't be dispatched as a synthesized event" ")"); do { *((volatile int*)__null) = 8872; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8873 | if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)(__builtin_expect(!!(aIsWidgetEventSynthesized), 0))) { | |||
8874 | // `click`, `auxclick` nor `contextmenu` should not be dispatched as a | |||
8875 | // synthesized event. | |||
8876 | return NS_ERROR_INVALID_ARG; | |||
8877 | } | |||
8878 | pointerEvent.emplace(true, msg, widget, | |||
8879 | contextMenuKey ? WidgetMouseEvent::eContextMenuKey | |||
8880 | : WidgetMouseEvent::eNormal); | |||
8881 | } else { | |||
8882 | mouseEvent.emplace(true, msg, widget, | |||
8883 | aIsWidgetEventSynthesized | |||
8884 | ? WidgetMouseEvent::eSynthesized | |||
8885 | : WidgetMouseEvent::eReal, | |||
8886 | contextMenuKey ? WidgetMouseEvent::eContextMenuKey | |||
8887 | : WidgetMouseEvent::eNormal); | |||
8888 | } | |||
8889 | WidgetMouseEvent& mouseOrPointerEvent = | |||
8890 | pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref(); | |||
8891 | mouseOrPointerEvent.pointerId = aIdentifier; | |||
8892 | mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers); | |||
8893 | mouseOrPointerEvent.mButton = aButton; | |||
8894 | mouseOrPointerEvent.mButtons = | |||
8895 | aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ? aButtons | |||
8896 | : msg == eMouseUp ? 0 | |||
8897 | : GetButtonsFlagForButton(aButton); | |||
8898 | mouseOrPointerEvent.mPressure = aPressure; | |||
8899 | mouseOrPointerEvent.mInputSource = aInputSourceArg; | |||
8900 | mouseOrPointerEvent.mClickCount = aClickCount; | |||
8901 | mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized; | |||
8902 | mouseOrPointerEvent.mExitFrom = exitFrom; | |||
8903 | ||||
8904 | nsPresContext* presContext = aPresShell->GetPresContext(); | |||
8905 | if (!presContext) return NS_ERROR_FAILURE; | |||
8906 | ||||
8907 | mouseOrPointerEvent.mRefPoint = | |||
8908 | ToWidgetPoint(CSSPoint(aX, aY), offset, presContext); | |||
8909 | mouseOrPointerEvent.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame; | |||
8910 | ||||
8911 | nsEventStatus status = nsEventStatus_eIgnore; | |||
8912 | if (aToWindow) { | |||
8913 | RefPtr<PresShell> presShell; | |||
8914 | nsView* view = | |||
8915 | GetViewToDispatchEvent(presContext, getter_AddRefs(presShell)); | |||
8916 | if (!presShell || !view) { | |||
8917 | return NS_ERROR_FAILURE; | |||
8918 | } | |||
8919 | return presShell->HandleEvent(view->GetFrame(), &mouseOrPointerEvent, false, | |||
8920 | &status); | |||
8921 | } | |||
8922 | if (StaticPrefs::test_events_async_enabled()) { | |||
8923 | status = widget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus; | |||
8924 | } else { | |||
8925 | nsresult rv = widget->DispatchEvent(&mouseOrPointerEvent, status); | |||
8926 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8926); return rv; } } while (false); | |||
8927 | } | |||
8928 | if (aPreventDefault) { | |||
8929 | if (status == nsEventStatus_eConsumeNoDefault) { | |||
8930 | if (mouseOrPointerEvent.mFlags.mDefaultPreventedByContent) { | |||
8931 | *aPreventDefault = PreventDefaultResult::ByContent; | |||
8932 | } else { | |||
8933 | *aPreventDefault = PreventDefaultResult::ByChrome; | |||
8934 | } | |||
8935 | } else { | |||
8936 | *aPreventDefault = PreventDefaultResult::No; | |||
8937 | } | |||
8938 | } | |||
8939 | ||||
8940 | return NS_OK; | |||
8941 | } | |||
8942 | ||||
8943 | /* static */ | |||
8944 | void nsContentUtils::FirePageHideEventForFrameLoaderSwap( | |||
8945 | nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler, | |||
8946 | bool aOnlySystemGroup) { | |||
8947 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8947); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem" ")"); do { *((volatile int*)__null) = 8947; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8948 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8948); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler" ")"); do { *((volatile int*)__null) = 8948; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
8949 | ||||
8950 | RefPtr<Document> doc = aItem->GetDocument(); | |||
8951 | NS_ASSERTION(doc, "What happened here?")do { if (!(doc)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "What happened here?" , "doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 8951); MOZ_PretendNoReturn(); } } while (0); | |||
8952 | doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup); | |||
8953 | ||||
8954 | int32_t childCount = 0; | |||
8955 | aItem->GetInProcessChildCount(&childCount); | |||
8956 | AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids; | |||
8957 | kids.AppendElements(childCount); | |||
8958 | for (int32_t i = 0; i < childCount; ++i) { | |||
8959 | aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i])); | |||
8960 | } | |||
8961 | ||||
8962 | for (uint32_t i = 0; i < kids.Length(); ++i) { | |||
8963 | if (kids[i]) { | |||
8964 | FirePageHideEventForFrameLoaderSwap(kids[i], aChromeEventHandler, | |||
8965 | aOnlySystemGroup); | |||
8966 | } | |||
8967 | } | |||
8968 | } | |||
8969 | ||||
8970 | // The pageshow event is fired for a given document only if IsShowing() returns | |||
8971 | // the same thing as aFireIfShowing. This gives us a way to fire pageshow only | |||
8972 | // on documents that are still loading or only on documents that are already | |||
8973 | // loaded. | |||
8974 | /* static */ | |||
8975 | void nsContentUtils::FirePageShowEventForFrameLoaderSwap( | |||
8976 | nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler, | |||
8977 | bool aFireIfShowing, bool aOnlySystemGroup) { | |||
8978 | int32_t childCount = 0; | |||
8979 | aItem->GetInProcessChildCount(&childCount); | |||
8980 | AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids; | |||
8981 | kids.AppendElements(childCount); | |||
8982 | for (int32_t i = 0; i < childCount; ++i) { | |||
8983 | aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i])); | |||
8984 | } | |||
8985 | ||||
8986 | for (uint32_t i = 0; i < kids.Length(); ++i) { | |||
8987 | if (kids[i]) { | |||
8988 | FirePageShowEventForFrameLoaderSwap(kids[i], aChromeEventHandler, | |||
8989 | aFireIfShowing, aOnlySystemGroup); | |||
8990 | } | |||
8991 | } | |||
8992 | ||||
8993 | RefPtr<Document> doc = aItem->GetDocument(); | |||
8994 | if (doc && doc->IsShowing() == aFireIfShowing) { | |||
8995 | doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup); | |||
8996 | } | |||
8997 | } | |||
8998 | ||||
8999 | /* static */ | |||
9000 | already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) { | |||
9001 | if (aDoc) { | |||
9002 | if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) { | |||
9003 | return win->GetTopWindowRoot(); | |||
9004 | } | |||
9005 | } | |||
9006 | return nullptr; | |||
9007 | } | |||
9008 | ||||
9009 | /* static */ | |||
9010 | bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor, | |||
9011 | nsIURI* aDocURI) { | |||
9012 | if (aAnchor.IsEmpty()) { | |||
9013 | // anchor parameter not present or empty -> same document reference | |||
9014 | return true; | |||
9015 | } | |||
9016 | ||||
9017 | // the document URI might contain a fragment identifier ("#...') | |||
9018 | // we want to ignore that because it's invisible to the server | |||
9019 | // and just affects the local interpretation in the recipient | |||
9020 | nsCOMPtr<nsIURI> contextUri; | |||
9021 | nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri)); | |||
9022 | ||||
9023 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
9024 | // copying failed | |||
9025 | return false; | |||
9026 | } | |||
9027 | ||||
9028 | // resolve anchor against context | |||
9029 | nsCOMPtr<nsIURI> resolvedUri; | |||
9030 | rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri); | |||
9031 | ||||
9032 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
9033 | // resolving failed | |||
9034 | return false; | |||
9035 | } | |||
9036 | ||||
9037 | bool same; | |||
9038 | rv = contextUri->Equals(resolvedUri, &same); | |||
9039 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
9040 | // comparison failed | |||
9041 | return false; | |||
9042 | } | |||
9043 | ||||
9044 | return same; | |||
9045 | } | |||
9046 | ||||
9047 | /* static */ | |||
9048 | bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) { | |||
9049 | return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || | |||
9050 | aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD || | |||
9051 | aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || | |||
9052 | aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD || | |||
9053 | aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD || | |||
9054 | aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD); | |||
9055 | } | |||
9056 | ||||
9057 | // static | |||
9058 | ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel( | |||
9059 | nsIChannel* aChannel) { | |||
9060 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); | |||
9061 | if (!httpChannel) { | |||
9062 | return ReferrerPolicy::_empty; | |||
9063 | } | |||
9064 | ||||
9065 | nsresult rv; | |||
9066 | nsAutoCString headerValue; | |||
9067 | rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue); | |||
9068 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) { | |||
9069 | return ReferrerPolicy::_empty; | |||
9070 | } | |||
9071 | ||||
9072 | return ReferrerInfo::ReferrerPolicyFromHeaderString( | |||
9073 | NS_ConvertUTF8toUTF16(headerValue)); | |||
9074 | } | |||
9075 | ||||
9076 | // static | |||
9077 | bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) { | |||
9078 | nsLoadFlags loadFlags = 0; | |||
9079 | aChannel->GetLoadFlags(&loadFlags); | |||
9080 | if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) { | |||
9081 | return true; | |||
9082 | } | |||
9083 | ||||
9084 | nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
9085 | nsContentPolicyType type = loadInfo->InternalContentPolicyType(); | |||
9086 | return IsNonSubresourceInternalPolicyType(type); | |||
9087 | } | |||
9088 | ||||
9089 | // static | |||
9090 | bool nsContentUtils::IsNonSubresourceInternalPolicyType( | |||
9091 | nsContentPolicyType aType) { | |||
9092 | return aType == nsIContentPolicy::TYPE_DOCUMENT || | |||
9093 | aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || | |||
9094 | aType == nsIContentPolicy::TYPE_INTERNAL_FRAME || | |||
9095 | aType == nsIContentPolicy::TYPE_INTERNAL_WORKER || | |||
9096 | aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER; | |||
9097 | } | |||
9098 | ||||
9099 | // static public | |||
9100 | bool nsContentUtils::IsThirdPartyTrackingResourceWindow( | |||
9101 | nsPIDOMWindowInner* aWindow) { | |||
9102 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { *((volatile int*)__null) = 9102; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9103 | ||||
9104 | Document* document = aWindow->GetExtantDoc(); | |||
9105 | if (!document) { | |||
9106 | return false; | |||
9107 | } | |||
9108 | ||||
9109 | nsCOMPtr<nsIClassifiedChannel> classifiedChannel = | |||
9110 | do_QueryInterface(document->GetChannel()); | |||
9111 | if (!classifiedChannel) { | |||
9112 | return false; | |||
9113 | } | |||
9114 | ||||
9115 | return classifiedChannel->IsThirdPartyTrackingResource(); | |||
9116 | } | |||
9117 | ||||
9118 | // static public | |||
9119 | bool nsContentUtils::IsFirstPartyTrackingResourceWindow( | |||
9120 | nsPIDOMWindowInner* aWindow) { | |||
9121 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { *((volatile int*)__null) = 9121; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9122 | ||||
9123 | Document* document = aWindow->GetExtantDoc(); | |||
9124 | if (!document) { | |||
9125 | return false; | |||
9126 | } | |||
9127 | ||||
9128 | nsCOMPtr<nsIClassifiedChannel> classifiedChannel = | |||
9129 | do_QueryInterface(document->GetChannel()); | |||
9130 | if (!classifiedChannel) { | |||
9131 | return false; | |||
9132 | } | |||
9133 | ||||
9134 | uint32_t classificationFlags = | |||
9135 | classifiedChannel->GetFirstPartyClassificationFlags(); | |||
9136 | ||||
9137 | return mozilla::net::UrlClassifierCommon::IsTrackingClassificationFlag( | |||
9138 | classificationFlags, NS_UsePrivateBrowsing(document->GetChannel())); | |||
9139 | } | |||
9140 | ||||
9141 | namespace { | |||
9142 | ||||
9143 | // We put StringBuilder in the anonymous namespace to prevent anything outside | |||
9144 | // this file from accidentally being linked against it. | |||
9145 | class BulkAppender { | |||
9146 | using size_type = typename nsAString::size_type; | |||
9147 | ||||
9148 | public: | |||
9149 | explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle) | |||
9150 | : mHandle(std::move(aHandle)), mPosition(0) {} | |||
9151 | ~BulkAppender() = default; | |||
9152 | ||||
9153 | template <int N> | |||
9154 | void AppendLiteral(const char16_t (&aStr)[N]) { | |||
9155 | size_t len = N - 1; | |||
9156 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"); do { *((volatile int*)__null) = 9156; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9157 | memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t)); | |||
9158 | mPosition += len; | |||
9159 | } | |||
9160 | ||||
9161 | void Append(Span<const char16_t> aStr) { | |||
9162 | size_t len = aStr.Length(); | |||
9163 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"); do { *((volatile int*)__null) = 9163; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9164 | // Both mHandle.Elements() and aStr.Elements() are guaranteed | |||
9165 | // to be non-null (by the string implementation and by Span, | |||
9166 | // respectively), so not checking the pointers for null before | |||
9167 | // memcpy does not lead to UB even if len was zero. | |||
9168 | memcpy(mHandle.Elements() + mPosition, aStr.Elements(), | |||
9169 | len * sizeof(char16_t)); | |||
9170 | mPosition += len; | |||
9171 | } | |||
9172 | ||||
9173 | void Append(Span<const char> aStr) { | |||
9174 | size_t len = aStr.Length(); | |||
9175 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"); do { *((volatile int*)__null) = 9175; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9176 | ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition)); | |||
9177 | mPosition += len; | |||
9178 | } | |||
9179 | ||||
9180 | void Finish() { mHandle.Finish(mPosition, false); } | |||
9181 | ||||
9182 | private: | |||
9183 | BulkWriteHandle<char16_t> mHandle; | |||
9184 | size_type mPosition; | |||
9185 | }; | |||
9186 | ||||
9187 | class StringBuilder { | |||
9188 | private: | |||
9189 | class Unit { | |||
9190 | public: | |||
9191 | 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<nsISupports, StringBuilder::Unit>::value , "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder::Unit" , sizeof(*this)); } while (0); } | |||
9192 | ~Unit() { | |||
9193 | if (mType == Type::String || mType == Type::StringWithEncode) { | |||
9194 | mString.~nsString(); | |||
9195 | } | |||
9196 | 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<nsISupports, StringBuilder::Unit>::value , "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder::Unit" , sizeof(*this)); } while (0); | |||
9197 | } | |||
9198 | ||||
9199 | enum class Type : uint8_t { | |||
9200 | Unknown, | |||
9201 | Atom, | |||
9202 | String, | |||
9203 | StringWithEncode, | |||
9204 | Literal, | |||
9205 | TextFragment, | |||
9206 | TextFragmentWithEncode, | |||
9207 | }; | |||
9208 | ||||
9209 | struct LiteralSpan { | |||
9210 | const char16_t* mData; | |||
9211 | uint32_t mLength; | |||
9212 | ||||
9213 | Span<const char16_t> AsSpan() { return Span(mData, mLength); } | |||
9214 | }; | |||
9215 | ||||
9216 | union { | |||
9217 | nsAtom* mAtom; | |||
9218 | LiteralSpan mLiteral; | |||
9219 | nsString mString; | |||
9220 | const nsTextFragment* mTextFragment; | |||
9221 | }; | |||
9222 | Type mType = Type::Unknown; | |||
9223 | }; | |||
9224 | ||||
9225 | static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*), | |||
9226 | "Unit should remain small"); | |||
9227 | ||||
9228 | public: | |||
9229 | // Try to keep the size of StringBuilder close to a jemalloc bucket size (the | |||
9230 | // 16kb one in this case). | |||
9231 | static constexpr uint32_t TARGET_SIZE = 16 * 1024; | |||
9232 | ||||
9233 | // The number of units we need to remove from the inline buffer so that the | |||
9234 | // rest of the builder members fit. A more precise approach would be to | |||
9235 | // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) / sizeof(Unit) | |||
9236 | // or so, but this is simpler. | |||
9237 | static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2; | |||
9238 | ||||
9239 | static constexpr uint32_t STRING_BUFFER_UNITS = | |||
9240 | TARGET_SIZE / sizeof(Unit) - PADDING_UNITS; | |||
9241 | ||||
9242 | 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); } | |||
9243 | ||||
9244 | 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); } | |||
9245 | ||||
9246 | void Append(nsAtom* aAtom) { | |||
9247 | Unit* u = AddUnit(); | |||
9248 | u->mAtom = aAtom; | |||
9249 | u->mType = Unit::Type::Atom; | |||
9250 | uint32_t len = aAtom->GetLength(); | |||
9251 | mLength += len; | |||
9252 | } | |||
9253 | ||||
9254 | template <int N> | |||
9255 | void Append(const char16_t (&aLiteral)[N]) { | |||
9256 | constexpr uint32_t len = N - 1; | |||
9257 | Unit* u = AddUnit(); | |||
9258 | u->mLiteral = {aLiteral, len}; | |||
9259 | u->mType = Unit::Type::Literal; | |||
9260 | mLength += len; | |||
9261 | } | |||
9262 | ||||
9263 | void Append(nsString&& aString) { | |||
9264 | Unit* u = AddUnit(); | |||
9265 | uint32_t len = aString.Length(); | |||
9266 | new (&u->mString) nsString(std::move(aString)); | |||
9267 | u->mType = Unit::Type::String; | |||
9268 | mLength += len; | |||
9269 | } | |||
9270 | ||||
9271 | // aLen can be !isValid(), which will get propagated into mLength. | |||
9272 | void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) { | |||
9273 | Unit* u = AddUnit(); | |||
9274 | new (&u->mString) nsString(std::move(aString)); | |||
9275 | u->mType = Unit::Type::StringWithEncode; | |||
9276 | mLength += aLen; | |||
9277 | } | |||
9278 | ||||
9279 | void Append(const nsTextFragment* aTextFragment) { | |||
9280 | Unit* u = AddUnit(); | |||
9281 | u->mTextFragment = aTextFragment; | |||
9282 | u->mType = Unit::Type::TextFragment; | |||
9283 | uint32_t len = aTextFragment->GetLength(); | |||
9284 | mLength += len; | |||
9285 | } | |||
9286 | ||||
9287 | // aLen can be !isValid(), which will get propagated into mLength. | |||
9288 | void AppendWithEncode(const nsTextFragment* aTextFragment, | |||
9289 | CheckedInt<uint32_t> aLen) { | |||
9290 | Unit* u = AddUnit(); | |||
9291 | u->mTextFragment = aTextFragment; | |||
9292 | u->mType = Unit::Type::TextFragmentWithEncode; | |||
9293 | mLength += aLen; | |||
9294 | } | |||
9295 | ||||
9296 | bool ToString(nsAString& aOut) { | |||
9297 | if (!mLength.isValid()) { | |||
9298 | return false; | |||
9299 | } | |||
9300 | auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true); | |||
9301 | if (appenderOrErr.isErr()) { | |||
9302 | return false; | |||
9303 | } | |||
9304 | ||||
9305 | BulkAppender appender{appenderOrErr.unwrap()}; | |||
9306 | ||||
9307 | for (StringBuilder* current = this; current; | |||
9308 | current = current->mNext.get()) { | |||
9309 | uint32_t len = current->mUnits.Length(); | |||
9310 | for (uint32_t i = 0; i < len; ++i) { | |||
9311 | Unit& u = current->mUnits[i]; | |||
9312 | switch (u.mType) { | |||
9313 | case Unit::Type::Atom: | |||
9314 | appender.Append(*(u.mAtom)); | |||
9315 | break; | |||
9316 | case Unit::Type::String: | |||
9317 | appender.Append(u.mString); | |||
9318 | break; | |||
9319 | case Unit::Type::StringWithEncode: | |||
9320 | EncodeAttrString(u.mString, appender); | |||
9321 | break; | |||
9322 | case Unit::Type::Literal: | |||
9323 | appender.Append(u.mLiteral.AsSpan()); | |||
9324 | break; | |||
9325 | case Unit::Type::TextFragment: | |||
9326 | if (u.mTextFragment->Is2b()) { | |||
9327 | appender.Append( | |||
9328 | Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength())); | |||
9329 | } else { | |||
9330 | appender.Append( | |||
9331 | Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength())); | |||
9332 | } | |||
9333 | break; | |||
9334 | case Unit::Type::TextFragmentWithEncode: | |||
9335 | if (u.mTextFragment->Is2b()) { | |||
9336 | EncodeTextFragment( | |||
9337 | Span(u.mTextFragment->Get2b(), u.mTextFragment->GetLength()), | |||
9338 | appender); | |||
9339 | } else { | |||
9340 | EncodeTextFragment( | |||
9341 | Span(u.mTextFragment->Get1b(), u.mTextFragment->GetLength()), | |||
9342 | appender); | |||
9343 | } | |||
9344 | break; | |||
9345 | default: | |||
9346 | MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9346); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown unit type?" ")"); do { *((volatile int*)__null) = 9346; __attribute__((nomerge )) ::abort(); } while (false); } while (false); | |||
9347 | } | |||
9348 | } | |||
9349 | } | |||
9350 | appender.Finish(); | |||
9351 | return true; | |||
9352 | } | |||
9353 | ||||
9354 | private: | |||
9355 | Unit* AddUnit() { | |||
9356 | if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) { | |||
9357 | new StringBuilder(this); | |||
9358 | } | |||
9359 | return mLast->mUnits.AppendElement(); | |||
9360 | } | |||
9361 | ||||
9362 | explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) { | |||
9363 | 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<nsISupports, StringBuilder>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder", sizeof(*this)); } while (0); | |||
9364 | aFirst->mLast->mNext = WrapUnique(this); | |||
9365 | aFirst->mLast = this; | |||
9366 | } | |||
9367 | ||||
9368 | void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) { | |||
9369 | size_t flushedUntil = 0; | |||
9370 | size_t currentPosition = 0; | |||
9371 | for (char16_t c : aStr) { | |||
9372 | switch (c) { | |||
9373 | case '"': | |||
9374 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9375 | aAppender.AppendLiteral(u"""); | |||
9376 | flushedUntil = currentPosition + 1; | |||
9377 | break; | |||
9378 | case '&': | |||
9379 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9380 | aAppender.AppendLiteral(u"&"); | |||
9381 | flushedUntil = currentPosition + 1; | |||
9382 | break; | |||
9383 | case 0x00A0: | |||
9384 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9385 | aAppender.AppendLiteral(u" "); | |||
9386 | flushedUntil = currentPosition + 1; | |||
9387 | break; | |||
9388 | default: | |||
9389 | break; | |||
9390 | } | |||
9391 | currentPosition++; | |||
9392 | } | |||
9393 | if (currentPosition > flushedUntil) { | |||
9394 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9395 | } | |||
9396 | } | |||
9397 | ||||
9398 | template <class T> | |||
9399 | void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) { | |||
9400 | size_t flushedUntil = 0; | |||
9401 | size_t currentPosition = 0; | |||
9402 | for (T c : aStr) { | |||
9403 | switch (c) { | |||
9404 | case '<': | |||
9405 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9406 | aAppender.AppendLiteral(u"<"); | |||
9407 | flushedUntil = currentPosition + 1; | |||
9408 | break; | |||
9409 | case '>': | |||
9410 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9411 | aAppender.AppendLiteral(u">"); | |||
9412 | flushedUntil = currentPosition + 1; | |||
9413 | break; | |||
9414 | case '&': | |||
9415 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9416 | aAppender.AppendLiteral(u"&"); | |||
9417 | flushedUntil = currentPosition + 1; | |||
9418 | break; | |||
9419 | case T(0xA0): | |||
9420 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9421 | aAppender.AppendLiteral(u" "); | |||
9422 | flushedUntil = currentPosition + 1; | |||
9423 | break; | |||
9424 | default: | |||
9425 | break; | |||
9426 | } | |||
9427 | currentPosition++; | |||
9428 | } | |||
9429 | if (currentPosition > flushedUntil) { | |||
9430 | aAppender.Append(aStr.FromTo(flushedUntil, currentPosition)); | |||
9431 | } | |||
9432 | } | |||
9433 | ||||
9434 | AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits; | |||
9435 | UniquePtr<StringBuilder> mNext; | |||
9436 | StringBuilder* mLast; | |||
9437 | // mLength is used only in the first StringBuilder object in the linked list. | |||
9438 | CheckedInt<uint32_t> mLength; | |||
9439 | }; | |||
9440 | ||||
9441 | static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE, | |||
9442 | "StringBuilder should fit in the target bucket"); | |||
9443 | ||||
9444 | } // namespace | |||
9445 | ||||
9446 | static void AppendEncodedCharacters(const nsTextFragment* aText, | |||
9447 | StringBuilder& aBuilder) { | |||
9448 | uint32_t numEncodedChars = 0; | |||
9449 | uint32_t len = aText->GetLength(); | |||
9450 | if (aText->Is2b()) { | |||
9451 | const char16_t* data = aText->Get2b(); | |||
9452 | for (uint32_t i = 0; i < len; ++i) { | |||
9453 | const char16_t c = data[i]; | |||
9454 | switch (c) { | |||
9455 | case '<': | |||
9456 | case '>': | |||
9457 | case '&': | |||
9458 | case 0x00A0: | |||
9459 | ++numEncodedChars; | |||
9460 | break; | |||
9461 | default: | |||
9462 | break; | |||
9463 | } | |||
9464 | } | |||
9465 | } else { | |||
9466 | const char* data = aText->Get1b(); | |||
9467 | for (uint32_t i = 0; i < len; ++i) { | |||
9468 | const unsigned char c = data[i]; | |||
9469 | switch (c) { | |||
9470 | case '<': | |||
9471 | case '>': | |||
9472 | case '&': | |||
9473 | case 0x00A0: | |||
9474 | ++numEncodedChars; | |||
9475 | break; | |||
9476 | default: | |||
9477 | break; | |||
9478 | } | |||
9479 | } | |||
9480 | } | |||
9481 | ||||
9482 | if (numEncodedChars) { | |||
9483 | // For simplicity, conservatively estimate the size of the string after | |||
9484 | // encoding. This will result in reserving more memory than we actually | |||
9485 | // need, but that should be fine unless the string has an enormous number of | |||
9486 | // eg < in it. We subtract 1 for the null terminator, then 1 more for the | |||
9487 | // existing character that will be replaced. | |||
9488 | constexpr uint32_t maxCharExtraSpace = | |||
9489 | std::max({ArrayLength("<"), ArrayLength(">"), | |||
9490 | ArrayLength("&"), ArrayLength(" ")}) - | |||
9491 | 2; | |||
9492 | static_assert(maxCharExtraSpace < 100, "Possible underflow"); | |||
9493 | CheckedInt<uint32_t> maxExtraSpace = | |||
9494 | CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace; | |||
9495 | aBuilder.AppendWithEncode(aText, maxExtraSpace + len); | |||
9496 | } else { | |||
9497 | aBuilder.Append(aText); | |||
9498 | } | |||
9499 | } | |||
9500 | ||||
9501 | static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding( | |||
9502 | const nsAString& aValue) { | |||
9503 | const char16_t* c = aValue.BeginReading(); | |||
9504 | const char16_t* end = aValue.EndReading(); | |||
9505 | ||||
9506 | uint32_t numEncodedChars = 0; | |||
9507 | while (c < end) { | |||
9508 | switch (*c) { | |||
9509 | case '"': | |||
9510 | case '&': | |||
9511 | case 0x00A0: | |||
9512 | ++numEncodedChars; | |||
9513 | break; | |||
9514 | default: | |||
9515 | break; | |||
9516 | } | |||
9517 | ++c; | |||
9518 | } | |||
9519 | ||||
9520 | if (!numEncodedChars) { | |||
9521 | return 0; | |||
9522 | } | |||
9523 | ||||
9524 | // For simplicity, conservatively estimate the size of the string after | |||
9525 | // encoding. This will result in reserving more memory than we actually | |||
9526 | // need, but that should be fine unless the string has an enormous number of | |||
9527 | // & in it. We subtract 1 for the null terminator, then 1 more for the | |||
9528 | // existing character that will be replaced. | |||
9529 | constexpr uint32_t maxCharExtraSpace = | |||
9530 | std::max({ArrayLength("""), ArrayLength("&"), | |||
9531 | ArrayLength(" ")}) - | |||
9532 | 2; | |||
9533 | static_assert(maxCharExtraSpace < 100, "Possible underflow"); | |||
9534 | return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace; | |||
9535 | } | |||
9536 | ||||
9537 | static void AppendEncodedAttributeValue(const nsAttrValue& aValue, | |||
9538 | StringBuilder& aBuilder) { | |||
9539 | if (nsAtom* atom = aValue.GetStoredAtom()) { | |||
9540 | nsDependentAtomString atomStr(atom); | |||
9541 | auto space = ExtraSpaceNeededForAttrEncoding(atomStr); | |||
9542 | if (space.isValid() && !space.value()) { | |||
9543 | aBuilder.Append(atom); | |||
9544 | } else { | |||
9545 | aBuilder.AppendWithAttrEncode(nsString(atomStr), | |||
9546 | space + atomStr.Length()); | |||
9547 | } | |||
9548 | return; | |||
9549 | } | |||
9550 | // NOTE(emilio): In most cases this will just be a reference to the stored | |||
9551 | // nsStringBuffer. | |||
9552 | nsString str; | |||
9553 | aValue.ToString(str); | |||
9554 | auto space = ExtraSpaceNeededForAttrEncoding(str); | |||
9555 | if (!space.isValid() || space.value()) { | |||
9556 | aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length()); | |||
9557 | } else { | |||
9558 | aBuilder.Append(std::move(str)); | |||
9559 | } | |||
9560 | } | |||
9561 | ||||
9562 | static void StartElement(Element* aElement, StringBuilder& aBuilder) { | |||
9563 | nsAtom* localName = aElement->NodeInfo()->NameAtom(); | |||
9564 | const int32_t tagNS = aElement->GetNameSpaceID(); | |||
9565 | ||||
9566 | aBuilder.Append(u"<"); | |||
9567 | if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 || | |||
9568 | tagNS == kNameSpaceID_MathML6) { | |||
9569 | aBuilder.Append(localName); | |||
9570 | } else { | |||
9571 | aBuilder.Append(nsString(aElement->NodeName())); | |||
9572 | } | |||
9573 | ||||
9574 | if (CustomElementData* ceData = aElement->GetCustomElementData()) { | |||
9575 | nsAtom* isAttr = ceData->GetIs(aElement); | |||
9576 | if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) { | |||
9577 | aBuilder.Append(uR"( is=")"); | |||
9578 | aBuilder.Append(isAttr); | |||
9579 | aBuilder.Append(uR"(")"); | |||
9580 | } | |||
9581 | } | |||
9582 | ||||
9583 | uint32_t i = 0; | |||
9584 | while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) { | |||
9585 | const nsAttrName* name = info.mName; | |||
9586 | ||||
9587 | int32_t attNs = name->NamespaceID(); | |||
9588 | nsAtom* attName = name->LocalName(); | |||
9589 | ||||
9590 | // Filter out any attribute starting with [-|_]moz | |||
9591 | // FIXME(emilio): Do we still need this? | |||
9592 | nsDependentAtomString attrNameStr(attName); | |||
9593 | if (StringBeginsWith(attrNameStr, u"_moz"_ns) || | |||
9594 | StringBeginsWith(attrNameStr, u"-moz"_ns)) { | |||
9595 | continue; | |||
9596 | } | |||
9597 | ||||
9598 | aBuilder.Append(u" "); | |||
9599 | ||||
9600 | if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) || | |||
9601 | (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) { | |||
9602 | // Nothing else required | |||
9603 | } else if (attNs == kNameSpaceID_XML2) { | |||
9604 | aBuilder.Append(u"xml:"); | |||
9605 | } else if (attNs == kNameSpaceID_XMLNS1) { | |||
9606 | aBuilder.Append(u"xmlns:"); | |||
9607 | } else if (attNs == kNameSpaceID_XLink4) { | |||
9608 | aBuilder.Append(u"xlink:"); | |||
9609 | } else if (nsAtom* prefix = name->GetPrefix()) { | |||
9610 | aBuilder.Append(prefix); | |||
9611 | aBuilder.Append(u":"); | |||
9612 | } | |||
9613 | ||||
9614 | aBuilder.Append(attName); | |||
9615 | aBuilder.Append(uR"(=")"); | |||
9616 | AppendEncodedAttributeValue(*info.mValue, aBuilder); | |||
9617 | aBuilder.Append(uR"(")"); | |||
9618 | } | |||
9619 | ||||
9620 | aBuilder.Append(u">"); | |||
9621 | ||||
9622 | /* | |||
9623 | // Per HTML spec we should append one \n if the first child of | |||
9624 | // pre/textarea/listing is a textnode and starts with a \n. | |||
9625 | // But because browsers haven't traditionally had that behavior, | |||
9626 | // we're not changing our behavior either - yet. | |||
9627 | if (aContent->IsHTMLElement()) { | |||
9628 | if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea || | |||
9629 | localName == nsGkAtoms::listing) { | |||
9630 | nsIContent* fc = aContent->GetFirstChild(); | |||
9631 | if (fc && | |||
9632 | (fc->NodeType() == nsINode::TEXT_NODE || | |||
9633 | fc->NodeType() == nsINode::CDATA_SECTION_NODE)) { | |||
9634 | const nsTextFragment* text = fc->GetText(); | |||
9635 | if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) { | |||
9636 | aBuilder.Append("\n"); | |||
9637 | } | |||
9638 | } | |||
9639 | } | |||
9640 | }*/ | |||
9641 | } | |||
9642 | ||||
9643 | static inline bool ShouldEscape(nsIContent* aParent) { | |||
9644 | if (!aParent || !aParent->IsHTMLElement()) { | |||
9645 | return true; | |||
9646 | } | |||
9647 | ||||
9648 | static const nsAtom* nonEscapingElements[] = { | |||
9649 | nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp, | |||
9650 | nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes, | |||
9651 | nsGkAtoms::plaintext, nsGkAtoms::noscript}; | |||
9652 | static mozilla::BitBloomFilter<12, nsAtom> sFilter; | |||
9653 | static bool sInitialized = false; | |||
9654 | if (!sInitialized) { | |||
9655 | sInitialized = true; | |||
9656 | for (auto& nonEscapingElement : nonEscapingElements) { | |||
9657 | sFilter.add(nonEscapingElement); | |||
9658 | } | |||
9659 | } | |||
9660 | ||||
9661 | nsAtom* tag = aParent->NodeInfo()->NameAtom(); | |||
9662 | if (sFilter.mightContain(tag)) { | |||
9663 | for (auto& nonEscapingElement : nonEscapingElements) { | |||
9664 | if (tag == nonEscapingElement) { | |||
9665 | if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) && | |||
9666 | MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled ()), 0))) { | |||
9667 | return true; | |||
9668 | } | |||
9669 | return false; | |||
9670 | } | |||
9671 | } | |||
9672 | } | |||
9673 | return true; | |||
9674 | } | |||
9675 | ||||
9676 | static inline bool IsVoidTag(Element* aElement) { | |||
9677 | if (!aElement->IsHTMLElement()) { | |||
9678 | return false; | |||
9679 | } | |||
9680 | return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom()); | |||
9681 | } | |||
9682 | ||||
9683 | static bool StartSerializingShadowDOM( | |||
9684 | nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots, | |||
9685 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
9686 | ShadowRoot* shadow = aNode->GetShadowRoot(); | |||
9687 | if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) && | |||
9688 | !aShadowRoots.Contains(shadow))) { | |||
9689 | return false; | |||
9690 | } | |||
9691 | ||||
9692 | aBuilder.Append(u"<template shadowrootmode=\""); | |||
9693 | if (shadow->IsClosed()) { | |||
9694 | aBuilder.Append(u"closed\""); | |||
9695 | } else { | |||
9696 | aBuilder.Append(u"open\""); | |||
9697 | } | |||
9698 | ||||
9699 | if (shadow->DelegatesFocus()) { | |||
9700 | aBuilder.Append(u" shadowrootdelegatesfocus=\"\""); | |||
9701 | } | |||
9702 | if (shadow->Serializable()) { | |||
9703 | aBuilder.Append(u" shadowrootserializable=\"\""); | |||
9704 | } | |||
9705 | if (shadow->Clonable()) { | |||
9706 | aBuilder.Append(u" shadowrootclonable=\"\""); | |||
9707 | } | |||
9708 | ||||
9709 | aBuilder.Append(u">"); | |||
9710 | ||||
9711 | if (!shadow->HasChildren()) { | |||
9712 | aBuilder.Append(u"</template>"); | |||
9713 | return false; | |||
9714 | } | |||
9715 | return true; | |||
9716 | } | |||
9717 | ||||
9718 | template <SerializeShadowRoots ShouldSerializeShadowRoots> | |||
9719 | static void SerializeNodeToMarkupInternal( | |||
9720 | nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder, | |||
9721 | bool aSerializableShadowRoots, | |||
9722 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
9723 | nsINode* current = | |||
9724 | aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot; | |||
9725 | if (!current) { | |||
9726 | return; | |||
9727 | } | |||
9728 | ||||
9729 | nsIContent* next; | |||
9730 | while (true) { | |||
9731 | bool isVoid = false; | |||
9732 | switch (current->NodeType()) { | |||
9733 | case nsINode::ELEMENT_NODE: { | |||
9734 | Element* elem = current->AsElement(); | |||
9735 | StartElement(elem, aBuilder); | |||
9736 | ||||
9737 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
9738 | if (StartSerializingShadowDOM( | |||
9739 | current, aBuilder, aSerializableShadowRoots, aShadowRoots)) { | |||
9740 | current = current->GetShadowRoot()->GetFirstChild(); | |||
9741 | continue; | |||
9742 | } | |||
9743 | } | |||
9744 | ||||
9745 | isVoid = IsVoidTag(elem); | |||
9746 | if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) { | |||
9747 | current = next; | |||
9748 | continue; | |||
9749 | } | |||
9750 | break; | |||
9751 | } | |||
9752 | ||||
9753 | case nsINode::TEXT_NODE: | |||
9754 | case nsINode::CDATA_SECTION_NODE: { | |||
9755 | const nsTextFragment* text = ¤t->AsText()->TextFragment(); | |||
9756 | nsIContent* parent = current->GetParent(); | |||
9757 | if (ShouldEscape(parent)) { | |||
9758 | AppendEncodedCharacters(text, aBuilder); | |||
9759 | } else { | |||
9760 | aBuilder.Append(text); | |||
9761 | } | |||
9762 | break; | |||
9763 | } | |||
9764 | ||||
9765 | case nsINode::COMMENT_NODE: { | |||
9766 | aBuilder.Append(u"<!--"); | |||
9767 | aBuilder.Append(static_cast<nsIContent*>(current)->GetText()); | |||
9768 | aBuilder.Append(u"-->"); | |||
9769 | break; | |||
9770 | } | |||
9771 | ||||
9772 | case nsINode::DOCUMENT_TYPE_NODE: { | |||
9773 | aBuilder.Append(u"<!DOCTYPE "); | |||
9774 | aBuilder.Append(nsString(current->NodeName())); | |||
9775 | aBuilder.Append(u">"); | |||
9776 | break; | |||
9777 | } | |||
9778 | ||||
9779 | case nsINode::PROCESSING_INSTRUCTION_NODE: { | |||
9780 | aBuilder.Append(u"<?"); | |||
9781 | aBuilder.Append(nsString(current->NodeName())); | |||
9782 | aBuilder.Append(u" "); | |||
9783 | aBuilder.Append(static_cast<nsIContent*>(current)->GetText()); | |||
9784 | aBuilder.Append(u">"); | |||
9785 | break; | |||
9786 | } | |||
9787 | } | |||
9788 | ||||
9789 | while (true) { | |||
9790 | if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) { | |||
9791 | aBuilder.Append(u"</"); | |||
9792 | nsIContent* elem = static_cast<nsIContent*>(current); | |||
9793 | if (elem->IsHTMLElement() || elem->IsSVGElement() || | |||
9794 | elem->IsMathMLElement()) { | |||
9795 | aBuilder.Append(elem->NodeInfo()->NameAtom()); | |||
9796 | } else { | |||
9797 | aBuilder.Append(nsString(current->NodeName())); | |||
9798 | } | |||
9799 | aBuilder.Append(u">"); | |||
9800 | } | |||
9801 | isVoid = false; | |||
9802 | ||||
9803 | if (current == aRoot) { | |||
9804 | return; | |||
9805 | } | |||
9806 | ||||
9807 | if ((next = current->GetNextSibling())) { | |||
9808 | current = next; | |||
9809 | break; | |||
9810 | } | |||
9811 | ||||
9812 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
9813 | // If the current node is a shadow root, then we must go to its host. | |||
9814 | // Since shadow DOMs are serialized declaratively as template elements, | |||
9815 | // we serialize the end tag of the template before going back to | |||
9816 | // serializing the shadow host. | |||
9817 | if (current->IsShadowRoot()) { | |||
9818 | current = current->GetContainingShadowHost(); | |||
9819 | aBuilder.Append(u"</template>"); | |||
9820 | ||||
9821 | if (current->HasChildren()) { | |||
9822 | current = current->GetFirstChildOfTemplateOrNode(); | |||
9823 | break; | |||
9824 | } | |||
9825 | continue; | |||
9826 | } | |||
9827 | } | |||
9828 | ||||
9829 | current = current->GetParentNode(); | |||
9830 | ||||
9831 | // Handle template element. If the parent is a template's content, | |||
9832 | // then adjust the parent to be the template element. | |||
9833 | if (current != aRoot && | |||
9834 | current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) { | |||
9835 | DocumentFragment* frag = static_cast<DocumentFragment*>(current); | |||
9836 | nsIContent* fragHost = frag->GetHost(); | |||
9837 | if (fragHost && fragHost->IsTemplateElement()) { | |||
9838 | current = fragHost; | |||
9839 | } | |||
9840 | } | |||
9841 | ||||
9842 | if (aDescendantsOnly && current == aRoot) { | |||
9843 | return; | |||
9844 | } | |||
9845 | } | |||
9846 | } | |||
9847 | } | |||
9848 | ||||
9849 | template <SerializeShadowRoots ShouldSerializeShadowRoots> | |||
9850 | bool nsContentUtils::SerializeNodeToMarkup( | |||
9851 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
9852 | bool aSerializableShadowRoots, | |||
9853 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) { | |||
9854 | // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true | |||
9855 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE" ")"); do { *((volatile int*)__null) = 9855; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9856 | ||||
9857 | StringBuilder builder; | |||
9858 | if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) { | |||
9859 | if (aDescendantsOnly && | |||
9860 | StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots, | |||
9861 | aShadowRoots)) { | |||
9862 | SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>( | |||
9863 | aRoot->GetShadowRoot()->GetFirstChild(), false, builder, | |||
9864 | aSerializableShadowRoots, aShadowRoots); | |||
9865 | // The template tag is opened in StartSerializingShadowDOM, so we need | |||
9866 | // to close it here before serializing any children of aRoot. | |||
9867 | builder.Append(u"</template>"); | |||
9868 | } | |||
9869 | } | |||
9870 | ||||
9871 | SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>( | |||
9872 | aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots); | |||
9873 | return builder.ToString(aOut); | |||
9874 | } | |||
9875 | ||||
9876 | template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>( | |||
9877 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
9878 | bool aSerializableShadowRoots, | |||
9879 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots); | |||
9880 | template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>( | |||
9881 | nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut, | |||
9882 | bool aSerializableShadowRoots, | |||
9883 | const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots); | |||
9884 | ||||
9885 | bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) { | |||
9886 | // aUri must start with about: or this isn't the right function to be using. | |||
9887 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0" ")"); do { *((volatile int*)__null) = 9887; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9888 | ||||
9889 | // Make sure the global is a window | |||
9890 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9890); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)" ")"); do { *((volatile int*)__null) = 9890; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
9891 | nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal); | |||
9892 | if (!win) { | |||
9893 | return false; | |||
9894 | } | |||
9895 | ||||
9896 | nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal(); | |||
9897 | NS_ENSURE_TRUE(principal, false)do { if ((__builtin_expect(!!(!(principal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principal" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 9897); return false; } } while (false); | |||
9898 | ||||
9899 | // First check the scheme to avoid getting long specs in the common case. | |||
9900 | if (!principal->SchemeIs("about")) { | |||
9901 | return false; | |||
9902 | } | |||
9903 | ||||
9904 | nsAutoCString spec; | |||
9905 | principal->GetAsciiSpec(spec); | |||
9906 | ||||
9907 | return spec.EqualsASCII(aUri); | |||
9908 | } | |||
9909 | ||||
9910 | /* static */ | |||
9911 | void nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell, | |||
9912 | bool aVisible) { | |||
9913 | if (!aDocShell) { | |||
9914 | return; | |||
9915 | } | |||
9916 | auto pref = aVisible ? ScrollbarPreference::Auto : ScrollbarPreference::Never; | |||
9917 | nsDocShell::Cast(aDocShell)->SetScrollbarPreference(pref); | |||
9918 | } | |||
9919 | ||||
9920 | /* static */ | |||
9921 | nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) { | |||
9922 | if (!aTarget) { | |||
9923 | return nullptr; | |||
9924 | } | |||
9925 | ||||
9926 | nsCOMPtr<nsPIDOMWindowInner> innerWindow; | |||
9927 | if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) { | |||
9928 | bool ignore; | |||
9929 | innerWindow = | |||
9930 | do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore)); | |||
9931 | } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) { | |||
9932 | // Nothing else to do | |||
9933 | } else if (nsCOMPtr<DOMEventTargetHelper> helper = | |||
9934 | do_QueryInterface(aTarget)) { | |||
9935 | innerWindow = helper->GetOwnerWindow(); | |||
9936 | } | |||
9937 | ||||
9938 | if (innerWindow) { | |||
9939 | return innerWindow->GetDocShell(); | |||
9940 | } | |||
9941 | ||||
9942 | return nullptr; | |||
9943 | } | |||
9944 | ||||
9945 | /* | |||
9946 | * Note: this function only relates to figuring out HTTPS state, which is an | |||
9947 | * input to the Secure Context algorithm. We are not actually implementing any | |||
9948 | * part of the Secure Context algorithm itself here. | |||
9949 | * | |||
9950 | * This is a bit of a hack. Ideally we'd propagate HTTPS state through | |||
9951 | * nsIChannel as described in the Fetch and HTML specs, but making channels | |||
9952 | * know about whether they should inherit HTTPS state, propagating information | |||
9953 | * about who the channel's "client" is, exposing GetHttpsState API on channels | |||
9954 | * and modifying the various cache implementations to store and retrieve HTTPS | |||
9955 | * state involves a huge amount of code (see bug 1220687). We avoid that for | |||
9956 | * now using this function. | |||
9957 | * | |||
9958 | * This function takes advantage of the observation that we can return true if | |||
9959 | * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for | |||
9960 | * the document's origin (e.g. the origin has a scheme of 'https' or host | |||
9961 | * 'localhost' etc.). Since we generally propagate a creator document's origin | |||
9962 | * onto data:, blob:, etc. documents, this works for them too. | |||
9963 | * | |||
9964 | * The scenario where this observation breaks down is sandboxing without the | |||
9965 | * 'allow-same-origin' flag, since in this case a document is given a unique | |||
9966 | * origin (IsOriginPotentiallyTrustworthy would return false). We handle that | |||
9967 | * by using the origin that the document would have had had it not been | |||
9968 | * sandboxed. | |||
9969 | * | |||
9970 | * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's | |||
9971 | * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of | |||
9972 | * sandboxing is limited to the immediate sandbox. In the case that aDocument | |||
9973 | * should inherit its origin (e.g. data: URI) but its parent has ended up | |||
9974 | * with a unique origin due to sandboxing further up the parent chain we may | |||
9975 | * end up returning false when we would ideally return true (since we will | |||
9976 | * examine the parent's origin for 'https' and not finding it.) This means | |||
9977 | * that we may restrict the privileges of some pages unnecessarily in this | |||
9978 | * edge case. | |||
9979 | */ | |||
9980 | /* static */ | |||
9981 | bool nsContentUtils::HttpsStateIsModern(Document* aDocument) { | |||
9982 | if (!aDocument) { | |||
9983 | return false; | |||
9984 | } | |||
9985 | ||||
9986 | nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal(); | |||
9987 | ||||
9988 | if (principal->IsSystemPrincipal()) { | |||
9989 | return true; | |||
9990 | } | |||
9991 | ||||
9992 | // If aDocument is sandboxed, try and get the principal that it would have | |||
9993 | // been given had it not been sandboxed: | |||
9994 | if (principal->GetIsNullPrincipal() && | |||
9995 | (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) { | |||
9996 | nsIChannel* channel = aDocument->GetChannel(); | |||
9997 | if (channel) { | |||
9998 | nsCOMPtr<nsIScriptSecurityManager> ssm = | |||
9999 | nsContentUtils::GetSecurityManager(); | |||
10000 | nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed( | |||
10001 | channel, getter_AddRefs(principal)); | |||
10002 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
10003 | return false; | |||
10004 | } | |||
10005 | if (principal->IsSystemPrincipal()) { | |||
10006 | // If a document with the system principal is sandboxing a subdocument | |||
10007 | // that would normally inherit the embedding element's principal (e.g. | |||
10008 | // a srcdoc document) then the embedding document does not trust the | |||
10009 | // content that is written to the embedded document. Unlike when the | |||
10010 | // embedding document is https, in this case we have no indication as | |||
10011 | // to whether the embedded document's contents are delivered securely | |||
10012 | // or not, and the sandboxing would possibly indicate that they were | |||
10013 | // not. To play it safe we return false here. (See bug 1162772 | |||
10014 | // comment 73-80.) | |||
10015 | return false; | |||
10016 | } | |||
10017 | } | |||
10018 | } | |||
10019 | ||||
10020 | if (principal->GetIsNullPrincipal()) { | |||
10021 | return false; | |||
10022 | } | |||
10023 | ||||
10024 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()" ")"); do { *((volatile int*)__null) = 10024; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10025 | ||||
10026 | return principal->GetIsOriginPotentiallyTrustworthy(); | |||
10027 | } | |||
10028 | ||||
10029 | /* static */ | |||
10030 | bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) { | |||
10031 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")" ); do { *((volatile int*)__null) = 10031; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10032 | ||||
10033 | nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager(); | |||
10034 | nsCOMPtr<nsIPrincipal> principal; | |||
10035 | nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed( | |||
10036 | aChannel, getter_AddRefs(principal)); | |||
10037 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
10038 | return false; | |||
10039 | } | |||
10040 | ||||
10041 | const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); | |||
10042 | ||||
10043 | if (principal->IsSystemPrincipal()) { | |||
10044 | // If the load would've been sandboxed, treat this load as an untrusted | |||
10045 | // load, as system code considers sandboxed resources insecure. | |||
10046 | return !loadInfo->GetLoadingSandboxed(); | |||
10047 | } | |||
10048 | ||||
10049 | if (principal->GetIsNullPrincipal()) { | |||
10050 | return false; | |||
10051 | } | |||
10052 | ||||
10053 | if (const RefPtr<WindowContext> windowContext = | |||
10054 | WindowContext::GetById(loadInfo->GetInnerWindowID())) { | |||
10055 | if (!windowContext->GetIsSecureContext()) { | |||
10056 | return false; | |||
10057 | } | |||
10058 | } | |||
10059 | ||||
10060 | return principal->GetIsOriginPotentiallyTrustworthy(); | |||
10061 | } | |||
10062 | ||||
10063 | /* static */ | |||
10064 | void nsContentUtils::TryToUpgradeElement(Element* aElement) { | |||
10065 | NodeInfo* nodeInfo = aElement->NodeInfo(); | |||
10066 | RefPtr<nsAtom> typeAtom = | |||
10067 | aElement->GetCustomElementData()->GetCustomElementType(); | |||
10068 | ||||
10069 | 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())" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" ")"); do { *((volatile int*)__null) = 10069; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10070 | CustomElementDefinition* definition = | |||
10071 | nsContentUtils::LookupCustomElementDefinition( | |||
10072 | nodeInfo->GetDocument(), nodeInfo->NameAtom(), | |||
10073 | nodeInfo->NamespaceID(), typeAtom); | |||
10074 | if (definition) { | |||
10075 | nsContentUtils::EnqueueUpgradeReaction(aElement, definition); | |||
10076 | } else { | |||
10077 | // Add an unresolved custom element that is a candidate for upgrade when a | |||
10078 | // custom element is connected to the document. | |||
10079 | nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom); | |||
10080 | } | |||
10081 | } | |||
10082 | ||||
10083 | MOZ_CAN_RUN_SCRIPT | |||
10084 | static void DoCustomElementCreate(Element** aElement, JSContext* aCx, | |||
10085 | Document* aDoc, NodeInfo* aNodeInfo, | |||
10086 | CustomElementConstructor* aConstructor, | |||
10087 | ErrorResult& aRv, FromParser aFromParser) { | |||
10088 | JS::Rooted<JS::Value> constructResult(aCx); | |||
10089 | aConstructor->Construct(&constructResult, aRv, "Custom Element Create", | |||
10090 | CallbackFunction::eRethrowExceptions); | |||
10091 | if (aRv.Failed()) { | |||
10092 | return; | |||
10093 | } | |||
10094 | ||||
10095 | RefPtr<Element> element; | |||
10096 | // constructResult is an ObjectValue because construction with a callback | |||
10097 | // always forms the return value from a JSObject. | |||
10098 | UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts < mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding ::NativeType>(&constructResult, element); | |||
10099 | if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10100 | if (!element || !element->IsHTMLElement()) { | |||
10101 | aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"", | |||
10102 | "HTMLElement"); | |||
10103 | return; | |||
10104 | } | |||
10105 | } else { | |||
10106 | if (!element || !element->IsXULElement()) { | |||
10107 | aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"", | |||
10108 | "XULElement"); | |||
10109 | return; | |||
10110 | } | |||
10111 | } | |||
10112 | ||||
10113 | nsAtom* localName = aNodeInfo->NameAtom(); | |||
10114 | ||||
10115 | if (aDoc != element->OwnerDoc() || element->GetParentNode() || | |||
10116 | element->HasChildren() || element->GetAttrCount() || | |||
10117 | element->NodeInfo()->NameAtom() != localName) { | |||
10118 | aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); | |||
10119 | return; | |||
10120 | } | |||
10121 | ||||
10122 | if (element->IsHTMLElement()) { | |||
10123 | static_cast<HTMLElement*>(&*element)->InhibitRestoration( | |||
10124 | !(aFromParser & FROM_PARSER_NETWORK)); | |||
10125 | } | |||
10126 | ||||
10127 | element.forget(aElement); | |||
10128 | } | |||
10129 | ||||
10130 | /* static */ | |||
10131 | nsresult nsContentUtils::NewXULOrHTMLElement( | |||
10132 | Element** aResult, mozilla::dom::NodeInfo* aNodeInfo, | |||
10133 | FromParser aFromParser, nsAtom* aIsAtom, | |||
10134 | mozilla::dom::CustomElementDefinition* aDefinition) { | |||
10135 | RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo; | |||
10136 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { *( (volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) | |||
| ||||
10137 | 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { *( (volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) | |||
10138 | "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)" ") (" "Can only create XUL or XHTML elements." ")"); do { *( (volatile int*)__null) = 10138; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); | |||
10139 | ||||
10140 | nsAtom* name = nodeInfo->NameAtom(); | |||
10141 | int32_t tag = eHTMLTag_unknown; | |||
10142 | bool isCustomElementName = false; | |||
10143 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10144 | tag = nsHTMLTags::CaseSensitiveAtomTagToId(name); | |||
10145 | isCustomElementName = | |||
10146 | (tag == eHTMLTag_userdefined && | |||
10147 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3)); | |||
10148 | } else { // kNameSpaceID_XUL | |||
10149 | if (aIsAtom) { | |||
10150 | // Make sure the customized built-in element to be constructed confirms | |||
10151 | // to our naming requirement, i.e. [is] must be a dashed name and | |||
10152 | // the tag name must not. | |||
10153 | // if so, set isCustomElementName to false to kick off all the logics | |||
10154 | // that pick up aIsAtom. | |||
10155 | if (nsContentUtils::IsNameWithDash(aIsAtom) && | |||
10156 | !nsContentUtils::IsNameWithDash(name)) { | |||
10157 | isCustomElementName = false; | |||
10158 | } else { | |||
10159 | isCustomElementName = | |||
10160 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8); | |||
10161 | } | |||
10162 | } else { | |||
10163 | isCustomElementName = | |||
10164 | nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8); | |||
10165 | } | |||
10166 | } | |||
10167 | ||||
10168 | nsAtom* tagAtom = nodeInfo->NameAtom(); | |||
10169 | nsAtom* typeAtom = nullptr; | |||
10170 | bool isCustomElement = isCustomElementName
| |||
10171 | if (isCustomElement
| |||
10172 | typeAtom = isCustomElementName
| |||
10173 | } | |||
10174 | ||||
10175 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement" ")"); do { *((volatile int*)__null) = 10175; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); | |||
10176 | ||||
10177 | // https://dom.spec.whatwg.org/#concept-create-element | |||
10178 | // We only handle the "synchronous custom elements flag is set" now. | |||
10179 | // For the unset case (e.g. cloning a node), see bug 1319342 for that. | |||
10180 | // Step 4. | |||
10181 | RefPtr<CustomElementDefinition> definition = aDefinition; | |||
10182 | if (isCustomElement
| |||
10183 | 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())" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())" ")"); do { *((volatile int*)__null) = 10183; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10184 | definition = nsContentUtils::LookupCustomElementDefinition( | |||
10185 | nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(), | |||
10186 | typeAtom); | |||
10187 | } | |||
10188 | ||||
10189 | // It might be a problem that parser synchronously calls constructor, so filed | |||
10190 | // bug 1378079 to figure out what we should do for parser case. | |||
10191 | if (definition) { | |||
10192 | /* | |||
10193 | * Synchronous custom elements flag is determined by 3 places in spec, | |||
10194 | * 1) create an element for a token, the flag is determined by | |||
10195 | * "will execute script" which is not originally created | |||
10196 | * for the HTML fragment parsing algorithm. | |||
10197 | * 2) createElement and createElementNS, the flag is the same as | |||
10198 | * NOT_FROM_PARSER. | |||
10199 | * 3) clone a node, our implementation will not go into this function. | |||
10200 | * For the unset case which is non-synchronous only applied for | |||
10201 | * inner/outerHTML. | |||
10202 | */ | |||
10203 | bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT; | |||
10204 | // Per discussion in https://github.com/w3c/webcomponents/issues/635, | |||
10205 | // use entry global in those places that are called from JS APIs and use the | |||
10206 | // node document's global object if it is called from parser. | |||
10207 | nsIGlobalObject* global; | |||
10208 | if (aFromParser
| |||
10209 | global = GetEntryGlobal(); | |||
10210 | ||||
10211 | // Documents created from the PrototypeDocumentSink always use | |||
10212 | // NOT_FROM_PARSER for non-XUL elements. We can get the global from the | |||
10213 | // document in that case. | |||
10214 | if (!global) { | |||
10215 | Document* doc = nodeInfo->GetDocument(); | |||
10216 | if (doc && doc->LoadedFromPrototype()) { | |||
10217 | global = doc->GetScopeObject(); | |||
10218 | } | |||
10219 | } | |||
10220 | } else { | |||
10221 | global = nodeInfo->GetDocument()->GetScopeObject(); | |||
10222 | } | |||
10223 | if (!global) { | |||
10224 | // In browser chrome code, one may have access to a document which doesn't | |||
10225 | // have scope object anymore. | |||
10226 | return NS_ERROR_FAILURE; | |||
10227 | } | |||
10228 | ||||
10229 | AutoAllowLegacyScriptExecution exemption; | |||
10230 | AutoEntryScript aes(global, "create custom elements"); | |||
10231 | JSContext* cx = aes.cx(); | |||
10232 | ErrorResult rv; | |||
10233 | ||||
10234 | // Step 5. | |||
10235 | if (definition->IsCustomBuiltIn()) { | |||
10236 | // SetupCustomElement() should be called with an element that don't have | |||
10237 | // CustomElementData setup, if not we will hit the assertion in | |||
10238 | // SetCustomElementData(). | |||
10239 | // Built-in element | |||
10240 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10241 | *aResult = | |||
10242 | CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take(); | |||
10243 | } else { | |||
10244 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
10245 | } | |||
10246 | (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom)); | |||
10247 | if (synchronousCustomElements) { | |||
10248 | CustomElementRegistry::Upgrade(*aResult, definition, rv); | |||
10249 | if (rv.MaybeSetPendingException(cx)) { | |||
10250 | aes.ReportException(); | |||
10251 | } | |||
10252 | } else { | |||
10253 | nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); | |||
10254 | } | |||
10255 | ||||
10256 | return NS_OK; | |||
10257 | } | |||
10258 | ||||
10259 | // Step 6.1. | |||
10260 | if (synchronousCustomElements
| |||
10261 | definition->mPrefixStack.AppendElement(nodeInfo->GetPrefixAtom()); | |||
10262 | RefPtr<Document> doc = nodeInfo->GetDocument(); | |||
10263 | DoCustomElementCreate(aResult, cx, doc, nodeInfo, | |||
10264 | MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv, | |||
10265 | aFromParser); | |||
10266 | if (rv.MaybeSetPendingException(cx)) { | |||
10267 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10268 | NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget (), aFromParser)) | |||
10269 | aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget (), aFromParser)); | |||
10270 | } else { | |||
10271 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
10272 | } | |||
10273 | (*aResult)->SetDefined(false); | |||
10274 | } | |||
10275 | definition->mPrefixStack.RemoveLastElement(); | |||
10276 | return NS_OK; | |||
10277 | } | |||
10278 | ||||
10279 | // Step 6.2. | |||
10280 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10281 | NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )) | |||
10282 | NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )); | |||
10283 | } else { | |||
10284 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
10285 | } | |||
10286 | (*aResult)->SetCustomElementData( | |||
| ||||
10287 | MakeUnique<CustomElementData>(definition->mType)); | |||
10288 | nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); | |||
10289 | return NS_OK; | |||
10290 | } | |||
10291 | ||||
10292 | if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) { | |||
10293 | // Per the Custom Element specification, unknown tags that are valid custom | |||
10294 | // element names should be HTMLElement instead of HTMLUnknownElement. | |||
10295 | if (isCustomElementName) { | |||
10296 | NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )) | |||
10297 | NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser )); | |||
10298 | } else { | |||
10299 | *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take(); | |||
10300 | } | |||
10301 | } else { | |||
10302 | NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget ())); | |||
10303 | } | |||
10304 | ||||
10305 | if (!*aResult) { | |||
10306 | return NS_ERROR_OUT_OF_MEMORY; | |||
10307 | } | |||
10308 | ||||
10309 | if (isCustomElement) { | |||
10310 | (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom)); | |||
10311 | nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom); | |||
10312 | } | |||
10313 | ||||
10314 | return NS_OK; | |||
10315 | } | |||
10316 | ||||
10317 | CustomElementRegistry* nsContentUtils::GetCustomElementRegistry( | |||
10318 | Document* aDoc) { | |||
10319 | MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDoc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")") ; do { *((volatile int*)__null) = 10319; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10320 | ||||
10321 | if (!aDoc->GetDocShell()) { | |||
10322 | return nullptr; | |||
10323 | } | |||
10324 | ||||
10325 | nsPIDOMWindowInner* window = aDoc->GetInnerWindow(); | |||
10326 | if (!window) { | |||
10327 | return nullptr; | |||
10328 | } | |||
10329 | ||||
10330 | return window->CustomElements(); | |||
10331 | } | |||
10332 | ||||
10333 | /* static */ | |||
10334 | CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition( | |||
10335 | Document* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID, | |||
10336 | nsAtom* aTypeAtom) { | |||
10337 | if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) { | |||
10338 | return nullptr; | |||
10339 | } | |||
10340 | ||||
10341 | RefPtr<CustomElementRegistry> registry = GetCustomElementRegistry(aDoc); | |||
10342 | if (!registry) { | |||
10343 | return nullptr; | |||
10344 | } | |||
10345 | ||||
10346 | return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID, | |||
10347 | aTypeAtom); | |||
10348 | } | |||
10349 | ||||
10350 | /* static */ | |||
10351 | void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement, | |||
10352 | nsAtom* aTypeName) { | |||
10353 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { *((volatile int*)__null) = 10353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10354 | ||||
10355 | Document* doc = aElement->OwnerDoc(); | |||
10356 | CustomElementRegistry* registry = GetCustomElementRegistry(doc); | |||
10357 | if (registry) { | |||
10358 | registry->RegisterCallbackUpgradeElement(aElement, aTypeName); | |||
10359 | } | |||
10360 | } | |||
10361 | ||||
10362 | /* static */ | |||
10363 | void nsContentUtils::RegisterUnresolvedElement(Element* aElement, | |||
10364 | nsAtom* aTypeName) { | |||
10365 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { *((volatile int*)__null) = 10365; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10366 | ||||
10367 | Document* doc = aElement->OwnerDoc(); | |||
10368 | CustomElementRegistry* registry = GetCustomElementRegistry(doc); | |||
10369 | if (registry) { | |||
10370 | registry->RegisterUnresolvedElement(aElement, aTypeName); | |||
10371 | } | |||
10372 | } | |||
10373 | ||||
10374 | /* static */ | |||
10375 | void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) { | |||
10376 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { *((volatile int*)__null) = 10376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10377 | ||||
10378 | nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType(); | |||
10379 | Document* doc = aElement->OwnerDoc(); | |||
10380 | CustomElementRegistry* registry = GetCustomElementRegistry(doc); | |||
10381 | if (registry) { | |||
10382 | registry->UnregisterUnresolvedElement(aElement, typeAtom); | |||
10383 | } | |||
10384 | } | |||
10385 | ||||
10386 | /* static */ | |||
10387 | void nsContentUtils::EnqueueUpgradeReaction( | |||
10388 | Element* aElement, CustomElementDefinition* aDefinition) { | |||
10389 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")" ); do { *((volatile int*)__null) = 10389; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10390 | ||||
10391 | Document* doc = aElement->OwnerDoc(); | |||
10392 | ||||
10393 | // No DocGroup means no custom element reactions stack. | |||
10394 | if (!doc->GetDocGroup()) { | |||
10395 | return; | |||
10396 | } | |||
10397 | ||||
10398 | CustomElementReactionsStack* stack = | |||
10399 | doc->GetDocGroup()->CustomElementReactionsStack(); | |||
10400 | stack->EnqueueUpgradeReaction(aElement, aDefinition); | |||
10401 | } | |||
10402 | ||||
10403 | /* static */ | |||
10404 | void nsContentUtils::EnqueueLifecycleCallback( | |||
10405 | ElementCallbackType aType, Element* aCustomElement, | |||
10406 | const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) { | |||
10407 | // No DocGroup means no custom element reactions stack. | |||
10408 | if (!aCustomElement->OwnerDoc()->GetDocGroup()) { | |||
10409 | return; | |||
10410 | } | |||
10411 | ||||
10412 | CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs, | |||
10413 | aDefinition); | |||
10414 | } | |||
10415 | ||||
10416 | /* static */ | |||
10417 | CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue( | |||
10418 | const Nullable<OwningFileOrUSVStringOrFormData>& aState) { | |||
10419 | if (aState.IsNull()) { | |||
10420 | return void_t{}; | |||
10421 | } | |||
10422 | const auto& state = aState.Value(); | |||
10423 | if (state.IsFile()) { | |||
10424 | RefPtr<BlobImpl> impl = state.GetAsFile()->Impl(); | |||
10425 | return {std::move(impl)}; | |||
10426 | } | |||
10427 | if (state.IsUSVString()) { | |||
10428 | return state.GetAsUSVString(); | |||
10429 | } | |||
10430 | return state.GetAsFormData()->ConvertToCustomElementFormValue(); | |||
10431 | } | |||
10432 | ||||
10433 | /* static */ | |||
10434 | Nullable<OwningFileOrUSVStringOrFormData> | |||
10435 | nsContentUtils::ExtractFormAssociatedCustomElementValue( | |||
10436 | nsIGlobalObject* aGlobal, | |||
10437 | const mozilla::dom::CustomElementFormValue& aCEValue) { | |||
10438 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")" ); do { *((volatile int*)__null) = 10438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10439 | ||||
10440 | OwningFileOrUSVStringOrFormData value; | |||
10441 | switch (aCEValue.type()) { | |||
10442 | case CustomElementFormValue::TBlobImpl: { | |||
10443 | RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl()); | |||
10444 | if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10444)) { | |||
10445 | return {}; | |||
10446 | } | |||
10447 | value.SetAsFile() = file; | |||
10448 | } break; | |||
10449 | ||||
10450 | case CustomElementFormValue::TnsString: | |||
10451 | value.SetAsUSVString() = aCEValue.get_nsString(); | |||
10452 | break; | |||
10453 | ||||
10454 | case CustomElementFormValue::TArrayOfFormDataTuple: { | |||
10455 | const auto& array = aCEValue.get_ArrayOfFormDataTuple(); | |||
10456 | auto formData = MakeRefPtr<FormData>(); | |||
10457 | ||||
10458 | for (auto i = 0ul; i < array.Length(); ++i) { | |||
10459 | const auto& item = array.ElementAt(i); | |||
10460 | switch (item.value().type()) { | |||
10461 | case FormDataValue::TnsString: | |||
10462 | formData->AddNameValuePair(item.name(), | |||
10463 | item.value().get_nsString()); | |||
10464 | break; | |||
10465 | ||||
10466 | case FormDataValue::TBlobImpl: { | |||
10467 | auto blobImpl = item.value().get_BlobImpl(); | |||
10468 | auto* blob = Blob::Create(aGlobal, blobImpl); | |||
10469 | formData->AddNameBlobPair(item.name(), blob); | |||
10470 | } break; | |||
10471 | ||||
10472 | default: | |||
10473 | continue; | |||
10474 | } | |||
10475 | } | |||
10476 | ||||
10477 | value.SetAsFormData() = formData; | |||
10478 | } break; | |||
10479 | case CustomElementFormValue::Tvoid_t: | |||
10480 | return {}; | |||
10481 | default: | |||
10482 | NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10482); | |||
10483 | return {}; | |||
10484 | } | |||
10485 | return value; | |||
10486 | } | |||
10487 | ||||
10488 | /* static */ | |||
10489 | void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo( | |||
10490 | Document* aDocument, nsTArray<nsIContent*>& aElements) { | |||
10491 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"); do { *((volatile int*)__null) = 10491; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10492 | #ifdef DEBUG1 | |||
10493 | size_t oldLength = aElements.Length(); | |||
10494 | #endif | |||
10495 | ||||
10496 | if (PresShell* presShell = aDocument->GetPresShell()) { | |||
10497 | if (ScrollContainerFrame* rootScrollContainerFrame = | |||
10498 | presShell->GetRootScrollContainerFrame()) { | |||
10499 | rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0); | |||
10500 | } | |||
10501 | if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) { | |||
10502 | canvasFrame->AppendAnonymousContentTo(aElements, 0); | |||
10503 | } | |||
10504 | } | |||
10505 | ||||
10506 | #ifdef DEBUG1 | |||
10507 | for (size_t i = oldLength; i < aElements.Length(); i++) { | |||
10508 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { *((volatile int*)__null) = 10510; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
10509 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { *((volatile int*)__null) = 10510; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
10510 | "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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)" ") (" "Someone here has lied, or missed to flag the node" ")" ); do { *((volatile int*)__null) = 10510; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
10511 | } | |||
10512 | #endif | |||
10513 | } | |||
10514 | ||||
10515 | static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame, | |||
10516 | nsTArray<nsIContent*>& aKids, | |||
10517 | uint32_t aFlags) { | |||
10518 | if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) { | |||
10519 | ac->AppendAnonymousContentTo(aKids, aFlags); | |||
10520 | } | |||
10521 | } | |||
10522 | ||||
10523 | /* static */ | |||
10524 | void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent, | |||
10525 | nsTArray<nsIContent*>& aKids, | |||
10526 | uint32_t aFlags) { | |||
10527 | if (aContent->MayHaveAnonymousChildren()) { | |||
10528 | if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) { | |||
10529 | // NAC created by the element's primary frame. | |||
10530 | AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags); | |||
10531 | ||||
10532 | // NAC created by any other non-primary frames for the element. | |||
10533 | AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes; | |||
10534 | primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes); | |||
10535 | for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) { | |||
10536 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent" ")"); do { *((volatile int*)__null) = 10536; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10537 | AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids, | |||
10538 | aFlags); | |||
10539 | } | |||
10540 | } | |||
10541 | ||||
10542 | // Get manually created NAC (editor resize handles, etc.). | |||
10543 | if (auto nac = static_cast<ManualNACArray*>( | |||
10544 | aContent->GetProperty(nsGkAtoms::manualNACProperty))) { | |||
10545 | aKids.AppendElements(*nac); | |||
10546 | } | |||
10547 | } | |||
10548 | ||||
10549 | // The root scroll frame is not the primary frame of the root element. | |||
10550 | // Detect and handle this case. | |||
10551 | if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) && | |||
10552 | aContent == aContent->OwnerDoc()->GetRootElement()) { | |||
10553 | AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids); | |||
10554 | } | |||
10555 | } | |||
10556 | ||||
10557 | bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI, | |||
10558 | nsIPrincipal* aDefaultTriggeringPrincipal, | |||
10559 | CORSMode aCORSMode) { | |||
10560 | nsCOMPtr<nsIPrincipal> triggeringPrincipal; | |||
10561 | QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal, | |||
10562 | getter_AddRefs(triggeringPrincipal)); | |||
10563 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "triggeringPrincipal" ")"); do { *((volatile int*)__null) = 10563; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10564 | ||||
10565 | Document* doc = aLoadingNode->OwnerDoc(); | |||
10566 | return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc); | |||
10567 | } | |||
10568 | ||||
10569 | bool nsContentUtils::IsImageAvailable(nsIURI* aURI, | |||
10570 | nsIPrincipal* aTriggeringPrincipal, | |||
10571 | CORSMode aCORSMode, Document* aDoc) { | |||
10572 | imgLoader* imgLoader = GetImgLoaderForDocument(aDoc); | |||
10573 | return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode, | |||
10574 | aDoc); | |||
10575 | } | |||
10576 | ||||
10577 | /* static */ | |||
10578 | bool nsContentUtils::QueryTriggeringPrincipal( | |||
10579 | nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal, | |||
10580 | nsIPrincipal** aTriggeringPrincipal) { | |||
10581 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode" ")"); do { *((volatile int*)__null) = 10581; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10582 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal" ")"); do { *((volatile int*)__null) = 10582; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10583 | ||||
10584 | bool result = false; | |||
10585 | nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal; | |||
10586 | if (!loadingPrincipal) { | |||
10587 | loadingPrincipal = aLoadingNode->NodePrincipal(); | |||
10588 | } | |||
10589 | ||||
10590 | // If aLoadingNode is content, bail out early. | |||
10591 | if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) { | |||
10592 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
10593 | return result; | |||
10594 | } | |||
10595 | ||||
10596 | nsAutoString loadingStr; | |||
10597 | if (aLoadingNode->IsElement()) { | |||
10598 | aLoadingNode->AsElement()->GetAttr( | |||
10599 | kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr); | |||
10600 | } | |||
10601 | ||||
10602 | // Fall back if 'triggeringprincipal' isn't specified, | |||
10603 | if (loadingStr.IsEmpty()) { | |||
10604 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
10605 | return result; | |||
10606 | } | |||
10607 | ||||
10608 | nsCString binary; | |||
10609 | nsCOMPtr<nsIPrincipal> serializedPrin = | |||
10610 | BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr)); | |||
10611 | if (serializedPrin) { | |||
10612 | result = true; | |||
10613 | serializedPrin.forget(aTriggeringPrincipal); | |||
10614 | } | |||
10615 | ||||
10616 | if (!result) { | |||
10617 | // Fallback if the deserialization is failed. | |||
10618 | loadingPrincipal.forget(aTriggeringPrincipal); | |||
10619 | } | |||
10620 | ||||
10621 | return result; | |||
10622 | } | |||
10623 | ||||
10624 | /* static */ | |||
10625 | void nsContentUtils::GetContentPolicyTypeForUIImageLoading( | |||
10626 | nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal, | |||
10627 | nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) { | |||
10628 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequestContextID" ")"); do { *((volatile int*)__null) = 10628; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10629 | ||||
10630 | bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal); | |||
10631 | if (result) { | |||
10632 | // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for | |||
10633 | // indicating it's a favicon loading. | |||
10634 | aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; | |||
10635 | ||||
10636 | nsAutoString requestContextID; | |||
10637 | if (aLoadingNode->IsElement()) { | |||
10638 | aLoadingNode->AsElement()->GetAttr( | |||
10639 | kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID); | |||
10640 | } | |||
10641 | nsresult rv; | |||
10642 | int64_t val = requestContextID.ToInteger64(&rv); | |||
10643 | *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0; | |||
10644 | } else { | |||
10645 | aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; | |||
10646 | } | |||
10647 | } | |||
10648 | ||||
10649 | /* static */ | |||
10650 | nsresult nsContentUtils::CreateJSValueFromSequenceOfObject( | |||
10651 | JSContext* aCx, const Sequence<JSObject*>& aTransfer, | |||
10652 | JS::MutableHandle<JS::Value> aValue) { | |||
10653 | if (aTransfer.IsEmpty()) { | |||
10654 | return NS_OK; | |||
10655 | } | |||
10656 | ||||
10657 | JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length())); | |||
10658 | if (!array) { | |||
10659 | return NS_ERROR_OUT_OF_MEMORY; | |||
10660 | } | |||
10661 | ||||
10662 | for (uint32_t i = 0; i < aTransfer.Length(); ++i) { | |||
10663 | JS::Rooted<JSObject*> object(aCx, aTransfer[i]); | |||
10664 | if (!object) { | |||
10665 | continue; | |||
10666 | } | |||
10667 | ||||
10668 | if (NS_WARN_IF(NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE ), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10669) | |||
10669 | !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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10669)) { | |||
10670 | return NS_ERROR_OUT_OF_MEMORY; | |||
10671 | } | |||
10672 | } | |||
10673 | ||||
10674 | aValue.setObject(*array); | |||
10675 | return NS_OK; | |||
10676 | } | |||
10677 | ||||
10678 | /* static */ | |||
10679 | void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal, | |||
10680 | JS::Handle<JS::Value> aValue, | |||
10681 | const StructuredSerializeOptions& aOptions, | |||
10682 | JS::MutableHandle<JS::Value> aRetval, | |||
10683 | ErrorResult& aError) { | |||
10684 | JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue()); | |||
10685 | aError = nsContentUtils::CreateJSValueFromSequenceOfObject( | |||
10686 | aCx, aOptions.mTransfer, &transferArray); | |||
10687 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10687)) { | |||
10688 | return; | |||
10689 | } | |||
10690 | ||||
10691 | JS::CloneDataPolicy clonePolicy; | |||
10692 | // We are definitely staying in the same agent cluster. | |||
10693 | clonePolicy.allowIntraClusterClonableSharedObjects(); | |||
10694 | if (aGlobal->IsSharedMemoryAllowed()) { | |||
10695 | clonePolicy.allowSharedMemoryObjects(); | |||
10696 | } | |||
10697 | ||||
10698 | StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported, | |||
10699 | StructuredCloneHolder::TransferringSupported, | |||
10700 | JS::StructuredCloneScope::SameProcess); | |||
10701 | holder.Write(aCx, aValue, transferArray, clonePolicy, aError); | |||
10702 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10702)) { | |||
10703 | return; | |||
10704 | } | |||
10705 | ||||
10706 | holder.Read(aGlobal, aCx, aRetval, clonePolicy, aError); | |||
10707 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10707)) { | |||
10708 | return; | |||
10709 | } | |||
10710 | ||||
10711 | nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts(); | |||
10712 | Unused << ports; | |||
10713 | } | |||
10714 | ||||
10715 | /* static */ | |||
10716 | bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) { | |||
10717 | nsCOMPtr<nsIPrincipal> principal; | |||
10718 | RefPtr<Element> targetElement = | |||
10719 | Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget); | |||
10720 | nsCOMPtr<nsIBrowser> targetBrowser; | |||
10721 | if (targetElement) { | |||
10722 | targetBrowser = targetElement->AsBrowser(); | |||
10723 | } | |||
10724 | bool isRemoteBrowser = false; | |||
10725 | if (targetBrowser) { | |||
10726 | targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser); | |||
10727 | } | |||
10728 | ||||
10729 | if (isRemoteBrowser) { | |||
10730 | targetBrowser->GetContentPrincipal(getter_AddRefs(principal)); | |||
10731 | return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns) | |||
10732 | : false; | |||
10733 | } | |||
10734 | ||||
10735 | if (targetElement) { | |||
10736 | Document* doc = targetElement->GetUncomposedDoc(); | |||
10737 | if (doc) { | |||
10738 | RefPtr<WindowContext> wc = doc->GetWindowContext(); | |||
10739 | if (wc) { | |||
10740 | return wc->TopWindowContext()->GetShortcutsPermission() == | |||
10741 | nsIPermissionManager::DENY_ACTION; | |||
10742 | } | |||
10743 | } | |||
10744 | } | |||
10745 | ||||
10746 | return false; | |||
10747 | } | |||
10748 | ||||
10749 | /** | |||
10750 | * Checks whether the given type is a supported document type for | |||
10751 | * loading within the nsObjectLoadingContent specified by aContent. | |||
10752 | * | |||
10753 | * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType. | |||
10754 | * NOTE Does not take content policy or capabilities into account | |||
10755 | */ | |||
10756 | static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) { | |||
10757 | nsCOMPtr<nsIWebNavigationInfo> info( | |||
10758 | do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1")); | |||
10759 | if (!info) { | |||
10760 | return false; | |||
10761 | } | |||
10762 | ||||
10763 | uint32_t supported; | |||
10764 | nsresult rv = info->IsTypeSupported(aMimeType, &supported); | |||
10765 | ||||
10766 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
10767 | return false; | |||
10768 | } | |||
10769 | ||||
10770 | if (supported != nsIWebNavigationInfo::UNSUPPORTED) { | |||
10771 | // Don't want to support plugins as documents | |||
10772 | return supported != nsIWebNavigationInfo::FALLBACK; | |||
10773 | } | |||
10774 | ||||
10775 | // Try a stream converter | |||
10776 | // NOTE: We treat any type we can convert from as a supported type. If a | |||
10777 | // type is not actually supported, the URI loader will detect that and | |||
10778 | // return an error, and we'll fallback. | |||
10779 | nsCOMPtr<nsIStreamConverterService> convServ = | |||
10780 | do_GetService("@mozilla.org/streamConverters;1"); | |||
10781 | bool canConvert = false; | |||
10782 | if (convServ) { | |||
10783 | rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert); | |||
10784 | } | |||
10785 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert; | |||
10786 | } | |||
10787 | ||||
10788 | /* static */ | |||
10789 | uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType( | |||
10790 | const nsCString& aMIMEType) { | |||
10791 | if (aMIMEType.IsEmpty()) { | |||
10792 | return nsIObjectLoadingContent::TYPE_FALLBACK; | |||
10793 | } | |||
10794 | ||||
10795 | if (imgLoader::SupportImageWithMimeType(aMIMEType)) { | |||
10796 | return nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
10797 | } | |||
10798 | ||||
10799 | // Faking support of the PDF content as a document for EMBED tags | |||
10800 | // when internal PDF viewer is enabled. | |||
10801 | if (aMIMEType.LowerCaseEqualsLiteral("application/pdf") && IsPDFJSEnabled()) { | |||
10802 | return nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
10803 | } | |||
10804 | ||||
10805 | if (HtmlObjectContentSupportsDocument(aMIMEType)) { | |||
10806 | return nsIObjectLoadingContent::TYPE_DOCUMENT; | |||
10807 | } | |||
10808 | ||||
10809 | return nsIObjectLoadingContent::TYPE_FALLBACK; | |||
10810 | } | |||
10811 | ||||
10812 | /* static */ | |||
10813 | bool nsContentUtils::IsLocalRefURL(const nsAString& aString) { | |||
10814 | return !aString.IsEmpty() && aString[0] == '#'; | |||
10815 | } | |||
10816 | ||||
10817 | // We use only 53 bits for the ID so that it can be converted to and from a JS | |||
10818 | // value without loss of precision. The upper bits of the ID hold the process | |||
10819 | // ID. The lower bits identify the object itself. | |||
10820 | static constexpr uint64_t kIdTotalBits = 53; | |||
10821 | static constexpr uint64_t kIdProcessBits = 22; | |||
10822 | static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits; | |||
10823 | ||||
10824 | /* static */ | |||
10825 | uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) { | |||
10826 | uint64_t processId = 0; | |||
10827 | if (XRE_IsContentProcess()) { | |||
10828 | ContentChild* cc = ContentChild::GetSingleton(); | |||
10829 | processId = cc->GetID(); | |||
10830 | } | |||
10831 | ||||
10832 | 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)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10832); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)" ")"); do { *((volatile int*)__null) = 10832; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10833 | uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1); | |||
10834 | ||||
10835 | uint64_t id = aId; | |||
10836 | 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)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 10836); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)" ")"); do { *((volatile int*)__null) = 10836; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
10837 | uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1); | |||
10838 | ||||
10839 | return (processBits << kIdBits) | bits; | |||
10840 | } | |||
10841 | ||||
10842 | /* static */ | |||
10843 | std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId( | |||
10844 | uint64_t aId) { | |||
10845 | return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)}; | |||
10846 | } | |||
10847 | ||||
10848 | // Next process-local Tab ID. | |||
10849 | static uint64_t gNextTabId = 0; | |||
10850 | ||||
10851 | /* static */ | |||
10852 | uint64_t nsContentUtils::GenerateTabId() { | |||
10853 | return GenerateProcessSpecificId(++gNextTabId); | |||
10854 | } | |||
10855 | ||||
10856 | // Next process-local Browser ID. | |||
10857 | static uint64_t gNextBrowserId = 0; | |||
10858 | ||||
10859 | /* static */ | |||
10860 | uint64_t nsContentUtils::GenerateBrowserId() { | |||
10861 | return GenerateProcessSpecificId(++gNextBrowserId); | |||
10862 | } | |||
10863 | ||||
10864 | // Next process-local Browsing Context ID. | |||
10865 | static uint64_t gNextBrowsingContextId = 0; | |||
10866 | ||||
10867 | /* static */ | |||
10868 | uint64_t nsContentUtils::GenerateBrowsingContextId() { | |||
10869 | return GenerateProcessSpecificId(++gNextBrowsingContextId); | |||
10870 | } | |||
10871 | ||||
10872 | // Next process-local Window ID. | |||
10873 | static uint64_t gNextWindowId = 0; | |||
10874 | ||||
10875 | /* static */ | |||
10876 | uint64_t nsContentUtils::GenerateWindowId() { | |||
10877 | return GenerateProcessSpecificId(++gNextWindowId); | |||
10878 | } | |||
10879 | ||||
10880 | // Next process-local load. | |||
10881 | static Atomic<uint64_t> gNextLoadIdentifier(0); | |||
10882 | ||||
10883 | /* static */ | |||
10884 | uint64_t nsContentUtils::GenerateLoadIdentifier() { | |||
10885 | return GenerateProcessSpecificId(++gNextLoadIdentifier); | |||
10886 | } | |||
10887 | ||||
10888 | /* static */ | |||
10889 | bool nsContentUtils::GetUserIsInteracting() { | |||
10890 | return UserInteractionObserver::sUserActive; | |||
10891 | } | |||
10892 | ||||
10893 | /* static */ | |||
10894 | bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, | |||
10895 | nsACString& aResult) { | |||
10896 | nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult); | |||
10897 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
10898 | rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult); | |||
10899 | } | |||
10900 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))); | |||
10901 | } | |||
10902 | ||||
10903 | /* static */ | |||
10904 | bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) { | |||
10905 | if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) == | |||
10906 | mozilla::dom::PBrowser::PBrowserStart) { | |||
10907 | switch (aMsg.type()) { | |||
10908 | case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID: | |||
10909 | case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID: | |||
10910 | case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID: | |||
10911 | case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID: | |||
10912 | case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID: | |||
10913 | case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID: | |||
10914 | case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID: | |||
10915 | case mozilla::dom::PBrowser::Msg_RealDragEvent__ID: | |||
10916 | case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID: | |||
10917 | return true; | |||
10918 | } | |||
10919 | } | |||
10920 | return false; | |||
10921 | } | |||
10922 | ||||
10923 | /* static */ | |||
10924 | bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) { | |||
10925 | if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) == | |||
10926 | mozilla::dom::PBrowser::PBrowserStart) { | |||
10927 | switch (aMsg.type()) { | |||
10928 | case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID: | |||
10929 | case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID: | |||
10930 | case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID: | |||
10931 | case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID: | |||
10932 | case mozilla::dom::PBrowser::Msg_RealDragEvent__ID: | |||
10933 | return true; | |||
10934 | } | |||
10935 | } | |||
10936 | return false; | |||
10937 | } | |||
10938 | ||||
10939 | static const char* kUserInteractionInactive = "user-interaction-inactive"; | |||
10940 | static const char* kUserInteractionActive = "user-interaction-active"; | |||
10941 | ||||
10942 | void nsContentUtils::UserInteractionObserver::Init() { | |||
10943 | // Listen for the observer messages from EventStateManager which are telling | |||
10944 | // us whether or not the user is interacting. | |||
10945 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); | |||
10946 | obs->AddObserver(this, kUserInteractionInactive, false); | |||
10947 | obs->AddObserver(this, kUserInteractionActive, false); | |||
10948 | ||||
10949 | // We can't register ourselves as an annotator yet, as the | |||
10950 | // BackgroundHangMonitor hasn't started yet. It will have started by the | |||
10951 | // time we have the chance to spin the event loop. | |||
10952 | RefPtr<UserInteractionObserver> self = this; | |||
10953 | NS_DispatchToMainThread(NS_NewRunnableFunction( | |||
10954 | "nsContentUtils::UserInteractionObserver::Init", | |||
10955 | [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); })); | |||
10956 | } | |||
10957 | ||||
10958 | void nsContentUtils::UserInteractionObserver::Shutdown() { | |||
10959 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); | |||
10960 | if (obs) { | |||
10961 | obs->RemoveObserver(this, kUserInteractionInactive); | |||
10962 | obs->RemoveObserver(this, kUserInteractionActive); | |||
10963 | } | |||
10964 | ||||
10965 | BackgroundHangMonitor::UnregisterAnnotator(*this); | |||
10966 | } | |||
10967 | ||||
10968 | /** | |||
10969 | * NB: This function is always called by the BackgroundHangMonitor thread. | |||
10970 | * Plan accordingly | |||
10971 | */ | |||
10972 | void nsContentUtils::UserInteractionObserver::AnnotateHang( | |||
10973 | BackgroundHangAnnotations& aAnnotations) { | |||
10974 | // NOTE: Only annotate the hang report if the user is known to be interacting. | |||
10975 | if (sUserActive) { | |||
10976 | aAnnotations.AddAnnotation(u"UserInteracting"_ns, true); | |||
10977 | } | |||
10978 | } | |||
10979 | ||||
10980 | NS_IMETHODIMPnsresult | |||
10981 | nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject, | |||
10982 | const char* aTopic, | |||
10983 | const char16_t* aData) { | |||
10984 | if (!strcmp(aTopic, kUserInteractionInactive)) { | |||
10985 | if (sUserActive && XRE_IsParentProcess()) { | |||
10986 | glean::RecordPowerMetrics(); | |||
10987 | } | |||
10988 | sUserActive = false; | |||
10989 | } else if (!strcmp(aTopic, kUserInteractionActive)) { | |||
10990 | if (!sUserActive && XRE_IsParentProcess()) { | |||
10991 | glean::RecordPowerMetrics(); | |||
10992 | ||||
10993 | nsCOMPtr<nsIUserIdleServiceInternal> idleService = | |||
10994 | do_GetService("@mozilla.org/widget/useridleservice;1"); | |||
10995 | if (idleService) { | |||
10996 | idleService->ResetIdleTimeOut(0); | |||
10997 | } | |||
10998 | } | |||
10999 | ||||
11000 | sUserActive = true; | |||
11001 | } else { | |||
11002 | NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11002); | |||
11003 | } | |||
11004 | return NS_OK; | |||
11005 | } | |||
11006 | ||||
11007 | Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false); | |||
11008 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 11008; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 11008; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 11008 ; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 11008; __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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11008); 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((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr , table); return rv; } | |||
11009 | ||||
11010 | /* static */ | |||
11011 | bool nsContentUtils::IsSpecialName(const nsAString& aName) { | |||
11012 | return aName.LowerCaseEqualsLiteral("_blank") || | |||
11013 | aName.LowerCaseEqualsLiteral("_top") || | |||
11014 | aName.LowerCaseEqualsLiteral("_parent") || | |||
11015 | aName.LowerCaseEqualsLiteral("_self"); | |||
11016 | } | |||
11017 | ||||
11018 | /* static */ | |||
11019 | bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) { | |||
11020 | return !aName.IsEmpty() && !IsSpecialName(aName); | |||
11021 | } | |||
11022 | ||||
11023 | // Unfortunately, we can't unwrap an IDL object using only a concrete type. | |||
11024 | // We need to calculate type data based on the IDL typename. Which means | |||
11025 | // wrapping our templated function in a macro. | |||
11026 | #define EXTRACT_EXN_VALUES(T, ...) \ | |||
11027 | ExtractExceptionValues<mozilla::dom::prototypes::id::T, \ | |||
11028 | T##_Binding::NativeType, T>(__VA_ARGS__) \ | |||
11029 | .isOk() | |||
11030 | ||||
11031 | template <prototypes::ID PrototypeID, class NativeType, typename T> | |||
11032 | static Result<Ok, nsresult> ExtractExceptionValues( | |||
11033 | JSContext* aCx, JS::Handle<JSObject*> aObj, nsAString& aSourceSpecOut, | |||
11034 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
11035 | AssertStaticUnwrapOK<PrototypeID>(); | |||
11036 | RefPtr<T> exn; | |||
11037 | MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr)))do { auto mozTryTempResult_ = ::mozilla::ToResult((UnwrapObject <PrototypeID, NativeType>(aObj, exn, nullptr))); if ((__builtin_expect (!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_ .propagateErr(); } } while (0); | |||
11038 | ||||
11039 | exn->GetFilename(aCx, aSourceSpecOut); | |||
11040 | if (!aSourceSpecOut.IsEmpty()) { | |||
11041 | *aLineOut = exn->LineNumber(aCx); | |||
11042 | *aColumnOut = exn->ColumnNumber(); | |||
11043 | } | |||
11044 | ||||
11045 | exn->GetName(aMessageOut); | |||
11046 | aMessageOut.AppendLiteral(": "); | |||
11047 | ||||
11048 | nsAutoString message; | |||
11049 | exn->GetMessageMoz(message); | |||
11050 | aMessageOut.Append(message); | |||
11051 | return Ok(); | |||
11052 | } | |||
11053 | ||||
11054 | /* static */ | |||
11055 | void nsContentUtils::ExtractErrorValues( | |||
11056 | JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut, | |||
11057 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
11058 | nsAutoString sourceSpec; | |||
11059 | ExtractErrorValues(aCx, aValue, sourceSpec, aLineOut, aColumnOut, | |||
11060 | aMessageOut); | |||
11061 | CopyUTF16toUTF8(sourceSpec, aSourceSpecOut); | |||
11062 | } | |||
11063 | ||||
11064 | /* static */ | |||
11065 | void nsContentUtils::ExtractErrorValues( | |||
11066 | JSContext* aCx, JS::Handle<JS::Value> aValue, nsAString& aSourceSpecOut, | |||
11067 | uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) { | |||
11068 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")" ); do { *((volatile int*)__null) = 11068; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
11069 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut" ")"); do { *((volatile int*)__null) = 11069; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11070 | ||||
11071 | if (aValue.isObject()) { | |||
11072 | JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); | |||
11073 | ||||
11074 | // Try to process as an Error object. Use the file/line/column values | |||
11075 | // from the Error as they will be more specific to the root cause of | |||
11076 | // the problem. | |||
11077 | JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr; | |||
11078 | if (err) { | |||
11079 | // Use xpc to extract the error message only. We don't actually send | |||
11080 | // this report anywhere. | |||
11081 | RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport(); | |||
11082 | report->Init(err, | |||
11083 | nullptr, // toString result | |||
11084 | false, // chrome | |||
11085 | 0); // window ID | |||
11086 | ||||
11087 | if (!report->mFileName.IsEmpty()) { | |||
11088 | aSourceSpecOut = report->mFileName; | |||
11089 | *aLineOut = report->mLineNumber; | |||
11090 | *aColumnOut = report->mColumn; | |||
11091 | } | |||
11092 | aMessageOut.Assign(report->mErrorMsg); | |||
11093 | } | |||
11094 | ||||
11095 | // Next, try to unwrap the rejection value as a DOMException. | |||
11096 | else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut, | |||
11097 | aLineOut, aColumnOut, aMessageOut)) { | |||
11098 | return; | |||
11099 | } | |||
11100 | ||||
11101 | // Next, try to unwrap the rejection value as an XPC Exception. | |||
11102 | else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut, aLineOut, | |||
11103 | aColumnOut, aMessageOut)) { | |||
11104 | return; | |||
11105 | } | |||
11106 | } | |||
11107 | ||||
11108 | // If we could not unwrap a specific error type, then perform default safe | |||
11109 | // string conversions on primitives. Objects will result in "[Object]" | |||
11110 | // unfortunately. | |||
11111 | if (aMessageOut.IsEmpty()) { | |||
11112 | nsAutoJSString jsString; | |||
11113 | if (jsString.init(aCx, aValue)) { | |||
11114 | aMessageOut = jsString; | |||
11115 | } else { | |||
11116 | JS_ClearPendingException(aCx); | |||
11117 | } | |||
11118 | } | |||
11119 | } | |||
11120 | ||||
11121 | #undef EXTRACT_EXN_VALUES | |||
11122 | ||||
11123 | /* static */ | |||
11124 | bool nsContentUtils::ContentIsLink(nsIContent* aContent) { | |||
11125 | if (!aContent || !aContent->IsElement()) { | |||
11126 | return false; | |||
11127 | } | |||
11128 | ||||
11129 | if (aContent->IsHTMLElement(nsGkAtoms::a)) { | |||
11130 | return true; | |||
11131 | } | |||
11132 | ||||
11133 | return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type, | |||
11134 | nsGkAtoms::simple, eCaseMatters); | |||
11135 | } | |||
11136 | ||||
11137 | /* static */ | |||
11138 | already_AddRefed<ContentFrameMessageManager> | |||
11139 | nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) { | |||
11140 | RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom); | |||
11141 | if (!frameLoaderOwner) { | |||
11142 | return nullptr; | |||
11143 | } | |||
11144 | ||||
11145 | RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); | |||
11146 | if (!frameLoader) { | |||
11147 | return nullptr; | |||
11148 | } | |||
11149 | ||||
11150 | RefPtr<ContentFrameMessageManager> manager = | |||
11151 | frameLoader->GetBrowserChildMessageManager(); | |||
11152 | return manager.forget(); | |||
11153 | } | |||
11154 | ||||
11155 | /* static */ | |||
11156 | uint32_t nsContentUtils::InnerOrOuterWindowCreated() { | |||
11157 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 11157; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11158 | ++sInnerOrOuterWindowCount; | |||
11159 | return ++sInnerOrOuterWindowSerialCounter; | |||
11160 | } | |||
11161 | ||||
11162 | /* static */ | |||
11163 | void nsContentUtils::InnerOrOuterWindowDestroyed() { | |||
11164 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 11164; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11165 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0" ")"); do { *((volatile int*)__null) = 11165; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11166 | --sInnerOrOuterWindowCount; | |||
11167 | } | |||
11168 | ||||
11169 | /* static */ | |||
11170 | nsresult nsContentUtils::AnonymizeURI(nsIURI* aURI, nsCString& aAnonymizedURI) { | |||
11171 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")") ; do { *((volatile int*)__null) = 11171; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
11172 | ||||
11173 | if (aURI->SchemeIs("data")) { | |||
11174 | aAnonymizedURI.Assign("data:..."_ns); | |||
11175 | return NS_OK; | |||
11176 | } | |||
11177 | // Anonymize the URL. | |||
11178 | // Strip the URL of any possible username/password and make it ready to be | |||
11179 | // presented in the UI. | |||
11180 | nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(aURI); | |||
11181 | return exposableURI->GetSpec(aAnonymizedURI); | |||
11182 | } | |||
11183 | ||||
11184 | static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) { | |||
11185 | nsAString* result = static_cast<nsAString*>(aData); | |||
11186 | return result->Append(aBuf, aLen, fallible); | |||
11187 | } | |||
11188 | ||||
11189 | /* static */ | |||
11190 | bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue, | |||
11191 | nsAString& aOutStr, JSONBehavior aBehavior) { | |||
11192 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")"); do { *((volatile int*)__null) = 11192; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
11193 | switch (aBehavior) { | |||
11194 | case UndefinedIsNullStringLiteral: { | |||
11195 | aOutStr.Truncate(); | |||
11196 | JS::Rooted<JS::Value> value(aCx, aValue); | |||
11197 | return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue, | |||
11198 | JSONCreator, &aOutStr); | |||
11199 | } | |||
11200 | case UndefinedIsVoidString: { | |||
11201 | aOutStr.SetIsVoid(true); | |||
11202 | return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator, | |||
11203 | &aOutStr); | |||
11204 | } | |||
11205 | default: | |||
11206 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")" ); do { *((volatile int*)__null) = 11206; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
11207 | return false; | |||
11208 | } | |||
11209 | } | |||
11210 | ||||
11211 | /* static */ | |||
11212 | bool nsContentUtils:: | |||
11213 | HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint( | |||
11214 | Document* aDocument) { | |||
11215 | 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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes" ")" ); do { *((volatile int*)__null) = 11216; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
11216 | "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" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes" ")" ); do { *((volatile int*)__null) = 11216; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
11217 | ||||
11218 | if (aDocument && !aDocument->IsLoadedAsData()) { | |||
11219 | if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) { | |||
11220 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()" ") (" "Should never have a chrome PresContext in a content process" ")"); do { *((volatile int*)__null) = 11221; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) | |||
11221 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()" ") (" "Should never have a chrome PresContext in a content process" ")"); do { *((volatile int*)__null) = 11221; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11222 | ||||
11223 | return !presContext->GetInProcessRootContentDocumentPresContext() | |||
11224 | ->HadFirstContentfulPaint() && | |||
11225 | nsThreadManager::MainThreadHasPendingHighPriorityEvents(); | |||
11226 | } | |||
11227 | } | |||
11228 | return false; | |||
11229 | } | |||
11230 | ||||
11231 | static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) { | |||
11232 | NS_ENSURE_TRUE(aGlobal, nullptr)do { if ((__builtin_expect(!!(!(aGlobal)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aGlobal" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11232); return nullptr; } } while (false); | |||
11233 | ||||
11234 | if (auto* window = aGlobal->GetAsInnerWindow()) { | |||
11235 | return nsGlobalWindowInner::Cast(window); | |||
11236 | } | |||
11237 | ||||
11238 | // When Extensions run content scripts inside a sandbox, it uses | |||
11239 | // sandboxPrototype to make them appear as though they're running in the | |||
11240 | // scope of the page. So when a content script invokes postMessage, it expects | |||
11241 | // the |source| of the received message to be the window set as the | |||
11242 | // sandboxPrototype. This used to work incidentally for unrelated reasons, but | |||
11243 | // now we need to do some special handling to support it. | |||
11244 | JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject()); | |||
11245 | NS_ENSURE_TRUE(scope, nullptr)do { if ((__builtin_expect(!!(!(scope)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scope" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11245); return nullptr; } } while (false); | |||
11246 | ||||
11247 | if (xpc::IsSandbox(scope)) { | |||
11248 | AutoJSAPI jsapi; | |||
11249 | MOZ_ALWAYS_TRUE(jsapi.Init(scope))do { if ((__builtin_expect(!!(jsapi.Init(scope)), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "jsapi.Init(scope)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11249); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "jsapi.Init(scope)" ")"); do { *((volatile int*)__null ) = 11249; __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); } } while (false); | |||
11250 | JSContext* cx = jsapi.cx(); | |||
11251 | // Our current Realm on aCx is the sandbox. Using that for unwrapping | |||
11252 | // makes sense: if the sandbox can unwrap the window, we can use it. | |||
11253 | return xpc::SandboxWindowOrNull(scope, cx); | |||
11254 | } | |||
11255 | ||||
11256 | // The calling window must be holding a reference, so we can return a weak | |||
11257 | // pointer. | |||
11258 | return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow()); | |||
11259 | } | |||
11260 | ||||
11261 | /* static */ | |||
11262 | nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() { | |||
11263 | return GetInnerWindowForGlobal(GetIncumbentGlobal()); | |||
11264 | } | |||
11265 | ||||
11266 | /* static */ | |||
11267 | nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() { | |||
11268 | return GetInnerWindowForGlobal(GetEntryGlobal()); | |||
11269 | } | |||
11270 | ||||
11271 | /* static */ | |||
11272 | bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) { | |||
11273 | 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", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName" ")"); do { *((volatile int*)__null) = 11273; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11274 | ||||
11275 | nsAutoCString list; | |||
11276 | Preferences::GetCString(aPrefName, list); | |||
11277 | ToLowerCase(list); | |||
11278 | return IsURIInList(aURI, list); | |||
11279 | } | |||
11280 | ||||
11281 | /* static */ | |||
11282 | bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) { | |||
11283 | #ifdef DEBUG1 | |||
11284 | nsAutoCString listLowerCase(aList); | |||
11285 | ToLowerCase(listLowerCase); | |||
11286 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)" ") (" "The aList argument should be lower-case" ")"); do { * ((volatile int*)__null) = 11287; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) | |||
11287 | "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)" ") (" "The aList argument should be lower-case" ")"); do { * ((volatile int*)__null) = 11287; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); | |||
11288 | #endif | |||
11289 | ||||
11290 | if (!aURI) { | |||
11291 | return false; | |||
11292 | } | |||
11293 | ||||
11294 | nsAutoCString scheme; | |||
11295 | aURI->GetScheme(scheme); | |||
11296 | if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) { | |||
11297 | return false; | |||
11298 | } | |||
11299 | ||||
11300 | if (aList.IsEmpty()) { | |||
11301 | return false; | |||
11302 | } | |||
11303 | ||||
11304 | // The list is comma separated domain list. Each item may start with "*.". | |||
11305 | // If starts with "*.", it matches any sub-domains. | |||
11306 | ||||
11307 | nsCCharSeparatedTokenizer tokenizer(aList, ','); | |||
11308 | while (tokenizer.hasMoreTokens()) { | |||
11309 | const nsCString token(tokenizer.nextToken()); | |||
11310 | ||||
11311 | nsAutoCString host; | |||
11312 | aURI->GetHost(host); | |||
11313 | if (host.IsEmpty()) { | |||
11314 | return false; | |||
11315 | } | |||
11316 | ToLowerCase(host); | |||
11317 | ||||
11318 | for (;;) { | |||
11319 | int32_t index = token.Find(host); | |||
11320 | if (index >= 0 && | |||
11321 | static_cast<uint32_t>(index) + host.Length() <= token.Length()) { | |||
11322 | // If we found a full match, return true. | |||
11323 | size_t indexAfterHost = index + host.Length(); | |||
11324 | if (index == 0 && indexAfterHost == token.Length()) { | |||
11325 | return true; | |||
11326 | } | |||
11327 | // If next character is '/', we need to check the path too. | |||
11328 | // We assume the path in the list means "/foo" + "*". | |||
11329 | if (token[indexAfterHost] == '/') { | |||
11330 | nsDependentCSubstring pathInList( | |||
11331 | token, indexAfterHost, | |||
11332 | static_cast<nsDependentCSubstring::size_type>(-1)); | |||
11333 | nsAutoCString filePath; | |||
11334 | aURI->GetFilePath(filePath); | |||
11335 | ToLowerCase(filePath); | |||
11336 | if (StringBeginsWith(filePath, pathInList) && | |||
11337 | (filePath.Length() == pathInList.Length() || | |||
11338 | pathInList.EqualsLiteral("/") || | |||
11339 | filePath[pathInList.Length() - 1] == '/' || | |||
11340 | filePath[pathInList.Length() - 1] == '?' || | |||
11341 | filePath[pathInList.Length() - 1] == '#')) { | |||
11342 | return true; | |||
11343 | } | |||
11344 | } | |||
11345 | } | |||
11346 | int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0; | |||
11347 | int32_t startIndexOfNextLevel = | |||
11348 | host.Find(".", startIndexOfCurrentLevel + 1); | |||
11349 | if (startIndexOfNextLevel <= 0) { | |||
11350 | break; | |||
11351 | } | |||
11352 | host.ReplaceLiteral(0, startIndexOfNextLevel, "*"); | |||
11353 | } | |||
11354 | } | |||
11355 | ||||
11356 | return false; | |||
11357 | } | |||
11358 | ||||
11359 | /* static */ | |||
11360 | ScreenIntMargin nsContentUtils::GetWindowSafeAreaInsets( | |||
11361 | nsIScreen* aScreen, const ScreenIntMargin& aSafeAreaInsets, | |||
11362 | const LayoutDeviceIntRect& aWindowRect) { | |||
11363 | // This calculates safe area insets of window from screen rectangle, window | |||
11364 | // rectangle and safe area insets of screen. | |||
11365 | // | |||
11366 | // +----------------------------------------+ <-- screen | |||
11367 | // | +-------------------------------+ <------- window | |||
11368 | // | | window's safe area inset top) | | | |||
11369 | // +--+-------------------------------+--+ | | |||
11370 | // | | | |<------ safe area rectangle of | |||
11371 | // | | | | | screen | |||
11372 | // +--+-------------------------------+--+ | | |||
11373 | // | |window's safe area inset bottom| | | |||
11374 | // | +-------------------------------+ | | |||
11375 | // +----------------------------------------+ | |||
11376 | // | |||
11377 | ScreenIntMargin windowSafeAreaInsets; | |||
11378 | ||||
11379 | if (windowSafeAreaInsets == aSafeAreaInsets) { | |||
11380 | // no safe area insets. | |||
11381 | return windowSafeAreaInsets; | |||
11382 | } | |||
11383 | ||||
11384 | int32_t screenLeft, screenTop, screenWidth, screenHeight; | |||
11385 | nsresult rv = | |||
11386 | aScreen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight); | |||
11387 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11387)) { | |||
11388 | return windowSafeAreaInsets; | |||
11389 | } | |||
11390 | ||||
11391 | const ScreenIntRect screenRect(screenLeft, screenTop, screenWidth, | |||
11392 | screenHeight); | |||
11393 | ||||
11394 | ScreenIntRect safeAreaRect = screenRect; | |||
11395 | safeAreaRect.Deflate(aSafeAreaInsets); | |||
11396 | ||||
11397 | ScreenIntRect windowRect = ViewAs<ScreenPixel>( | |||
11398 | aWindowRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims); | |||
11399 | ||||
11400 | // FIXME(bug 1754323): This can trigger because the screen rect is not | |||
11401 | // orientation-aware. | |||
11402 | // MOZ_ASSERT(screenRect.Contains(windowRect), | |||
11403 | // "Screen doesn't contain window rect? Something seems off"); | |||
11404 | ||||
11405 | // window's rect of safe area | |||
11406 | safeAreaRect = safeAreaRect.Intersect(windowRect); | |||
11407 | ||||
11408 | windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y; | |||
11409 | windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x; | |||
11410 | windowSafeAreaInsets.right = | |||
11411 | aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width); | |||
11412 | windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height - | |||
11413 | (safeAreaRect.y + safeAreaRect.height); | |||
11414 | ||||
11415 | windowSafeAreaInsets.EnsureAtLeast(ScreenIntMargin()); | |||
11416 | // This shouldn't be needed, but it wallpapers orientation issues, see bug | |||
11417 | // 1754323. | |||
11418 | windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets); | |||
11419 | ||||
11420 | return windowSafeAreaInsets; | |||
11421 | } | |||
11422 | ||||
11423 | /* static */ | |||
11424 | nsContentUtils::SubresourceCacheValidationInfo | |||
11425 | nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest, | |||
11426 | nsIURI* aURI) { | |||
11427 | SubresourceCacheValidationInfo info; | |||
11428 | if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) { | |||
11429 | uint32_t value = 0; | |||
11430 | if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime (&value))), 1)))) { | |||
11431 | info.mExpirationTime.emplace(value); | |||
11432 | } | |||
11433 | } | |||
11434 | ||||
11435 | // Determine whether the cache entry must be revalidated when we try to use | |||
11436 | // it. Currently, only HTTP specifies this information... | |||
11437 | if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) { | |||
11438 | Unused << httpChannel->IsNoStoreResponse(&info.mMustRevalidate); | |||
11439 | ||||
11440 | if (!info.mMustRevalidate) { | |||
11441 | Unused << httpChannel->IsNoCacheResponse(&info.mMustRevalidate); | |||
11442 | } | |||
11443 | } | |||
11444 | ||||
11445 | // data: URIs are safe to cache across documents under any circumstance, so we | |||
11446 | // special-case them here even though the channel itself doesn't have any | |||
11447 | // caching policy. Same for chrome:// uris. | |||
11448 | // | |||
11449 | // TODO(emilio): Figure out which other schemes that don't have caching | |||
11450 | // policies are safe to cache. Blobs should be... | |||
11451 | const bool knownCacheable = [&] { | |||
11452 | if (!aURI) { | |||
11453 | return false; | |||
11454 | } | |||
11455 | if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") || | |||
11456 | aURI->SchemeIs("moz-extension")) { | |||
11457 | return true; | |||
11458 | } | |||
11459 | if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) { | |||
11460 | return !StaticPrefs::nglayout_debug_disable_xul_cache(); | |||
11461 | } | |||
11462 | return false; | |||
11463 | }(); | |||
11464 | ||||
11465 | if (knownCacheable) { | |||
11466 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mExpirationTime" ")"); do { *((volatile int*)__null) = 11466; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11467 | 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" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!info.mMustRevalidate" ")"); do { *((volatile int*)__null) = 11467; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11468 | info.mExpirationTime = Some(0); // 0 means "doesn't expire". | |||
11469 | } | |||
11470 | ||||
11471 | return info; | |||
11472 | } | |||
11473 | ||||
11474 | /* static */ | |||
11475 | bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) { | |||
11476 | RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup(); | |||
11477 | if (!lg) { | |||
11478 | return false; | |||
11479 | } | |||
11480 | nsLoadFlags flags; | |||
11481 | if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags (&flags))), 0)))) { | |||
11482 | return false; | |||
11483 | } | |||
11484 | return flags & (nsIRequest::LOAD_BYPASS_CACHE | | |||
11485 | nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE); | |||
11486 | } | |||
11487 | ||||
11488 | nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) { | |||
11489 | nsCString spec; | |||
11490 | if (aURL) { | |||
11491 | aURL->GetSpec(spec); | |||
11492 | spec.Truncate(std::min(aMaxLen, spec.Length())); | |||
11493 | } | |||
11494 | return spec; | |||
11495 | } | |||
11496 | ||||
11497 | /* static */ | |||
11498 | nsresult nsContentUtils::AnonymizeId(nsAString& aId, | |||
11499 | const nsACString& aOriginKey, | |||
11500 | OriginFormat aFormat) { | |||
11501 | 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()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 11501; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); | |||
11502 | ||||
11503 | nsresult rv; | |||
11504 | nsCString rawKey; | |||
11505 | if (aFormat == OriginFormat::Base64) { | |||
11506 | rv = Base64Decode(aOriginKey, rawKey); | |||
11507 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11507); return rv; } } while (false); | |||
11508 | } else { | |||
11509 | rawKey = aOriginKey; | |||
11510 | } | |||
11511 | ||||
11512 | HMAC hmac; | |||
11513 | rv = hmac.Begin( | |||
11514 | SEC_OID_SHA256, | |||
11515 | Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length())); | |||
11516 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11516); return rv; } } while (false); | |||
11517 | ||||
11518 | NS_ConvertUTF16toUTF8 id(aId); | |||
11519 | rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length()); | |||
11520 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11520); return rv; } } while (false); | |||
11521 | ||||
11522 | nsTArray<uint8_t> macBytes; | |||
11523 | rv = hmac.End(macBytes); | |||
11524 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11524); return rv; } } while (false); | |||
11525 | ||||
11526 | nsCString macBase64; | |||
11527 | rv = Base64Encode( | |||
11528 | nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()), | |||
11529 | macBytes.Length()), | |||
11530 | macBase64); | |||
11531 | 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, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11531); return rv; } } while (false); | |||
11532 | ||||
11533 | CopyUTF8toUTF16(macBase64, aId); | |||
11534 | return NS_OK; | |||
11535 | } | |||
11536 | ||||
11537 | void nsContentUtils::RequestGeckoTaskBurst() { | |||
11538 | nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{ 0x2d96b3df, 0xc051, 0x11d1, { 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }); | |||
11539 | if (appShell) { | |||
11540 | appShell->GeckoTaskBurst(); | |||
11541 | } | |||
11542 | } | |||
11543 | ||||
11544 | nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) { | |||
11545 | for (nsIContent* content = aContent; content; | |||
11546 | content = content->GetFlattenedTreeParent()) { | |||
11547 | if (nsContentUtils::IsDraggableLink(content)) { | |||
11548 | return content; | |||
11549 | } | |||
11550 | } | |||
11551 | return nullptr; | |||
11552 | } | |||
11553 | ||||
11554 | template <TreeKind aKind> | |||
11555 | MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) { | |||
11556 | if constexpr (aKind == TreeKind::DOM) { | |||
11557 | return aNode->GetParentNode(); | |||
11558 | } else { | |||
11559 | return aNode->GetFlattenedTreeParentNode(); | |||
11560 | } | |||
11561 | } | |||
11562 | ||||
11563 | template <TreeKind aKind> | |||
11564 | MOZ_ALWAYS_INLINEinline Maybe<uint32_t> GetIndexInParent(const nsINode* aParent, | |||
11565 | const nsINode* aNode) { | |||
11566 | if constexpr (aKind == TreeKind::DOM) { | |||
11567 | return aParent->ComputeIndexOf(aNode); | |||
11568 | } else { | |||
11569 | return aParent->ComputeFlatTreeIndexOf(aNode); | |||
11570 | } | |||
11571 | } | |||
11572 | ||||
11573 | template <TreeKind aTreeKind> | |||
11574 | int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1, | |||
11575 | const nsINode* aNode2, | |||
11576 | const nsINode* aCommonAncestor) { | |||
11577 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") (" "aNode1 must not be null" ")"); do { *((volatile int*)__null ) = 11577; __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); | |||
11578 | 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") (" "aNode2 must not be null" ")"); do { *((volatile int*)__null ) = 11578; __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); | |||
11579 | ||||
11580 | if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11580)) { | |||
11581 | return 0; | |||
11582 | } | |||
11583 | ||||
11584 | AutoTArray<const nsINode*, 32> node1Ancestors; | |||
11585 | const nsINode* c1; | |||
11586 | for (c1 = aNode1; c1 && c1 != aCommonAncestor; | |||
11587 | c1 = GetParent<aTreeKind>(c1)) { | |||
11588 | node1Ancestors.AppendElement(c1); | |||
11589 | } | |||
11590 | if (!c1 && aCommonAncestor) { | |||
11591 | // So, it turns out aCommonAncestor was not an ancestor of c1. Oops. | |||
11592 | // Never mind. We can continue as if aCommonAncestor was null. | |||
11593 | aCommonAncestor = nullptr; | |||
11594 | } | |||
11595 | ||||
11596 | AutoTArray<const nsINode*, 32> node2Ancestors; | |||
11597 | const nsINode* c2; | |||
11598 | for (c2 = aNode2; c2 && c2 != aCommonAncestor; | |||
11599 | c2 = GetParent<aTreeKind>(c2)) { | |||
11600 | node2Ancestors.AppendElement(c2); | |||
11601 | } | |||
11602 | if (!c2 && aCommonAncestor) { | |||
11603 | // So, it turns out aCommonAncestor was not an ancestor of c2. | |||
11604 | // We need to retry with no common ancestor hint. | |||
11605 | return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr); | |||
11606 | } | |||
11607 | ||||
11608 | int last1 = node1Ancestors.Length() - 1; | |||
11609 | int last2 = node2Ancestors.Length() - 1; | |||
11610 | const nsINode* node1Ancestor = nullptr; | |||
11611 | const nsINode* node2Ancestor = nullptr; | |||
11612 | while (last1 >= 0 && last2 >= 0 && | |||
11613 | ((node1Ancestor = node1Ancestors.ElementAt(last1)) == | |||
11614 | (node2Ancestor = node2Ancestors.ElementAt(last2)))) { | |||
11615 | last1--; | |||
11616 | last2--; | |||
11617 | } | |||
11618 | ||||
11619 | if (last1 < 0) { | |||
11620 | if (last2 < 0) { | |||
11621 | NS_ASSERTION(aNode1 == aNode2, "internal error?")do { if (!(aNode1 == aNode2)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "internal error?", "aNode1 == aNode2", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11621); MOZ_PretendNoReturn(); } } while (0); | |||
11622 | return 0; | |||
11623 | } | |||
11624 | // aContent1 is an ancestor of aContent2 | |||
11625 | return -1; | |||
11626 | } | |||
11627 | ||||
11628 | if (last2 < 0) { | |||
11629 | // aContent2 is an ancestor of aContent1 | |||
11630 | return 1; | |||
11631 | } | |||
11632 | ||||
11633 | // node1Ancestor != node2Ancestor, so they must be siblings with the | |||
11634 | // same parent | |||
11635 | const nsINode* parent = GetParent<aTreeKind>(node1Ancestor); | |||
11636 | if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsContentUtils.cpp" , 11636)) { // different documents?? | |||
11637 | return 0; | |||
11638 | } | |||
11639 | ||||
11640 | const Maybe<uint32_t> index1 = | |||
11641 | GetIndexInParent<aTreeKind>(parent, node1Ancestor); | |||
11642 | const Maybe<uint32_t> index2 = | |||
11643 | GetIndexInParent<aTreeKind>(parent, node2Ancestor); | |||
11644 | ||||
11645 | // None of the nodes are anonymous, just do a regular comparison. | |||
11646 | if (index1.isSome() && index2.isSome()) { | |||
11647 | return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2); | |||
11648 | } | |||
11649 | ||||
11650 | // Otherwise handle pseudo-element and anonymous node ordering. | |||
11651 | // ::marker -> ::before -> anon siblings -> regular siblings -> ::after | |||
11652 | auto PseudoIndex = [](const nsINode* aNode, | |||
11653 | const Maybe<uint32_t>& aNodeIndex) -> int32_t { | |||
11654 | if (aNodeIndex.isSome()) { | |||
11655 | return 1; // Not a pseudo. | |||
11656 | } | |||
11657 | if (aNode->IsGeneratedContentContainerForMarker()) { | |||
11658 | return -2; | |||
11659 | } | |||
11660 | if (aNode->IsGeneratedContentContainerForBefore()) { | |||
11661 | return -1; | |||
11662 | } | |||
11663 | if (aNode->IsGeneratedContentContainerForAfter()) { | |||
11664 | return 2; | |||
11665 | } | |||
11666 | return 0; | |||
11667 | }; | |||
11668 | ||||
11669 | return PseudoIndex(node1Ancestor, index1) - | |||
11670 | PseudoIndex(node2Ancestor, index2); | |||
11671 | } | |||
11672 | ||||
11673 | nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost, | |||
11674 | ShadowRootMode aMode, | |||
11675 | bool aIsClonable, | |||
11676 | bool aIsSerializable, | |||
11677 | bool aDelegatesFocus) { | |||
11678 | RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost); | |||
11679 | if (!host || host->GetShadowRoot()) { | |||
11680 | // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host | |||
11681 | return nullptr; | |||
11682 | } | |||
11683 | ||||
11684 | ShadowRootInit init; | |||
11685 | init.mMode = aMode; | |||
11686 | init.mDelegatesFocus = aDelegatesFocus; | |||
11687 | init.mSlotAssignment = SlotAssignmentMode::Named; | |||
11688 | init.mClonable = aIsClonable; | |||
11689 | init.mSerializable = aIsSerializable; | |||
11690 | ||||
11691 | RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors()); | |||
11692 | if (shadowRoot) { | |||
11693 | shadowRoot->SetIsDeclarative( | |||
11694 | nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes); | |||
11695 | // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals | |||
11696 | shadowRoot->SetAvailableToElementInternals(); | |||
11697 | } | |||
11698 | return shadowRoot; | |||
11699 | } | |||
11700 | ||||
11701 | template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>( | |||
11702 | const nsINode*, const nsINode*, const nsINode*); | |||
11703 | template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>( | |||
11704 | const nsINode*, const nsINode*, const nsINode*); | |||
11705 | ||||
11706 | namespace mozilla { | |||
11707 | std::ostream& operator<<(std::ostream& aOut, | |||
11708 | const PreventDefaultResult aPreventDefaultResult) { | |||
11709 | switch (aPreventDefaultResult) { | |||
11710 | case PreventDefaultResult::No: | |||
11711 | aOut << "unhandled"; | |||
11712 | break; | |||
11713 | case PreventDefaultResult::ByContent: | |||
11714 | aOut << "handled-by-content"; | |||
11715 | break; | |||
11716 | case PreventDefaultResult::ByChrome: | |||
11717 | aOut << "handled-by-chrome"; | |||
11718 | break; | |||
11719 | } | |||
11720 | return aOut; | |||
11721 | } | |||
11722 | } // namespace mozilla |