Line data Source code
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 <math.h>
13 :
14 : #include "DecoderTraits.h"
15 : #include "harfbuzz/hb.h"
16 : #include "imgICache.h"
17 : #include "imgIContainer.h"
18 : #include "imgINotificationObserver.h"
19 : #include "imgLoader.h"
20 : #include "imgRequestProxy.h"
21 : #include "jsapi.h"
22 : #include "jsfriendapi.h"
23 : #include "js/Value.h"
24 : #include "Layers.h"
25 : #include "MediaDecoder.h"
26 : #include "nsAppRunner.h"
27 : // nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
28 : #include "nsNPAPIPluginInstance.h"
29 : #include "gfxDrawable.h"
30 : #include "gfxPrefs.h"
31 : #include "ImageOps.h"
32 : #include "mozAutoDocUpdate.h"
33 : #include "mozilla/ArrayUtils.h"
34 : #include "mozilla/Attributes.h"
35 : #include "mozilla/AutoRestore.h"
36 : #include "mozilla/AutoTimelineMarker.h"
37 : #include "mozilla/Base64.h"
38 : #include "mozilla/CheckedInt.h"
39 : #include "mozilla/DebugOnly.h"
40 : #include "mozilla/LoadInfo.h"
41 : #include "mozilla/dom/ContentChild.h"
42 : #include "mozilla/dom/CustomElementRegistry.h"
43 : #include "mozilla/dom/DocumentFragment.h"
44 : #include "mozilla/dom/DOMTypes.h"
45 : #include "mozilla/dom/Element.h"
46 : #include "mozilla/dom/FileSystemSecurity.h"
47 : #include "mozilla/dom/FileBlobImpl.h"
48 : #include "mozilla/dom/HTMLInputElement.h"
49 : #include "mozilla/dom/HTMLMediaElement.h"
50 : #include "mozilla/dom/HTMLTemplateElement.h"
51 : #include "mozilla/dom/HTMLContentElement.h"
52 : #include "mozilla/dom/HTMLShadowElement.h"
53 : #include "mozilla/dom/IPCBlobUtils.h"
54 : #include "mozilla/dom/Promise.h"
55 : #include "mozilla/dom/ScriptSettings.h"
56 : #include "mozilla/dom/TabParent.h"
57 : #include "mozilla/dom/TouchEvent.h"
58 : #include "mozilla/dom/ShadowRoot.h"
59 : #include "mozilla/dom/XULCommandEvent.h"
60 : #include "mozilla/dom/WorkerPrivate.h"
61 : #include "mozilla/dom/workers/ServiceWorkerManager.h"
62 : #include "mozilla/EventDispatcher.h"
63 : #include "mozilla/EventListenerManager.h"
64 : #include "mozilla/EventStateManager.h"
65 : #include "mozilla/gfx/DataSurfaceHelpers.h"
66 : #include "mozilla/IMEStateManager.h"
67 : #include "mozilla/InternalMutationEvent.h"
68 : #include "mozilla/Likely.h"
69 : #include "mozilla/MouseEvents.h"
70 : #include "mozilla/Preferences.h"
71 : #include "mozilla/dom/Selection.h"
72 : #include "mozilla/TextEvents.h"
73 : #include "nsArrayUtils.h"
74 : #include "nsAString.h"
75 : #include "nsAttrName.h"
76 : #include "nsAttrValue.h"
77 : #include "nsAttrValueInlines.h"
78 : #include "nsBindingManager.h"
79 : #include "nsCanvasFrame.h"
80 : #include "nsCaret.h"
81 : #include "nsCCUncollectableMarker.h"
82 : #include "nsCharSeparatedTokenizer.h"
83 : #include "nsCOMPtr.h"
84 : #include "nsContentCreatorFunctions.h"
85 : #include "nsContentDLF.h"
86 : #include "nsContentList.h"
87 : #include "nsContentPolicyUtils.h"
88 : #include "nsContentSecurityManager.h"
89 : #include "nsCPrefetchService.h"
90 : #include "nsCRT.h"
91 : #include "nsCycleCollectionParticipant.h"
92 : #include "nsCycleCollector.h"
93 : #include "nsDataHashtable.h"
94 : #include "nsDocShellCID.h"
95 : #include "nsDocument.h"
96 : #include "nsDOMCID.h"
97 : #include "mozilla/dom/DataTransfer.h"
98 : #include "nsDOMJSUtils.h"
99 : #include "nsDOMMutationObserver.h"
100 : #include "nsError.h"
101 : #include "nsFocusManager.h"
102 : #include "nsGenericHTMLElement.h"
103 : #include "nsGenericHTMLFrameElement.h"
104 : #include "nsGkAtoms.h"
105 : #include "nsHostObjectProtocolHandler.h"
106 : #include "nsHtml5Module.h"
107 : #include "nsHtml5StringParser.h"
108 : #include "nsIAddonPolicyService.h"
109 : #include "nsIAnonymousContentCreator.h"
110 : #include "nsIAsyncVerifyRedirectCallback.h"
111 : #include "nsICategoryManager.h"
112 : #include "nsIChannelEventSink.h"
113 : #include "nsICharsetDetectionObserver.h"
114 : #include "nsIChromeRegistry.h"
115 : #include "nsIConsoleService.h"
116 : #include "nsIContent.h"
117 : #include "nsIContentInlines.h"
118 : #include "nsIContentSecurityPolicy.h"
119 : #include "nsIContentSink.h"
120 : #include "nsIContentViewer.h"
121 : #include "nsIDocShell.h"
122 : #include "nsIDocShellTreeOwner.h"
123 : #include "nsIDocument.h"
124 : #include "nsIDocumentEncoder.h"
125 : #include "nsIDOMChromeWindow.h"
126 : #include "nsIDOMDocument.h"
127 : #include "nsIDOMDocumentType.h"
128 : #include "nsIDOMEvent.h"
129 : #include "nsIDOMElement.h"
130 : #include "nsIDOMHTMLElement.h"
131 : #include "nsIDOMHTMLFormElement.h"
132 : #include "nsIDOMHTMLInputElement.h"
133 : #include "nsIDOMNode.h"
134 : #include "nsIDOMNodeList.h"
135 : #include "nsIDOMWindowUtils.h"
136 : #include "nsIDragService.h"
137 : #include "nsIEditor.h"
138 : #include "nsIFormControl.h"
139 : #include "nsIForm.h"
140 : #include "nsIFragmentContentSink.h"
141 : #include "nsContainerFrame.h"
142 : #include "nsIHTMLDocument.h"
143 : #include "nsIIdleService.h"
144 : #include "nsIImageLoadingContent.h"
145 : #include "nsIInterfaceRequestor.h"
146 : #include "nsIInterfaceRequestorUtils.h"
147 : #include "nsIIOService.h"
148 : #include "nsILineBreaker.h"
149 : #include "nsILoadContext.h"
150 : #include "nsILoadGroup.h"
151 : #include "nsIMemoryReporter.h"
152 : #include "nsIMIMEHeaderParam.h"
153 : #include "nsIMIMEService.h"
154 : #include "nsINode.h"
155 : #include "mozilla/dom/NodeInfo.h"
156 : #include "nsIObjectLoadingContent.h"
157 : #include "nsIObserver.h"
158 : #include "nsIObserverService.h"
159 : #include "nsIOfflineCacheUpdate.h"
160 : #include "nsIParser.h"
161 : #include "nsIParserService.h"
162 : #include "nsIPermissionManager.h"
163 : #include "nsIPluginHost.h"
164 : #include "nsIRequest.h"
165 : #include "nsIRunnable.h"
166 : #include "nsIScriptContext.h"
167 : #include "nsIScriptError.h"
168 : #include "nsIScriptGlobalObject.h"
169 : #include "nsIScriptObjectPrincipal.h"
170 : #include "nsIScriptSecurityManager.h"
171 : #include "nsIScrollable.h"
172 : #include "nsIStreamConverterService.h"
173 : #include "nsIStringBundle.h"
174 : #include "nsIURI.h"
175 : #include "nsIURIWithPrincipal.h"
176 : #include "nsIURL.h"
177 : #include "nsIWebNavigation.h"
178 : #include "nsIWindowMediator.h"
179 : #include "nsIWordBreaker.h"
180 : #include "nsIXPConnect.h"
181 : #include "nsJSUtils.h"
182 : #include "nsLWBrkCIID.h"
183 : #include "nsMappedAttributes.h"
184 : #include "nsNetCID.h"
185 : #include "nsNetUtil.h"
186 : #include "nsNodeInfoManager.h"
187 : #include "NullPrincipal.h"
188 : #include "nsParserCIID.h"
189 : #include "nsParserConstants.h"
190 : #include "nsPIDOMWindow.h"
191 : #include "nsPresContext.h"
192 : #include "nsPrintfCString.h"
193 : #include "nsReferencedElement.h"
194 : #include "nsSandboxFlags.h"
195 : #include "nsScriptSecurityManager.h"
196 : #include "nsSerializationHelper.h"
197 : #include "nsStreamUtils.h"
198 : #include "nsTextEditorState.h"
199 : #include "nsTextFragment.h"
200 : #include "nsTextNode.h"
201 : #include "nsThreadUtils.h"
202 : #include "nsUnicodeProperties.h"
203 : #include "nsViewManager.h"
204 : #include "nsViewportInfo.h"
205 : #include "nsWidgetsCID.h"
206 : #include "nsIWindowProvider.h"
207 : #include "nsWrapperCacheInlines.h"
208 : #include "nsXULPopupManager.h"
209 : #include "xpcprivate.h" // nsXPConnect
210 : #include "HTMLSplitOnSpacesTokenizer.h"
211 : #include "nsContentTypeParser.h"
212 : #include "nsICookiePermission.h"
213 : #include "mozIThirdPartyUtil.h"
214 : #include "nsICookieService.h"
215 : #include "mozilla/EnumSet.h"
216 : #include "mozilla/BloomFilter.h"
217 : #include "TabChild.h"
218 : #include "mozilla/dom/DocGroup.h"
219 : #include "mozilla/dom/TabGroup.h"
220 : #include "nsIWebNavigationInfo.h"
221 : #include "nsPluginHost.h"
222 : #include "mozilla/HangAnnotations.h"
223 : #include "mozilla/Encoding.h"
224 :
225 : #include "nsIBidiKeyboard.h"
226 :
227 : #if defined(XP_WIN)
228 : // Undefine LoadImage to prevent naming conflict with Windows.
229 : #undef LoadImage
230 : #endif
231 :
232 : extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
233 : const char** next, char16_t* result);
234 : extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
235 : int ns_aware, const char** colon);
236 :
237 : class imgLoader;
238 :
239 : using namespace mozilla::dom;
240 : using namespace mozilla::ipc;
241 : using namespace mozilla::gfx;
242 : using namespace mozilla::layers;
243 : using namespace mozilla::widget;
244 : using namespace mozilla;
245 :
246 : const char kLoadAsData[] = "loadAsData";
247 :
248 : nsIXPConnect *nsContentUtils::sXPConnect;
249 : nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
250 : nsIPrincipal *nsContentUtils::sSystemPrincipal;
251 : nsIPrincipal *nsContentUtils::sNullSubjectPrincipal;
252 : nsIParserService *nsContentUtils::sParserService = nullptr;
253 : nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
254 : nsIIOService *nsContentUtils::sIOService;
255 : nsIUUIDGenerator *nsContentUtils::sUUIDGenerator;
256 : nsIConsoleService *nsContentUtils::sConsoleService;
257 : nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
258 : nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
259 : nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nullptr;
260 : nsIStringBundleService *nsContentUtils::sStringBundleService;
261 : nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
262 : nsIContentPolicy *nsContentUtils::sContentPolicyService;
263 : bool nsContentUtils::sTriedToGetContentPolicy = false;
264 : nsILineBreaker *nsContentUtils::sLineBreaker;
265 : nsIWordBreaker *nsContentUtils::sWordBreaker;
266 : nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
267 : uint32_t nsContentUtils::sScriptBlockerCount = 0;
268 : uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
269 : uint32_t nsContentUtils::sMicroTaskLevel = 0;
270 : AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = nullptr;
271 : uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
272 : nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
273 :
274 : bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
275 : bool nsContentUtils::sAllowXULXBL_for_file = false;
276 :
277 : nsString* nsContentUtils::sShiftText = nullptr;
278 : nsString* nsContentUtils::sControlText = nullptr;
279 : nsString* nsContentUtils::sMetaText = nullptr;
280 : nsString* nsContentUtils::sOSText = nullptr;
281 : nsString* nsContentUtils::sAltText = nullptr;
282 : nsString* nsContentUtils::sModifierSeparator = nullptr;
283 :
284 : bool nsContentUtils::sInitialized = false;
285 : bool nsContentUtils::sIsFullScreenApiEnabled = false;
286 : bool nsContentUtils::sIsUnprefixedFullscreenApiEnabled = false;
287 : bool nsContentUtils::sTrustedFullScreenOnly = true;
288 : bool nsContentUtils::sIsCutCopyAllowed = true;
289 : bool nsContentUtils::sIsFrameTimingPrefEnabled = false;
290 : bool nsContentUtils::sIsPerformanceTimingEnabled = false;
291 : bool nsContentUtils::sIsResourceTimingEnabled = false;
292 : bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
293 : bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
294 : bool nsContentUtils::sIsWebComponentsEnabled = false;
295 : bool nsContentUtils::sIsCustomElementsEnabled = false;
296 : bool nsContentUtils::sSendPerformanceTimingNotifications = false;
297 : bool nsContentUtils::sUseActivityCursor = false;
298 : bool nsContentUtils::sAnimationsAPICoreEnabled = false;
299 : bool nsContentUtils::sAnimationsAPIElementAnimateEnabled = false;
300 : bool nsContentUtils::sGetBoxQuadsEnabled = false;
301 : bool nsContentUtils::sSkipCursorMoveForSameValueSet = false;
302 : bool nsContentUtils::sRequestIdleCallbackEnabled = false;
303 : bool nsContentUtils::sLowerNetworkPriority = false;
304 : bool nsContentUtils::sShowInputPlaceholderOnFocus = true;
305 : bool nsContentUtils::sAutoFocusEnabled = true;
306 : #ifndef RELEASE_OR_BETA
307 : bool nsContentUtils::sBypassCSSOMOriginCheck = false;
308 : #endif
309 : bool nsContentUtils::sIsScopedStyleEnabled = false;
310 :
311 : bool nsContentUtils::sIsBytecodeCacheEnabled = false;
312 : int32_t nsContentUtils::sBytecodeCacheStrategy = 0;
313 : nsCString* nsContentUtils::sJSBytecodeMimeType = nullptr;
314 :
315 : int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000;
316 : int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000;
317 :
318 : nsContentUtils::UserInteractionObserver*
319 : nsContentUtils::sUserInteractionObserver = nullptr;
320 :
321 : uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
322 :
323 : uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
324 : uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
325 :
326 : nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
327 : nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
328 : nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
329 : bool nsContentUtils::sFragmentParsingActive = false;
330 : nsISerialEventTarget* nsContentUtils::sStableStateEventTarget = nullptr;
331 :
332 : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
333 : bool nsContentUtils::sDOMWindowDumpEnabled;
334 : #endif
335 :
336 : bool nsContentUtils::sDoNotTrackEnabled = false;
337 :
338 : mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
339 :
340 : // Subset of http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
341 : enum AutocompleteUnsupportedFieldName : uint8_t
342 : {
343 : #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
344 : eAutocompleteUnsupportedFieldName_##name_,
345 : #include "AutocompleteFieldList.h"
346 : #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
347 : };
348 :
349 : enum AutocompleteUnsupportFieldContactHint : uint8_t
350 : {
351 : #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
352 : eAutocompleteUnsupportedFieldContactHint_##name_,
353 : #include "AutocompleteFieldList.h"
354 : #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
355 : };
356 :
357 : enum AutocompleteFieldName : uint8_t
358 : {
359 : #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
360 : eAutocompleteFieldName_##name_,
361 : #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
362 : AUTOCOMPLETE_FIELD_NAME(name_, value_)
363 : #include "AutocompleteFieldList.h"
364 : #undef AUTOCOMPLETE_FIELD_NAME
365 : #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
366 : };
367 :
368 : enum AutocompleteFieldHint : uint8_t
369 : {
370 : #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
371 : eAutocompleteFieldHint_##name_,
372 : #include "AutocompleteFieldList.h"
373 : #undef AUTOCOMPLETE_FIELD_HINT
374 : };
375 :
376 : enum AutocompleteFieldContactHint : uint8_t
377 : {
378 : #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
379 : eAutocompleteFieldContactHint_##name_,
380 : #include "AutocompleteFieldList.h"
381 : #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
382 : };
383 :
384 : enum AutocompleteCategory
385 : {
386 : #define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
387 : #include "AutocompleteFieldList.h"
388 : #undef AUTOCOMPLETE_CATEGORY
389 : };
390 :
391 : static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
392 : #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
393 : { value_, eAutocompleteUnsupportedFieldName_##name_ },
394 : #include "AutocompleteFieldList.h"
395 : #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
396 : { nullptr, 0 }
397 : };
398 :
399 : static const nsAttrValue::EnumTable kAutocompleteUnsupportedContactFieldHintTable[] = {
400 : #define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
401 : { value_, eAutocompleteUnsupportedFieldContactHint_##name_ },
402 : #include "AutocompleteFieldList.h"
403 : #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
404 : { nullptr, 0 }
405 : };
406 :
407 :
408 : static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
409 : #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
410 : { value_, eAutocompleteFieldName_##name_ },
411 : #include "AutocompleteFieldList.h"
412 : #undef AUTOCOMPLETE_FIELD_NAME
413 : { nullptr, 0 }
414 : };
415 :
416 : static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
417 : #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
418 : { value_, eAutocompleteFieldName_##name_ },
419 : #include "AutocompleteFieldList.h"
420 : #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
421 : { nullptr, 0 }
422 : };
423 :
424 : static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
425 : #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
426 : { value_, eAutocompleteFieldHint_##name_ },
427 : #include "AutocompleteFieldList.h"
428 : #undef AUTOCOMPLETE_FIELD_HINT
429 : { nullptr, 0 }
430 : };
431 :
432 : static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
433 : #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
434 : { value_, eAutocompleteFieldContactHint_##name_ },
435 : #include "AutocompleteFieldList.h"
436 : #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
437 : { nullptr, 0 }
438 : };
439 :
440 : namespace {
441 :
442 : static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
443 : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
444 :
445 : static PLDHashTable* sEventListenerManagersHash;
446 :
447 3 : class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter
448 : {
449 0 : MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
450 :
451 : ~DOMEventListenerManagersHashReporter() = default;
452 :
453 : public:
454 : NS_DECL_ISUPPORTS
455 :
456 0 : NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
457 : nsISupports* aData, bool aAnonymize) override
458 : {
459 : // We don't measure the |EventListenerManager| objects pointed to by the
460 : // entries because those references are non-owning.
461 : int64_t amount = sEventListenerManagersHash
462 0 : ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
463 : MallocSizeOf)
464 0 : : 0;
465 :
466 0 : MOZ_COLLECT_REPORT(
467 : "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
468 : amount,
469 0 : "Memory used by the event listener manager's hash table.");
470 :
471 0 : return NS_OK;
472 : }
473 : };
474 :
475 39 : NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
476 :
477 : class EventListenerManagerMapEntry : public PLDHashEntryHdr
478 : {
479 : public:
480 556 : explicit EventListenerManagerMapEntry(const void* aKey)
481 556 : : mKey(aKey)
482 : {
483 556 : }
484 :
485 3 : ~EventListenerManagerMapEntry()
486 3 : {
487 3 : NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
488 3 : }
489 :
490 : protected: // declared protected to silence clang warnings
491 : const void *mKey; // must be first, to look like PLDHashEntryStub
492 :
493 : public:
494 : RefPtr<EventListenerManager> mListenerManager;
495 : };
496 :
497 : static void
498 556 : EventListenerManagerHashInitEntry(PLDHashEntryHdr *entry, const void *key)
499 : {
500 : // Initialize the entry with placement new
501 556 : new (entry) EventListenerManagerMapEntry(key);
502 556 : }
503 :
504 : static void
505 3 : EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
506 : {
507 : EventListenerManagerMapEntry *lm =
508 3 : static_cast<EventListenerManagerMapEntry *>(entry);
509 :
510 : // Let the EventListenerManagerMapEntry clean itself up...
511 3 : lm->~EventListenerManagerMapEntry();
512 3 : }
513 :
514 0 : class SameOriginCheckerImpl final : public nsIChannelEventSink,
515 : public nsIInterfaceRequestor
516 : {
517 : ~SameOriginCheckerImpl() = default;
518 :
519 : NS_DECL_ISUPPORTS
520 : NS_DECL_NSICHANNELEVENTSINK
521 : NS_DECL_NSIINTERFACEREQUESTOR
522 : };
523 :
524 3 : class StableStateEventTarget final : public nsISerialEventTarget
525 : {
526 : public:
527 : NS_DECL_THREADSAFE_ISUPPORTS
528 : NS_DECL_NSIEVENTTARGET_FULL
529 : private:
530 0 : ~StableStateEventTarget() {}
531 : };
532 :
533 3 : NS_IMPL_ISUPPORTS(StableStateEventTarget, nsISerialEventTarget);
534 :
535 : bool
536 0 : StableStateEventTarget::IsOnCurrentThreadInfallible()
537 : {
538 0 : return true;
539 : }
540 :
541 : NS_IMETHODIMP
542 0 : StableStateEventTarget::IsOnCurrentThread(bool* aResult)
543 : {
544 0 : *aResult = true;
545 0 : return NS_OK;
546 : }
547 :
548 : NS_IMETHODIMP
549 0 : StableStateEventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
550 : {
551 0 : if (NS_WARN_IF(!CycleCollectedJSContext::Get())) {
552 0 : return NS_ERROR_UNEXPECTED;
553 : }
554 0 : nsContentUtils::RunInStableState(Move(aEvent));
555 0 : return NS_OK;
556 : }
557 :
558 : NS_IMETHODIMP
559 0 : StableStateEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
560 : {
561 0 : return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
562 : }
563 :
564 : NS_IMETHODIMP
565 0 : StableStateEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aDelay)
566 : {
567 0 : return NS_ERROR_NOT_IMPLEMENTED;
568 : }
569 :
570 : } // namespace
571 :
572 : /**
573 : * This class is used to determine whether or not the user is currently
574 : * interacting with the browser. It listens to observer events to toggle the
575 : * value of the sUserActive static.
576 : *
577 : * This class is an internal implementation detail.
578 : * nsContentUtils::GetUserIsInteracting() should be used to access current
579 : * user interaction status.
580 : */
581 3 : class nsContentUtils::UserInteractionObserver final : public nsIObserver
582 : , public HangMonitor::Annotator
583 : {
584 : public:
585 : NS_DECL_ISUPPORTS
586 : NS_DECL_NSIOBSERVER
587 :
588 : void Init();
589 : void Shutdown();
590 : void AnnotateHang(HangMonitor::HangAnnotations& aAnnotations) override;
591 :
592 : static Atomic<bool> sUserActive;
593 :
594 : private:
595 0 : ~UserInteractionObserver() {}
596 : };
597 :
598 : /* static */
599 : TimeDuration
600 0 : nsContentUtils::HandlingUserInputTimeout()
601 : {
602 0 : return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
603 : }
604 :
605 : // static
606 : nsresult
607 3 : nsContentUtils::Init()
608 : {
609 3 : if (sInitialized) {
610 0 : NS_WARNING("Init() called twice");
611 :
612 0 : return NS_OK;
613 : }
614 :
615 3 : sNameSpaceManager = nsNameSpaceManager::GetInstance();
616 3 : NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
617 :
618 3 : sXPConnect = nsXPConnect::XPConnect();
619 :
620 3 : sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
621 3 : if(!sSecurityManager)
622 0 : return NS_ERROR_FAILURE;
623 3 : NS_ADDREF(sSecurityManager);
624 :
625 3 : sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
626 3 : MOZ_ASSERT(sSystemPrincipal);
627 :
628 6 : RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create();
629 3 : if (!nullPrincipal) {
630 0 : return NS_ERROR_FAILURE;
631 : }
632 :
633 3 : nullPrincipal.forget(&sNullSubjectPrincipal);
634 :
635 3 : nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
636 3 : if (NS_FAILED(rv)) {
637 : // This makes life easier, but we can live without it.
638 :
639 0 : sIOService = nullptr;
640 : }
641 :
642 3 : rv = CallGetService(NS_LBRK_CONTRACTID, &sLineBreaker);
643 3 : NS_ENSURE_SUCCESS(rv, rv);
644 :
645 3 : rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
646 3 : NS_ENSURE_SUCCESS(rv, rv);
647 :
648 3 : if (!InitializeEventTable())
649 0 : return NS_ERROR_FAILURE;
650 :
651 3 : if (!sEventListenerManagersHash) {
652 : static const PLDHashTableOps hash_table_ops =
653 : {
654 : PLDHashTable::HashVoidPtrKeyStub,
655 : PLDHashTable::MatchEntryStub,
656 : PLDHashTable::MoveEntryStub,
657 : EventListenerManagerHashClearEntry,
658 : EventListenerManagerHashInitEntry
659 : };
660 :
661 3 : sEventListenerManagersHash =
662 3 : new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
663 :
664 3 : RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
665 : }
666 :
667 3 : sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
668 :
669 : Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
670 3 : "dom.allow_XUL_XBL_for_file");
671 :
672 : Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
673 3 : "full-screen-api.enabled");
674 :
675 : Preferences::AddBoolVarCache(&sIsUnprefixedFullscreenApiEnabled,
676 3 : "full-screen-api.unprefix.enabled");
677 :
678 : Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
679 3 : "full-screen-api.allow-trusted-requests-only");
680 :
681 : Preferences::AddBoolVarCache(&sIsCutCopyAllowed,
682 3 : "dom.allow_cut_copy", true);
683 :
684 : Preferences::AddBoolVarCache(&sIsPerformanceTimingEnabled,
685 3 : "dom.enable_performance", true);
686 :
687 : Preferences::AddBoolVarCache(&sIsResourceTimingEnabled,
688 3 : "dom.enable_resource_timing", true);
689 :
690 : Preferences::AddBoolVarCache(&sIsUserTimingLoggingEnabled,
691 3 : "dom.performance.enable_user_timing_logging", false);
692 :
693 : Preferences::AddBoolVarCache(&sIsFrameTimingPrefEnabled,
694 3 : "dom.enable_frame_timing", false);
695 :
696 : Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
697 3 : "dom.forms.autocomplete.experimental", false);
698 :
699 : Preferences::AddBoolVarCache(&sIsWebComponentsEnabled,
700 3 : "dom.webcomponents.enabled", false);
701 :
702 : Preferences::AddBoolVarCache(&sIsCustomElementsEnabled,
703 3 : "dom.webcomponents.customelements.enabled", false);
704 :
705 : Preferences::AddIntVarCache(&sPrivacyMaxInnerWidth,
706 : "privacy.window.maxInnerWidth",
707 3 : 1000);
708 :
709 : Preferences::AddIntVarCache(&sPrivacyMaxInnerHeight,
710 : "privacy.window.maxInnerHeight",
711 3 : 1000);
712 :
713 : Preferences::AddUintVarCache(&sHandlingInputTimeout,
714 : "dom.event.handling-user-input-time-limit",
715 3 : 1000);
716 :
717 : Preferences::AddBoolVarCache(&sSendPerformanceTimingNotifications,
718 3 : "dom.performance.enable_notify_performance_timing", false);
719 :
720 : Preferences::AddUintVarCache(&sCookiesLifetimePolicy,
721 : "network.cookie.lifetimePolicy",
722 3 : nsICookieService::ACCEPT_NORMALLY);
723 :
724 : Preferences::AddUintVarCache(&sCookiesBehavior,
725 : "network.cookie.cookieBehavior",
726 3 : nsICookieService::BEHAVIOR_ACCEPT);
727 :
728 : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
729 : Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
730 : "browser.dom.window.dump.enabled");
731 : #endif
732 :
733 : Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
734 3 : "privacy.donottrackheader.enabled", false);
735 :
736 : Preferences::AddBoolVarCache(&sUseActivityCursor,
737 3 : "ui.use_activity_cursor", false);
738 :
739 : Preferences::AddBoolVarCache(&sAnimationsAPICoreEnabled,
740 3 : "dom.animations-api.core.enabled", false);
741 :
742 : Preferences::AddBoolVarCache(&sAnimationsAPIElementAnimateEnabled,
743 3 : "dom.animations-api.element-animate.enabled", false);
744 :
745 : Preferences::AddBoolVarCache(&sGetBoxQuadsEnabled,
746 3 : "layout.css.getBoxQuads.enabled", false);
747 :
748 : Preferences::AddBoolVarCache(&sSkipCursorMoveForSameValueSet,
749 : "dom.input.skip_cursor_move_for_same_value_set",
750 3 : true);
751 :
752 : Preferences::AddBoolVarCache(&sRequestIdleCallbackEnabled,
753 3 : "dom.requestIdleCallback.enabled", false);
754 :
755 : #ifndef RELEASE_OR_BETA
756 3 : sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
757 : #endif
758 :
759 : Preferences::AddBoolVarCache(&sIsScopedStyleEnabled,
760 3 : "layout.css.scoped-style.enabled", false);
761 :
762 : Preferences::AddBoolVarCache(&sLowerNetworkPriority,
763 3 : "privacy.trackingprotection.lower_network_priority", false);
764 :
765 : Preferences::AddBoolVarCache(&sShowInputPlaceholderOnFocus,
766 3 : "dom.placeholder.show_on_focus", true);
767 :
768 : Preferences::AddBoolVarCache(&sAutoFocusEnabled,
769 3 : "browser.autofocus", true);
770 :
771 : Preferences::AddBoolVarCache(&sIsBytecodeCacheEnabled,
772 3 : "dom.script_loader.bytecode_cache.enabled", false);
773 :
774 : Preferences::AddIntVarCache(&sBytecodeCacheStrategy,
775 3 : "dom.script_loader.bytecode_cache.strategy", 0);
776 :
777 6 : nsDependentCString buildID(mozilla::PlatformBuildID());
778 6 : sJSBytecodeMimeType = new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
779 :
780 3 : Element::InitCCCallbacks();
781 :
782 3 : Unused << nsRFPService::GetOrCreate();
783 :
784 6 : RefPtr<StableStateEventTarget> stableStateEventTarget = new StableStateEventTarget();
785 3 : stableStateEventTarget.forget(&sStableStateEventTarget);
786 :
787 : nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
788 6 : do_GetService("@mozilla.org/uuid-generator;1", &rv);
789 3 : if (NS_WARN_IF(NS_FAILED(rv))) {
790 0 : return rv;
791 : }
792 3 : uuidGenerator.forget(&sUUIDGenerator);
793 :
794 6 : RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
795 3 : uio->Init();
796 3 : uio.forget(&sUserInteractionObserver);
797 :
798 3 : sInitialized = true;
799 :
800 3 : return NS_OK;
801 : }
802 :
803 : void
804 0 : nsContentUtils::GetShiftText(nsAString& text)
805 : {
806 0 : if (!sShiftText)
807 0 : InitializeModifierStrings();
808 0 : text.Assign(*sShiftText);
809 0 : }
810 :
811 : void
812 0 : nsContentUtils::GetControlText(nsAString& text)
813 : {
814 0 : if (!sControlText)
815 0 : InitializeModifierStrings();
816 0 : text.Assign(*sControlText);
817 0 : }
818 :
819 : void
820 0 : nsContentUtils::GetMetaText(nsAString& text)
821 : {
822 0 : if (!sMetaText)
823 0 : InitializeModifierStrings();
824 0 : text.Assign(*sMetaText);
825 0 : }
826 :
827 : void
828 0 : nsContentUtils::GetOSText(nsAString& text)
829 : {
830 0 : if (!sOSText) {
831 0 : InitializeModifierStrings();
832 : }
833 0 : text.Assign(*sOSText);
834 0 : }
835 :
836 : void
837 0 : nsContentUtils::GetAltText(nsAString& text)
838 : {
839 0 : if (!sAltText)
840 0 : InitializeModifierStrings();
841 0 : text.Assign(*sAltText);
842 0 : }
843 :
844 : void
845 0 : nsContentUtils::GetModifierSeparatorText(nsAString& text)
846 : {
847 0 : if (!sModifierSeparator)
848 0 : InitializeModifierStrings();
849 0 : text.Assign(*sModifierSeparator);
850 0 : }
851 :
852 : void
853 0 : nsContentUtils::InitializeModifierStrings()
854 : {
855 : //load the display strings for the keyboard accelerators
856 : nsCOMPtr<nsIStringBundleService> bundleService =
857 0 : mozilla::services::GetStringBundleService();
858 0 : nsCOMPtr<nsIStringBundle> bundle;
859 0 : DebugOnly<nsresult> rv = NS_OK;
860 0 : if (bundleService) {
861 0 : rv = bundleService->CreateBundle( "chrome://global-platform/locale/platformKeys.properties",
862 0 : getter_AddRefs(bundle));
863 : }
864 :
865 0 : NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/platformKeys.properties could not be loaded");
866 0 : nsXPIDLString shiftModifier;
867 0 : nsXPIDLString metaModifier;
868 0 : nsXPIDLString osModifier;
869 0 : nsXPIDLString altModifier;
870 0 : nsXPIDLString controlModifier;
871 0 : nsXPIDLString modifierSeparator;
872 0 : if (bundle) {
873 : //macs use symbols for each modifier key, so fetch each from the bundle, which also covers i18n
874 0 : bundle->GetStringFromName(u"VK_SHIFT", getter_Copies(shiftModifier));
875 0 : bundle->GetStringFromName(u"VK_META", getter_Copies(metaModifier));
876 0 : bundle->GetStringFromName(u"VK_WIN", getter_Copies(osModifier));
877 0 : bundle->GetStringFromName(u"VK_ALT", getter_Copies(altModifier));
878 0 : bundle->GetStringFromName(u"VK_CONTROL", getter_Copies(controlModifier));
879 0 : bundle->GetStringFromName(u"MODIFIER_SEPARATOR", getter_Copies(modifierSeparator));
880 : }
881 : //if any of these don't exist, we get an empty string
882 0 : sShiftText = new nsString(shiftModifier);
883 0 : sMetaText = new nsString(metaModifier);
884 0 : sOSText = new nsString(osModifier);
885 0 : sAltText = new nsString(altModifier);
886 0 : sControlText = new nsString(controlModifier);
887 0 : sModifierSeparator = new nsString(modifierSeparator);
888 0 : }
889 :
890 : mozilla::EventClassID
891 4 : nsContentUtils::GetEventClassIDFromMessage(EventMessage aEventMessage)
892 : {
893 4 : switch (aEventMessage) {
894 : #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
895 : case message_: return struct_;
896 : #include "mozilla/EventNameList.h"
897 : #undef MESSAGE_TO_EVENT
898 : default:
899 0 : MOZ_ASSERT_UNREACHABLE("Invalid event message?");
900 : return eBasicEventClass;
901 : }
902 : }
903 :
904 : static nsIAtom*
905 607 : GetEventTypeFromMessage(EventMessage aEventMessage)
906 : {
907 607 : switch (aEventMessage) {
908 : #define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
909 : case message_: return nsGkAtoms::on##name_;
910 : #include "mozilla/EventNameList.h"
911 : #undef MESSAGE_TO_EVENT
912 : default:
913 0 : return nullptr;
914 : }
915 : }
916 :
917 : // Because of SVG/SMIL we have several atoms mapped to the same
918 : // id, but we can rely on MESSAGE_TO_EVENT to map id to only one atom.
919 : static bool
920 603 : ShouldAddEventToStringEventTable(const EventNameMapping& aMapping)
921 : {
922 603 : MOZ_ASSERT(aMapping.mAtom);
923 603 : return GetEventTypeFromMessage(aMapping.mMessage) == aMapping.mAtom;
924 : }
925 :
926 : bool
927 3 : nsContentUtils::InitializeEventTable() {
928 3 : NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
929 3 : NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
930 :
931 : static const EventNameMapping eventArray[] = {
932 : #define EVENT(name_, _message, _type, _class) \
933 : { nsGkAtoms::on##name_, _type, _message, _class, false },
934 : #define WINDOW_ONLY_EVENT EVENT
935 : #define DOCUMENT_ONLY_EVENT EVENT
936 : #define NON_IDL_EVENT EVENT
937 : #include "mozilla/EventNameList.h"
938 : #undef WINDOW_ONLY_EVENT
939 : #undef NON_IDL_EVENT
940 : #undef EVENT
941 : { nullptr }
942 3 : };
943 :
944 3 : sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>(
945 6 : ArrayLength(eventArray));
946 3 : sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>(
947 6 : ArrayLength(eventArray));
948 3 : sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
949 :
950 : // Subtract one from the length because of the trailing null
951 606 : for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) {
952 603 : MOZ_ASSERT(!sAtomEventTable->Lookup(eventArray[i].mAtom),
953 : "Double-defining event name; fix your EventNameList.h");
954 603 : sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]);
955 603 : if (ShouldAddEventToStringEventTable(eventArray[i])) {
956 1164 : sStringEventTable->Put(
957 1164 : Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
958 582 : eventArray[i]);
959 : }
960 : }
961 :
962 3 : return true;
963 : }
964 :
965 : void
966 0 : nsContentUtils::InitializeTouchEventTable()
967 : {
968 : static bool sEventTableInitialized = false;
969 0 : if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
970 0 : sEventTableInitialized = true;
971 : static const EventNameMapping touchEventArray[] = {
972 : #define EVENT(name_, _message, _type, _class)
973 : #define TOUCH_EVENT(name_, _message, _type, _class) \
974 : { nsGkAtoms::on##name_, _type, _message, _class },
975 : #include "mozilla/EventNameList.h"
976 : #undef TOUCH_EVENT
977 : #undef EVENT
978 : { nullptr }
979 0 : };
980 : // Subtract one from the length because of the trailing null
981 0 : for (uint32_t i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
982 0 : sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]);
983 0 : sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
984 0 : touchEventArray[i]);
985 : }
986 : }
987 0 : }
988 :
989 : static bool
990 0 : Is8bit(const nsAString& aString)
991 : {
992 : static const char16_t EIGHT_BIT = char16_t(~0x00FF);
993 :
994 0 : for (nsAString::const_char_iterator start = aString.BeginReading(),
995 0 : end = aString.EndReading();
996 0 : start != end;
997 : ++start) {
998 0 : if (*start & EIGHT_BIT) {
999 0 : return false;
1000 : }
1001 : }
1002 :
1003 0 : return true;
1004 : }
1005 :
1006 : nsresult
1007 0 : nsContentUtils::Btoa(const nsAString& aBinaryData,
1008 : nsAString& aAsciiBase64String)
1009 : {
1010 0 : if (!Is8bit(aBinaryData)) {
1011 0 : aAsciiBase64String.Truncate();
1012 0 : return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1013 : }
1014 :
1015 0 : return Base64Encode(aBinaryData, aAsciiBase64String);
1016 : }
1017 :
1018 : nsresult
1019 0 : nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1020 : nsAString& aBinaryData)
1021 : {
1022 0 : if (!Is8bit(aAsciiBase64String)) {
1023 0 : aBinaryData.Truncate();
1024 0 : return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1025 : }
1026 :
1027 0 : const char16_t* start = aAsciiBase64String.BeginReading();
1028 0 : const char16_t* end = aAsciiBase64String.EndReading();
1029 0 : nsString trimmedString;
1030 0 : if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1031 0 : return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1032 : }
1033 0 : while (start < end) {
1034 0 : if (!nsContentUtils::IsHTMLWhitespace(*start)) {
1035 0 : trimmedString.Append(*start);
1036 : }
1037 0 : start++;
1038 : }
1039 0 : nsresult rv = Base64Decode(trimmedString, aBinaryData);
1040 0 : if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
1041 0 : return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1042 : }
1043 0 : return rv;
1044 : }
1045 :
1046 : bool
1047 0 : nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
1048 : {
1049 0 : NS_PRECONDITION(aInput, "aInput should not be null!");
1050 :
1051 0 : nsAutoString autocomplete;
1052 0 : aInput->GetAutocomplete(autocomplete);
1053 :
1054 0 : if (autocomplete.IsEmpty()) {
1055 0 : nsCOMPtr<nsIDOMHTMLFormElement> form;
1056 0 : aInput->GetForm(getter_AddRefs(form));
1057 0 : if (!form) {
1058 0 : return true;
1059 : }
1060 :
1061 0 : form->GetAutocomplete(autocomplete);
1062 : }
1063 :
1064 0 : return !autocomplete.EqualsLiteral("off");
1065 : }
1066 :
1067 : nsContentUtils::AutocompleteAttrState
1068 0 : nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
1069 : nsAString& aResult,
1070 : AutocompleteAttrState aCachedState)
1071 : {
1072 0 : if (!aAttr ||
1073 : aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1074 0 : return aCachedState;
1075 : }
1076 :
1077 0 : if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1078 0 : uint32_t atomCount = aAttr->GetAtomCount();
1079 0 : for (uint32_t i = 0; i < atomCount; i++) {
1080 0 : if (i != 0) {
1081 0 : aResult.Append(' ');
1082 : }
1083 0 : aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1084 : }
1085 0 : nsContentUtils::ASCIIToLower(aResult);
1086 0 : return aCachedState;
1087 : }
1088 :
1089 0 : aResult.Truncate();
1090 :
1091 0 : mozilla::dom::AutocompleteInfo info;
1092 : AutocompleteAttrState state =
1093 0 : InternalSerializeAutocompleteAttribute(aAttr, info);
1094 0 : if (state == eAutocompleteAttrState_Valid) {
1095 : // Concatenate the info fields.
1096 0 : aResult = info.mSection;
1097 :
1098 0 : if (!info.mAddressType.IsEmpty()) {
1099 0 : if (!aResult.IsEmpty()) {
1100 0 : aResult += ' ';
1101 : }
1102 0 : aResult += info.mAddressType;
1103 : }
1104 :
1105 0 : if (!info.mContactType.IsEmpty()) {
1106 0 : if (!aResult.IsEmpty()) {
1107 0 : aResult += ' ';
1108 : }
1109 0 : aResult += info.mContactType;
1110 : }
1111 :
1112 0 : if (!info.mFieldName.IsEmpty()) {
1113 0 : if (!aResult.IsEmpty()) {
1114 0 : aResult += ' ';
1115 : }
1116 0 : aResult += info.mFieldName;
1117 : }
1118 : }
1119 :
1120 0 : return state;
1121 : }
1122 :
1123 : nsContentUtils::AutocompleteAttrState
1124 0 : nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
1125 : mozilla::dom::AutocompleteInfo& aInfo,
1126 : AutocompleteAttrState aCachedState,
1127 : bool aGrantAllValidValue)
1128 : {
1129 0 : if (!aAttr ||
1130 : aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1131 0 : return aCachedState;
1132 : }
1133 :
1134 0 : return InternalSerializeAutocompleteAttribute(aAttr, aInfo, aGrantAllValidValue);
1135 : }
1136 :
1137 : /**
1138 : * Helper to validate the @autocomplete tokens.
1139 : *
1140 : * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1141 : */
1142 : nsContentUtils::AutocompleteAttrState
1143 0 : nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
1144 : mozilla::dom::AutocompleteInfo& aInfo,
1145 : bool aGrantAllValidValue)
1146 : {
1147 : // No sandbox attribute so we are done
1148 0 : if (!aAttrVal) {
1149 0 : return eAutocompleteAttrState_Invalid;
1150 : }
1151 :
1152 0 : uint32_t numTokens = aAttrVal->GetAtomCount();
1153 0 : if (!numTokens) {
1154 0 : return eAutocompleteAttrState_Invalid;
1155 : }
1156 :
1157 0 : uint32_t index = numTokens - 1;
1158 0 : nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1159 : AutocompleteCategory category;
1160 0 : nsAttrValue enumValue;
1161 :
1162 0 : bool unsupported = false;
1163 0 : if (!aGrantAllValidValue) {
1164 : unsupported = enumValue.ParseEnumValue(tokenString,
1165 : kAutocompleteUnsupportedFieldNameTable,
1166 0 : false);
1167 0 : if (unsupported) {
1168 0 : return eAutocompleteAttrState_Invalid;
1169 : }
1170 : }
1171 :
1172 0 : nsAutoString str;
1173 0 : bool result = enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1174 0 : if (result) {
1175 : // Off/Automatic/Normal categories.
1176 0 : if (enumValue.Equals(NS_LITERAL_STRING("off"), eIgnoreCase) ||
1177 0 : enumValue.Equals(NS_LITERAL_STRING("on"), eIgnoreCase)) {
1178 0 : if (numTokens > 1) {
1179 0 : return eAutocompleteAttrState_Invalid;
1180 : }
1181 0 : enumValue.ToString(str);
1182 0 : ASCIIToLower(str);
1183 0 : aInfo.mFieldName.Assign(str);
1184 0 : return eAutocompleteAttrState_Valid;
1185 : }
1186 :
1187 : // Only allow on/off if experimental @autocomplete values aren't enabled
1188 : // and it doesn't grant all valid values.
1189 0 : if (!sIsExperimentalAutocompleteEnabled && !aGrantAllValidValue) {
1190 0 : return eAutocompleteAttrState_Invalid;
1191 : }
1192 :
1193 : // Normal category
1194 0 : if (numTokens > 3) {
1195 0 : return eAutocompleteAttrState_Invalid;
1196 : }
1197 0 : category = eAutocompleteCategory_NORMAL;
1198 : } else { // Check if the last token is of the contact category instead.
1199 : // Only allow on/off if experimental @autocomplete values aren't enabled
1200 : // and it doesn't grant all valid values.
1201 0 : if (!sIsExperimentalAutocompleteEnabled && !aGrantAllValidValue) {
1202 0 : return eAutocompleteAttrState_Invalid;
1203 : }
1204 :
1205 0 : result = enumValue.ParseEnumValue(tokenString, kAutocompleteContactFieldNameTable, false);
1206 0 : if (!result || numTokens > 4) {
1207 0 : return eAutocompleteAttrState_Invalid;
1208 : }
1209 :
1210 0 : category = eAutocompleteCategory_CONTACT;
1211 : }
1212 :
1213 0 : enumValue.ToString(str);
1214 0 : ASCIIToLower(str);
1215 0 : aInfo.mFieldName.Assign(str);
1216 :
1217 : // We are done if this was the only token.
1218 0 : if (numTokens == 1) {
1219 0 : return eAutocompleteAttrState_Valid;
1220 : }
1221 :
1222 0 : --index;
1223 0 : tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1224 :
1225 0 : if (category == eAutocompleteCategory_CONTACT) {
1226 0 : if (!aGrantAllValidValue) {
1227 : unsupported = enumValue.ParseEnumValue(tokenString,
1228 : kAutocompleteUnsupportedContactFieldHintTable,
1229 0 : false);
1230 0 : if (unsupported) {
1231 0 : return eAutocompleteAttrState_Invalid;
1232 : }
1233 : }
1234 :
1235 :
1236 0 : nsAttrValue contactFieldHint;
1237 0 : result = contactFieldHint.ParseEnumValue(tokenString, kAutocompleteContactFieldHintTable, false);
1238 0 : if (result) {
1239 0 : nsAutoString contactFieldHintString;
1240 0 : contactFieldHint.ToString(contactFieldHintString);
1241 0 : ASCIIToLower(contactFieldHintString);
1242 0 : aInfo.mContactType.Assign(contactFieldHintString);
1243 0 : if (index == 0) {
1244 0 : return eAutocompleteAttrState_Valid;
1245 : }
1246 0 : --index;
1247 0 : tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1248 : }
1249 : }
1250 :
1251 : // Check for billing/shipping tokens
1252 0 : nsAttrValue fieldHint;
1253 0 : if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, false)) {
1254 0 : nsString fieldHintString;
1255 0 : fieldHint.ToString(fieldHintString);
1256 0 : ASCIIToLower(fieldHintString);
1257 0 : aInfo.mAddressType.Assign(fieldHintString);
1258 0 : if (index == 0) {
1259 0 : return eAutocompleteAttrState_Valid;
1260 : }
1261 0 : --index;
1262 0 : tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1263 : }
1264 :
1265 : // Check for section-* token
1266 0 : const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1267 0 : if (section.LowerCaseEqualsASCII("section-")) {
1268 0 : ASCIIToLower(tokenString);
1269 0 : aInfo.mSection.Assign(tokenString);
1270 0 : if (index == 0) {
1271 0 : return eAutocompleteAttrState_Valid;
1272 : }
1273 : }
1274 :
1275 : // Clear the fields as the autocomplete attribute is invalid.
1276 0 : aInfo.mSection.Truncate();
1277 0 : aInfo.mAddressType.Truncate();
1278 0 : aInfo.mContactType.Truncate();
1279 0 : aInfo.mFieldName.Truncate();
1280 :
1281 0 : return eAutocompleteAttrState_Invalid;
1282 : }
1283 :
1284 : // Parse an integer according to HTML spec
1285 : int32_t
1286 0 : nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
1287 : ParseHTMLIntegerResultFlags *aResult)
1288 : {
1289 0 : int result = eParseHTMLInteger_NoFlags;
1290 :
1291 0 : nsAString::const_iterator iter, end;
1292 0 : aValue.BeginReading(iter);
1293 0 : aValue.EndReading(end);
1294 :
1295 0 : while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
1296 0 : result |= eParseHTMLInteger_NonStandard;
1297 0 : ++iter;
1298 : }
1299 :
1300 0 : if (iter == end) {
1301 0 : result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1302 0 : *aResult = (ParseHTMLIntegerResultFlags)result;
1303 0 : return 0;
1304 : }
1305 :
1306 0 : int sign = 1;
1307 0 : if (*iter == char16_t('-')) {
1308 0 : sign = -1;
1309 0 : result |= eParseHTMLInteger_Negative;
1310 0 : ++iter;
1311 0 : } else if (*iter == char16_t('+')) {
1312 0 : result |= eParseHTMLInteger_NonStandard;
1313 0 : ++iter;
1314 : }
1315 :
1316 0 : bool foundValue = false;
1317 0 : CheckedInt32 value = 0;
1318 :
1319 : // Check for leading zeros first.
1320 0 : uint64_t leadingZeros = 0;
1321 0 : while (iter != end) {
1322 0 : if (*iter != char16_t('0')) {
1323 0 : break;
1324 : }
1325 :
1326 0 : ++leadingZeros;
1327 0 : foundValue = true;
1328 0 : ++iter;
1329 : }
1330 :
1331 0 : while (iter != end) {
1332 0 : if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
1333 0 : value = (value * 10) + (*iter - char16_t('0')) * sign;
1334 0 : ++iter;
1335 0 : if (!value.isValid()) {
1336 0 : result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1337 0 : break;
1338 : }
1339 0 : foundValue = true;
1340 0 : } else if (*iter == char16_t('%')) {
1341 0 : ++iter;
1342 0 : result |= eParseHTMLInteger_IsPercent;
1343 0 : break;
1344 : } else {
1345 0 : break;
1346 : }
1347 : }
1348 :
1349 0 : if (!foundValue) {
1350 0 : result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1351 : }
1352 :
1353 0 : if (value.isValid() &&
1354 0 : ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1355 0 : (sign == -1 && value == 0))) {
1356 0 : result |= eParseHTMLInteger_NonStandard;
1357 : }
1358 :
1359 0 : if (iter != end) {
1360 0 : result |= eParseHTMLInteger_DidNotConsumeAllInput;
1361 : }
1362 :
1363 0 : *aResult = (ParseHTMLIntegerResultFlags)result;
1364 0 : return value.isValid() ? value.value() : 0;
1365 : }
1366 :
1367 : #define SKIP_WHITESPACE(iter, end_iter, end_res) \
1368 : while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
1369 : ++(iter); \
1370 : } \
1371 : if ((iter) == (end_iter)) { \
1372 : return (end_res); \
1373 : }
1374 :
1375 : #define SKIP_ATTR_NAME(iter, end_iter) \
1376 : while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
1377 : *(iter) != '=') { \
1378 : ++(iter); \
1379 : }
1380 :
1381 : bool
1382 33 : nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
1383 : nsAString& aValue)
1384 : {
1385 33 : aValue.Truncate();
1386 :
1387 33 : const char16_t *start = aSource.get();
1388 33 : const char16_t *end = start + aSource.Length();
1389 : const char16_t *iter;
1390 :
1391 117 : while (start != end) {
1392 81 : SKIP_WHITESPACE(start, end, false)
1393 57 : iter = start;
1394 285 : SKIP_ATTR_NAME(iter, end)
1395 :
1396 57 : if (start == iter) {
1397 0 : return false;
1398 : }
1399 :
1400 : // Remember the attr name.
1401 99 : const nsDependentSubstring & attrName = Substring(start, iter);
1402 :
1403 : // Now check whether this is a valid name="value" pair.
1404 57 : start = iter;
1405 57 : SKIP_WHITESPACE(start, end, false)
1406 57 : if (*start != '=') {
1407 : // No '=', so this is not a name="value" pair. We don't know
1408 : // what it is, and we have no way to handle it.
1409 0 : return false;
1410 : }
1411 :
1412 : // Have to skip the value.
1413 57 : ++start;
1414 57 : SKIP_WHITESPACE(start, end, false)
1415 57 : char16_t q = *start;
1416 57 : if (q != kQuote && q != kApostrophe) {
1417 : // Not a valid quoted value, so bail.
1418 0 : return false;
1419 : }
1420 :
1421 57 : ++start; // Point to the first char of the value.
1422 57 : iter = start;
1423 :
1424 3163 : while (iter != end && *iter != q) {
1425 1553 : ++iter;
1426 : }
1427 :
1428 57 : if (iter == end) {
1429 : // Oops, unterminated quoted string.
1430 0 : return false;
1431 : }
1432 :
1433 : // At this point attrName holds the name of the "attribute" and
1434 : // the value is between start and iter.
1435 :
1436 57 : if (aName->Equals(attrName)) {
1437 : // We'll accumulate as many characters as possible (until we hit either
1438 : // the end of the string or the beginning of an entity). Chunks will be
1439 : // delimited by start and chunkEnd.
1440 15 : const char16_t *chunkEnd = start;
1441 873 : while (chunkEnd != iter) {
1442 429 : if (*chunkEnd == kLessThan) {
1443 0 : aValue.Truncate();
1444 :
1445 0 : return false;
1446 : }
1447 :
1448 429 : if (*chunkEnd == kAmpersand) {
1449 0 : aValue.Append(start, chunkEnd - start);
1450 :
1451 0 : const char16_t *afterEntity = nullptr;
1452 : char16_t result[2];
1453 : uint32_t count =
1454 0 : MOZ_XMLTranslateEntity(reinterpret_cast<const char*>(chunkEnd),
1455 : reinterpret_cast<const char*>(iter),
1456 : reinterpret_cast<const char**>(&afterEntity),
1457 0 : result);
1458 0 : if (count == 0) {
1459 0 : aValue.Truncate();
1460 :
1461 0 : return false;
1462 : }
1463 :
1464 0 : aValue.Append(result, count);
1465 :
1466 : // Advance to after the entity and begin a new chunk.
1467 0 : start = chunkEnd = afterEntity;
1468 : }
1469 : else {
1470 429 : ++chunkEnd;
1471 : }
1472 : }
1473 :
1474 : // Append remainder.
1475 15 : aValue.Append(start, iter - start);
1476 :
1477 15 : return true;
1478 : }
1479 :
1480 : // Resume scanning after the end of the attribute value (past the quote
1481 : // char).
1482 42 : start = iter + 1;
1483 : }
1484 :
1485 18 : return false;
1486 : }
1487 :
1488 : bool
1489 0 : nsContentUtils::IsJavaScriptLanguage(const nsString& aName)
1490 : {
1491 0 : return aName.LowerCaseEqualsLiteral("javascript") ||
1492 0 : aName.LowerCaseEqualsLiteral("livescript") ||
1493 0 : aName.LowerCaseEqualsLiteral("mocha") ||
1494 0 : aName.LowerCaseEqualsLiteral("javascript1.0") ||
1495 0 : aName.LowerCaseEqualsLiteral("javascript1.1") ||
1496 0 : aName.LowerCaseEqualsLiteral("javascript1.2") ||
1497 0 : aName.LowerCaseEqualsLiteral("javascript1.3") ||
1498 0 : aName.LowerCaseEqualsLiteral("javascript1.4") ||
1499 0 : aName.LowerCaseEqualsLiteral("javascript1.5");
1500 : }
1501 :
1502 : JSVersion
1503 0 : nsContentUtils::ParseJavascriptVersion(const nsAString& aVersionStr)
1504 : {
1505 0 : if (aVersionStr.Length() != 3 || aVersionStr[0] != '1' ||
1506 0 : aVersionStr[1] != '.') {
1507 0 : return JSVERSION_UNKNOWN;
1508 : }
1509 :
1510 0 : switch (aVersionStr[2]) {
1511 : case '0': /* fall through */
1512 : case '1': /* fall through */
1513 : case '2': /* fall through */
1514 : case '3': /* fall through */
1515 : case '4': /* fall through */
1516 0 : case '5': return JSVERSION_DEFAULT;
1517 0 : case '6': return JSVERSION_1_6;
1518 0 : case '7': return JSVERSION_1_7;
1519 0 : case '8': return JSVERSION_1_8;
1520 0 : default: return JSVERSION_UNKNOWN;
1521 : }
1522 : }
1523 :
1524 : void
1525 6 : nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
1526 : nsString& aParams)
1527 : {
1528 6 : aType.Truncate();
1529 6 : aParams.Truncate();
1530 6 : int32_t semiIndex = aValue.FindChar(char16_t(';'));
1531 6 : if (-1 != semiIndex) {
1532 0 : aType = Substring(aValue, 0, semiIndex);
1533 0 : aParams = Substring(aValue, semiIndex + 1,
1534 0 : aValue.Length() - (semiIndex + 1));
1535 0 : aParams.StripWhitespace();
1536 : }
1537 : else {
1538 6 : aType = aValue;
1539 : }
1540 6 : aType.StripWhitespace();
1541 6 : }
1542 :
1543 : nsresult
1544 0 : nsContentUtils::IsUserIdle(uint32_t aRequestedIdleTimeInMS, bool* aUserIsIdle)
1545 : {
1546 : nsresult rv;
1547 : nsCOMPtr<nsIIdleService> idleService =
1548 0 : do_GetService("@mozilla.org/widget/idleservice;1", &rv);
1549 0 : NS_ENSURE_SUCCESS(rv, rv);
1550 :
1551 : uint32_t idleTimeInMS;
1552 0 : rv = idleService->GetIdleTime(&idleTimeInMS);
1553 0 : NS_ENSURE_SUCCESS(rv, rv);
1554 :
1555 0 : *aUserIsIdle = idleTimeInMS >= aRequestedIdleTimeInMS;
1556 0 : return NS_OK;
1557 : }
1558 :
1559 : /**
1560 : * Access a cached parser service. Don't addref. We need only one
1561 : * reference to it and this class has that one.
1562 : */
1563 : /* static */
1564 : nsIParserService*
1565 74 : nsContentUtils::GetParserService()
1566 : {
1567 : // XXX: This isn't accessed from several threads, is it?
1568 74 : if (!sParserService) {
1569 : // Lock, recheck sCachedParserService and aquire if this should be
1570 : // safe for multiple threads.
1571 2 : nsresult rv = CallGetService(kParserServiceCID, &sParserService);
1572 2 : if (NS_FAILED(rv)) {
1573 0 : sParserService = nullptr;
1574 : }
1575 : }
1576 :
1577 74 : return sParserService;
1578 : }
1579 :
1580 : /**
1581 : * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
1582 : * directive) and converts it to the set of flags used internally.
1583 : *
1584 : * @param aSandboxAttr the sandbox attribute
1585 : * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
1586 : * null)
1587 : */
1588 : uint32_t
1589 0 : nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr)
1590 : {
1591 0 : if (!aSandboxAttr) {
1592 0 : return SANDBOXED_NONE;
1593 : }
1594 :
1595 0 : uint32_t out = SANDBOX_ALL_FLAGS;
1596 :
1597 : #define SANDBOX_KEYWORD(string, atom, flags) \
1598 : if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
1599 : out &= ~(flags); \
1600 : }
1601 : #include "IframeSandboxKeywordList.h"
1602 : #undef SANDBOX_KEYWORD
1603 :
1604 0 : return out;
1605 : }
1606 :
1607 : /**
1608 : * A helper function that checks if a string matches a valid sandbox flag.
1609 : *
1610 : * @param aFlag the potential sandbox flag.
1611 : * @return true if the flag is a sandbox flag.
1612 : */
1613 : bool
1614 0 : nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag)
1615 : {
1616 : #define SANDBOX_KEYWORD(string, atom, flags) \
1617 : if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
1618 : return true; \
1619 : }
1620 : #include "IframeSandboxKeywordList.h"
1621 : #undef SANDBOX_KEYWORD
1622 0 : return false;
1623 : }
1624 :
1625 : /**
1626 : * A helper function that returns a string attribute corresponding to the
1627 : * sandbox flags.
1628 : *
1629 : * @param aFlags the sandbox flags
1630 : * @param aString the attribute corresponding to the flags (null if aFlags
1631 : * is zero)
1632 : */
1633 : void
1634 0 : nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString)
1635 : {
1636 0 : if (!aFlags) {
1637 0 : SetDOMStringToNull(aString);
1638 0 : return;
1639 : }
1640 :
1641 0 : aString.Truncate();
1642 :
1643 : #define SANDBOX_KEYWORD(string, atom, flags) \
1644 : if (!(aFlags & (flags))) { \
1645 : if (!aString.IsEmpty()) { \
1646 : aString.Append(NS_LITERAL_STRING(" ")); \
1647 : } \
1648 : aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
1649 : }
1650 : #include "IframeSandboxKeywordList.h"
1651 : #undef SANDBOX_KEYWORD
1652 : }
1653 :
1654 : nsIBidiKeyboard*
1655 4 : nsContentUtils::GetBidiKeyboard()
1656 : {
1657 4 : if (!sBidiKeyboard) {
1658 3 : nsresult rv = CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
1659 3 : if (NS_FAILED(rv)) {
1660 0 : sBidiKeyboard = nullptr;
1661 : }
1662 : }
1663 4 : return sBidiKeyboard;
1664 : }
1665 :
1666 : template <class OutputIterator>
1667 : struct NormalizeNewlinesCharTraits {
1668 : public:
1669 : typedef typename OutputIterator::value_type value_type;
1670 :
1671 : public:
1672 0 : explicit NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { }
1673 0 : void writechar(typename OutputIterator::value_type aChar) {
1674 0 : *mIterator++ = aChar;
1675 0 : }
1676 :
1677 : private:
1678 : OutputIterator mIterator;
1679 : };
1680 :
1681 : template <class CharT>
1682 : struct NormalizeNewlinesCharTraits<CharT*> {
1683 : public:
1684 : typedef CharT value_type;
1685 :
1686 : public:
1687 0 : explicit NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { }
1688 0 : void writechar(CharT aChar) {
1689 0 : *mCharPtr++ = aChar;
1690 0 : }
1691 :
1692 : private:
1693 : CharT* mCharPtr;
1694 : };
1695 :
1696 : template <class OutputIterator>
1697 : class CopyNormalizeNewlines
1698 : {
1699 : public:
1700 : typedef typename OutputIterator::value_type value_type;
1701 :
1702 : public:
1703 0 : explicit CopyNormalizeNewlines(OutputIterator* aDestination,
1704 : bool aLastCharCR = false) :
1705 : mLastCharCR(aLastCharCR),
1706 : mDestination(aDestination),
1707 0 : mWritten(0)
1708 0 : { }
1709 :
1710 0 : uint32_t GetCharsWritten() {
1711 0 : return mWritten;
1712 : }
1713 :
1714 0 : bool IsLastCharCR() {
1715 0 : return mLastCharCR;
1716 : }
1717 :
1718 0 : void write(const typename OutputIterator::value_type* aSource, uint32_t aSourceLength) {
1719 :
1720 0 : const typename OutputIterator::value_type* done_writing = aSource + aSourceLength;
1721 :
1722 : // If the last source buffer ended with a CR...
1723 0 : if (mLastCharCR) {
1724 : // ..and if the next one is a LF, then skip it since
1725 : // we've already written out a newline
1726 0 : if (aSourceLength && (*aSource == value_type('\n'))) {
1727 0 : ++aSource;
1728 : }
1729 0 : mLastCharCR = false;
1730 : }
1731 :
1732 0 : uint32_t num_written = 0;
1733 0 : while ( aSource < done_writing ) {
1734 0 : if (*aSource == value_type('\r')) {
1735 0 : mDestination->writechar('\n');
1736 0 : ++aSource;
1737 : // If we've reached the end of the buffer, record
1738 : // that we wrote out a CR
1739 0 : if (aSource == done_writing) {
1740 0 : mLastCharCR = true;
1741 : }
1742 : // If the next character is a LF, skip it
1743 0 : else if (*aSource == value_type('\n')) {
1744 0 : ++aSource;
1745 : }
1746 : }
1747 : else {
1748 0 : mDestination->writechar(*aSource++);
1749 : }
1750 0 : ++num_written;
1751 : }
1752 :
1753 0 : mWritten += num_written;
1754 0 : }
1755 :
1756 : private:
1757 : bool mLastCharCR;
1758 : OutputIterator* mDestination;
1759 : uint32_t mWritten;
1760 : };
1761 :
1762 : // static
1763 : uint32_t
1764 0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString& aSource,
1765 : uint32_t aSrcOffset,
1766 : char16_t* aDest,
1767 : uint32_t aLength,
1768 : bool& aLastCharCR)
1769 : {
1770 : typedef NormalizeNewlinesCharTraits<char16_t*> sink_traits;
1771 :
1772 0 : sink_traits dest_traits(aDest);
1773 0 : CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits,aLastCharCR);
1774 0 : nsReadingIterator<char16_t> fromBegin, fromEnd;
1775 0 : copy_string(aSource.BeginReading(fromBegin).advance( int32_t(aSrcOffset) ),
1776 0 : aSource.BeginReading(fromEnd).advance( int32_t(aSrcOffset+aLength) ),
1777 0 : normalizer);
1778 0 : aLastCharCR = normalizer.IsLastCharCR();
1779 0 : return normalizer.GetCharsWritten();
1780 : }
1781 :
1782 : // static
1783 : uint32_t
1784 0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator<char16_t>& aSrcStart, const nsReadingIterator<char16_t>& aSrcEnd, nsAString& aDest)
1785 : {
1786 : typedef nsWritingIterator<char16_t> WritingIterator;
1787 : typedef NormalizeNewlinesCharTraits<WritingIterator> sink_traits;
1788 :
1789 0 : WritingIterator iter;
1790 0 : aDest.BeginWriting(iter);
1791 0 : sink_traits dest_traits(iter);
1792 0 : CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits);
1793 0 : copy_string(aSrcStart, aSrcEnd, normalizer);
1794 0 : return normalizer.GetCharsWritten();
1795 : }
1796 :
1797 : /**
1798 : * This is used to determine whether a character is in one of the classes
1799 : * which CSS says should be part of the first-letter. Currently, that is
1800 : * all punctuation classes (P*). Note that this is a change from CSS2
1801 : * which excluded Pc and Pd.
1802 : *
1803 : * https://www.w3.org/TR/css-pseudo-4/#first-letter-pseudo
1804 : * "Punctuation (i.e, characters that belong to the Punctuation (P*) Unicode
1805 : * general category [UAX44]) [...]"
1806 : */
1807 :
1808 : // static
1809 : bool
1810 0 : nsContentUtils::IsFirstLetterPunctuation(uint32_t aChar)
1811 : {
1812 0 : switch (mozilla::unicode::GetGeneralCategory(aChar)) {
1813 : case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
1814 : case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */
1815 : case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */
1816 : case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */
1817 : case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
1818 : case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */
1819 : case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */
1820 0 : return true;
1821 : default:
1822 0 : return false;
1823 : }
1824 : }
1825 :
1826 : // static
1827 : bool
1828 0 : nsContentUtils::IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, uint32_t aOffset)
1829 : {
1830 0 : char16_t h = aFrag->CharAt(aOffset);
1831 0 : if (!IS_SURROGATE(h)) {
1832 0 : return IsFirstLetterPunctuation(h);
1833 : }
1834 0 : if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
1835 0 : char16_t l = aFrag->CharAt(aOffset + 1);
1836 0 : if (NS_IS_LOW_SURROGATE(l)) {
1837 0 : return IsFirstLetterPunctuation(SURROGATE_TO_UCS4(h, l));
1838 : }
1839 : }
1840 0 : return false;
1841 : }
1842 :
1843 : // static
1844 0 : bool nsContentUtils::IsAlphanumeric(uint32_t aChar)
1845 : {
1846 0 : nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
1847 :
1848 0 : return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
1849 : }
1850 :
1851 : // static
1852 0 : bool nsContentUtils::IsAlphanumericAt(const nsTextFragment* aFrag, uint32_t aOffset)
1853 : {
1854 0 : char16_t h = aFrag->CharAt(aOffset);
1855 0 : if (!IS_SURROGATE(h)) {
1856 0 : return IsAlphanumeric(h);
1857 : }
1858 0 : if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
1859 0 : char16_t l = aFrag->CharAt(aOffset + 1);
1860 0 : if (NS_IS_LOW_SURROGATE(l)) {
1861 0 : return IsAlphanumeric(SURROGATE_TO_UCS4(h, l));
1862 : }
1863 : }
1864 0 : return false;
1865 : }
1866 :
1867 : /* static */
1868 : bool
1869 18101 : nsContentUtils::IsHTMLWhitespace(char16_t aChar)
1870 : {
1871 18101 : return aChar == char16_t(0x0009) ||
1872 18101 : aChar == char16_t(0x000A) ||
1873 18101 : aChar == char16_t(0x000C) ||
1874 36202 : aChar == char16_t(0x000D) ||
1875 18101 : aChar == char16_t(0x0020);
1876 : }
1877 :
1878 : /* static */
1879 : bool
1880 0 : nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar)
1881 : {
1882 0 : return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
1883 : }
1884 :
1885 : /* static */
1886 : bool
1887 0 : nsContentUtils::IsHTMLBlock(nsIContent* aContent)
1888 : {
1889 0 : return aContent->IsAnyOfHTMLElements(nsGkAtoms::address,
1890 : nsGkAtoms::article,
1891 : nsGkAtoms::aside,
1892 : nsGkAtoms::blockquote,
1893 : nsGkAtoms::center,
1894 : nsGkAtoms::dir,
1895 : nsGkAtoms::div,
1896 : nsGkAtoms::dl, // XXX why not dt and dd?
1897 : nsGkAtoms::fieldset,
1898 : nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
1899 : nsGkAtoms::footer,
1900 : nsGkAtoms::form,
1901 : nsGkAtoms::h1,
1902 : nsGkAtoms::h2,
1903 : nsGkAtoms::h3,
1904 : nsGkAtoms::h4,
1905 : nsGkAtoms::h5,
1906 : nsGkAtoms::h6,
1907 : nsGkAtoms::header,
1908 : nsGkAtoms::hgroup,
1909 : nsGkAtoms::hr,
1910 : nsGkAtoms::li,
1911 : nsGkAtoms::listing,
1912 : nsGkAtoms::menu,
1913 : nsGkAtoms::multicol, // XXX get rid of this one?
1914 : nsGkAtoms::nav,
1915 : nsGkAtoms::ol,
1916 : nsGkAtoms::p,
1917 : nsGkAtoms::pre,
1918 : nsGkAtoms::section,
1919 : nsGkAtoms::table,
1920 : nsGkAtoms::ul,
1921 0 : nsGkAtoms::xmp);
1922 : }
1923 :
1924 : /* static */
1925 : bool
1926 2 : nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result)
1927 : {
1928 4 : nsAutoString marginStr(aString);
1929 2 : marginStr.CompressWhitespace(true, true);
1930 2 : if (marginStr.IsEmpty()) {
1931 2 : return false;
1932 : }
1933 :
1934 0 : int32_t start = 0, end = 0;
1935 0 : for (int count = 0; count < 4; count++) {
1936 0 : if ((uint32_t)end >= marginStr.Length())
1937 0 : return false;
1938 :
1939 : // top, right, bottom, left
1940 0 : if (count < 3)
1941 0 : end = Substring(marginStr, start).FindChar(',');
1942 : else
1943 0 : end = Substring(marginStr, start).Length();
1944 :
1945 0 : if (end <= 0)
1946 0 : return false;
1947 :
1948 : nsresult ec;
1949 0 : int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec);
1950 0 : if (NS_FAILED(ec))
1951 0 : return false;
1952 :
1953 0 : switch(count) {
1954 : case 0:
1955 0 : result.top = val;
1956 0 : break;
1957 : case 1:
1958 0 : result.right = val;
1959 0 : break;
1960 : case 2:
1961 0 : result.bottom = val;
1962 0 : break;
1963 : case 3:
1964 0 : result.left = val;
1965 0 : break;
1966 : }
1967 0 : start += end + 1;
1968 : }
1969 0 : return true;
1970 : }
1971 :
1972 : // static
1973 : int32_t
1974 0 : nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
1975 : {
1976 0 : nsAString::const_iterator iter, end;
1977 0 : aValue.BeginReading(iter);
1978 0 : aValue.EndReading(end);
1979 :
1980 0 : while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
1981 0 : ++iter;
1982 : }
1983 :
1984 0 : if (iter == end) {
1985 0 : return 0;
1986 : }
1987 :
1988 0 : bool relative = false;
1989 0 : bool negate = false;
1990 0 : if (*iter == char16_t('-')) {
1991 0 : relative = true;
1992 0 : negate = true;
1993 0 : ++iter;
1994 0 : } else if (*iter == char16_t('+')) {
1995 0 : relative = true;
1996 0 : ++iter;
1997 : }
1998 :
1999 0 : if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
2000 0 : return 0;
2001 : }
2002 :
2003 : // We don't have to worry about overflow, since we can bail out as soon as
2004 : // we're bigger than 7.
2005 0 : int32_t value = 0;
2006 0 : while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
2007 0 : value = 10*value + (*iter - char16_t('0'));
2008 0 : if (value >= 7) {
2009 0 : break;
2010 : }
2011 0 : ++iter;
2012 : }
2013 :
2014 0 : if (relative) {
2015 0 : if (negate) {
2016 0 : value = 3 - value;
2017 : } else {
2018 0 : value = 3 + value;
2019 : }
2020 : }
2021 :
2022 0 : return clamped(value, 1, 7);
2023 : }
2024 :
2025 : /* static */
2026 : bool
2027 3 : nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument)
2028 : {
2029 3 : if (nsContentUtils::IsInPrivateBrowsing(aDocument)) {
2030 0 : return false;
2031 : }
2032 :
2033 : RefPtr<workers::ServiceWorkerManager> swm =
2034 6 : workers::ServiceWorkerManager::GetInstance();
2035 3 : MOZ_ASSERT(swm);
2036 :
2037 6 : ErrorResult rv;
2038 3 : bool controlled = swm->IsControlled(aDocument, rv);
2039 3 : if (NS_WARN_IF(rv.Failed())) {
2040 0 : rv.SuppressException();
2041 0 : return false;
2042 : }
2043 :
2044 3 : return controlled;
2045 : }
2046 :
2047 : /* static */
2048 : void
2049 0 : nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
2050 : {
2051 0 : MOZ_ASSERT(NS_IsMainThread());
2052 0 : MOZ_ASSERT(aDocument);
2053 0 : *aURI = nullptr;
2054 :
2055 0 : if (IsControlledByServiceWorker(aDocument)) {
2056 0 : return;
2057 : }
2058 :
2059 0 : Element* docElement = aDocument->GetRootElement();
2060 0 : if (!docElement) {
2061 0 : return;
2062 : }
2063 :
2064 0 : nsAutoString manifestSpec;
2065 0 : docElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
2066 :
2067 : // Manifest URIs can't have fragment identifiers.
2068 0 : if (manifestSpec.IsEmpty() ||
2069 0 : manifestSpec.Contains('#')) {
2070 0 : return;
2071 : }
2072 :
2073 0 : nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
2074 : aDocument,
2075 0 : aDocument->GetDocBaseURI());
2076 : }
2077 :
2078 : /* static */
2079 : bool
2080 0 : nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
2081 : {
2082 : nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
2083 0 : do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
2084 0 : if (!updateService) {
2085 0 : return false;
2086 : }
2087 :
2088 : bool allowed;
2089 : nsresult rv =
2090 0 : updateService->OfflineAppAllowedForURI(aURI,
2091 : Preferences::GetRootBranch(),
2092 0 : &allowed);
2093 0 : return NS_SUCCEEDED(rv) && allowed;
2094 : }
2095 :
2096 : /* static */
2097 : bool
2098 0 : nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
2099 : {
2100 : nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
2101 0 : do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
2102 0 : if (!updateService) {
2103 0 : return false;
2104 : }
2105 :
2106 : bool allowed;
2107 0 : nsresult rv = updateService->OfflineAppAllowed(aPrincipal,
2108 : Preferences::GetRootBranch(),
2109 0 : &allowed);
2110 0 : return NS_SUCCEEDED(rv) && allowed;
2111 : }
2112 :
2113 : bool
2114 0 : nsContentUtils::MaybeAllowOfflineAppByDefault(nsIPrincipal *aPrincipal)
2115 : {
2116 0 : if (!Preferences::GetRootBranch())
2117 0 : return false;
2118 :
2119 : nsresult rv;
2120 :
2121 : bool allowedByDefault;
2122 0 : rv = Preferences::GetRootBranch()->GetBoolPref(
2123 0 : "offline-apps.allow_by_default", &allowedByDefault);
2124 0 : if (NS_FAILED(rv))
2125 0 : return false;
2126 :
2127 0 : if (!allowedByDefault)
2128 0 : return false;
2129 :
2130 : nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
2131 0 : do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
2132 0 : if (!updateService) {
2133 0 : return false;
2134 : }
2135 :
2136 0 : rv = updateService->AllowOfflineApp(aPrincipal);
2137 0 : return NS_SUCCEEDED(rv);
2138 : }
2139 :
2140 : // static
2141 : void
2142 0 : nsContentUtils::Shutdown()
2143 : {
2144 0 : sInitialized = false;
2145 :
2146 0 : NS_IF_RELEASE(sContentPolicyService);
2147 0 : sTriedToGetContentPolicy = false;
2148 : uint32_t i;
2149 0 : for (i = 0; i < PropertiesFile_COUNT; ++i)
2150 0 : NS_IF_RELEASE(sStringBundles[i]);
2151 :
2152 0 : NS_IF_RELEASE(sStringBundleService);
2153 0 : NS_IF_RELEASE(sConsoleService);
2154 0 : sXPConnect = nullptr;
2155 0 : NS_IF_RELEASE(sSecurityManager);
2156 0 : NS_IF_RELEASE(sSystemPrincipal);
2157 0 : NS_IF_RELEASE(sNullSubjectPrincipal);
2158 0 : NS_IF_RELEASE(sParserService);
2159 0 : NS_IF_RELEASE(sIOService);
2160 0 : NS_IF_RELEASE(sUUIDGenerator);
2161 0 : NS_IF_RELEASE(sLineBreaker);
2162 0 : NS_IF_RELEASE(sWordBreaker);
2163 0 : NS_IF_RELEASE(sBidiKeyboard);
2164 :
2165 0 : delete sAtomEventTable;
2166 0 : sAtomEventTable = nullptr;
2167 0 : delete sStringEventTable;
2168 0 : sStringEventTable = nullptr;
2169 0 : delete sUserDefinedEvents;
2170 0 : sUserDefinedEvents = nullptr;
2171 :
2172 0 : if (sEventListenerManagersHash) {
2173 0 : NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0,
2174 : "Event listener manager hash not empty at shutdown!");
2175 :
2176 : // See comment above.
2177 :
2178 : // However, we have to handle this table differently. If it still
2179 : // has entries, we want to leak it too, so that we can keep it alive
2180 : // in case any elements are destroyed. Because if they are, we need
2181 : // their event listener managers to be destroyed too, or otherwise
2182 : // it could leave dangling references in DOMClassInfo's preserved
2183 : // wrapper table.
2184 :
2185 0 : if (sEventListenerManagersHash->EntryCount() == 0) {
2186 0 : delete sEventListenerManagersHash;
2187 0 : sEventListenerManagersHash = nullptr;
2188 : }
2189 : }
2190 :
2191 0 : NS_ASSERTION(!sBlockedScriptRunners ||
2192 : sBlockedScriptRunners->Length() == 0,
2193 : "How'd this happen?");
2194 0 : delete sBlockedScriptRunners;
2195 0 : sBlockedScriptRunners = nullptr;
2196 :
2197 0 : delete sShiftText;
2198 0 : sShiftText = nullptr;
2199 0 : delete sControlText;
2200 0 : sControlText = nullptr;
2201 0 : delete sMetaText;
2202 0 : sMetaText = nullptr;
2203 0 : delete sOSText;
2204 0 : sOSText = nullptr;
2205 0 : delete sAltText;
2206 0 : sAltText = nullptr;
2207 0 : delete sModifierSeparator;
2208 0 : sModifierSeparator = nullptr;
2209 :
2210 0 : delete sJSBytecodeMimeType;
2211 0 : sJSBytecodeMimeType = nullptr;
2212 :
2213 0 : NS_IF_RELEASE(sSameOriginChecker);
2214 :
2215 0 : NS_IF_RELEASE(sStableStateEventTarget);
2216 :
2217 0 : if (sUserInteractionObserver) {
2218 0 : sUserInteractionObserver->Shutdown();
2219 0 : NS_RELEASE(sUserInteractionObserver);
2220 : }
2221 :
2222 0 : HTMLInputElement::Shutdown();
2223 0 : nsMappedAttributes::Shutdown();
2224 0 : }
2225 :
2226 : /**
2227 : * Checks whether two nodes come from the same origin. aTrustedNode is
2228 : * considered 'safe' in that a user can operate on it and that it isn't
2229 : * a js-object that implements nsIDOMNode.
2230 : * Never call this function with the first node provided by script, it
2231 : * must always be known to be a 'real' node!
2232 : */
2233 : // static
2234 : nsresult
2235 4 : nsContentUtils::CheckSameOrigin(const nsINode *aTrustedNode,
2236 : nsIDOMNode *aUnTrustedNode)
2237 : {
2238 4 : MOZ_ASSERT(aTrustedNode);
2239 :
2240 : // Make sure it's a real node.
2241 8 : nsCOMPtr<nsINode> unTrustedNode = do_QueryInterface(aUnTrustedNode);
2242 4 : NS_ENSURE_TRUE(unTrustedNode, NS_ERROR_UNEXPECTED);
2243 4 : return CheckSameOrigin(aTrustedNode, unTrustedNode);
2244 : }
2245 :
2246 : nsresult
2247 288 : nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2248 : const nsINode* unTrustedNode)
2249 : {
2250 288 : MOZ_ASSERT(aTrustedNode);
2251 288 : MOZ_ASSERT(unTrustedNode);
2252 :
2253 : /*
2254 : * Get hold of each node's principal
2255 : */
2256 :
2257 288 : nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2258 288 : nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2259 :
2260 288 : if (trustedPrincipal == unTrustedPrincipal) {
2261 288 : return NS_OK;
2262 : }
2263 :
2264 : bool equal;
2265 : // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2266 : // a separate method for that, with callers using one or the other?
2267 0 : if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal)) ||
2268 0 : !equal) {
2269 0 : return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2270 : }
2271 :
2272 0 : return NS_OK;
2273 : }
2274 :
2275 : // static
2276 : bool
2277 4 : nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2278 : nsIPrincipal* aPrincipal)
2279 : {
2280 : bool subsumes;
2281 4 : nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2282 4 : NS_ENSURE_SUCCESS(rv, false);
2283 :
2284 4 : if (subsumes) {
2285 4 : return true;
2286 : }
2287 :
2288 : // The subject doesn't subsume aPrincipal. Allow access only if the subject
2289 : // is chrome.
2290 0 : return IsCallerChrome();
2291 : }
2292 :
2293 : // static
2294 : bool
2295 0 : nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
2296 : {
2297 0 : nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
2298 0 : NS_ENSURE_TRUE(node, false);
2299 0 : return CanCallerAccess(node);
2300 : }
2301 :
2302 : // static
2303 : bool
2304 4 : nsContentUtils::CanCallerAccess(nsINode* aNode)
2305 : {
2306 4 : return CanCallerAccess(SubjectPrincipal(), aNode->NodePrincipal());
2307 : }
2308 :
2309 : // static
2310 : bool
2311 0 : nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow)
2312 : {
2313 0 : nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2314 0 : NS_ENSURE_TRUE(scriptObject, false);
2315 :
2316 0 : return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2317 : }
2318 :
2319 : // static
2320 : bool
2321 0 : nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm)
2322 : {
2323 : // Chrome gets access by default.
2324 0 : if (IsSystemPrincipal(aPrincipal)) {
2325 0 : return true;
2326 : }
2327 :
2328 : // Otherwise, only allow if caller is an addon with the permission.
2329 0 : return BasePrincipal::Cast(aPrincipal)->AddonHasPermission(aPerm);
2330 : }
2331 :
2332 : // static
2333 : bool
2334 0 : nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
2335 : {
2336 0 : return PrincipalHasPermission(SubjectPrincipal(aCx), aPerm);
2337 : }
2338 :
2339 : //static
2340 : bool
2341 9 : nsContentUtils::InProlog(nsINode *aNode)
2342 : {
2343 9 : NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
2344 :
2345 9 : nsINode* parent = aNode->GetParentNode();
2346 9 : if (!parent || !parent->IsNodeOfType(nsINode::eDOCUMENT)) {
2347 0 : return false;
2348 : }
2349 :
2350 9 : nsIDocument* doc = static_cast<nsIDocument*>(parent);
2351 9 : nsIContent* root = doc->GetRootElement();
2352 :
2353 9 : return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
2354 : }
2355 :
2356 : nsIDocument*
2357 0 : nsContentUtils::GetDocumentFromCaller()
2358 : {
2359 0 : AutoJSContext cx;
2360 :
2361 : nsCOMPtr<nsPIDOMWindowInner> win =
2362 0 : do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(cx)));
2363 0 : if (!win) {
2364 0 : return nullptr;
2365 : }
2366 :
2367 0 : return win->GetExtantDoc();
2368 : }
2369 :
2370 : bool
2371 9253 : nsContentUtils::IsCallerChrome()
2372 : {
2373 9253 : MOZ_ASSERT(NS_IsMainThread());
2374 9253 : if (SubjectPrincipal() == sSystemPrincipal) {
2375 9196 : return true;
2376 : }
2377 :
2378 : // If the check failed, look for UniversalXPConnect on the cx compartment.
2379 57 : return xpc::IsUniversalXPConnectEnabled(GetCurrentJSContext());
2380 : }
2381 :
2382 : /* static */
2383 : bool
2384 34 : nsContentUtils::ShouldResistFingerprinting()
2385 : {
2386 34 : if (NS_IsMainThread()) {
2387 34 : return nsRFPService::IsResistFingerprintingEnabled();
2388 : }
2389 :
2390 0 : workers::WorkerPrivate* workerPrivate = workers::GetCurrentThreadWorkerPrivate();
2391 0 : if (NS_WARN_IF(!workerPrivate)) {
2392 0 : return false;
2393 : }
2394 0 : workerPrivate->AssertIsOnWorkerThread();
2395 :
2396 0 : return workerPrivate->ResistFingerprintingEnabled();
2397 : }
2398 :
2399 : bool
2400 152 : nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell)
2401 : {
2402 152 : if (!aDocShell) {
2403 8 : return false;
2404 : }
2405 144 : bool isChrome = nsContentUtils::IsChromeDoc(aDocShell->GetDocument());
2406 144 : return !isChrome && ShouldResistFingerprinting();
2407 : }
2408 :
2409 : /* static */
2410 : void
2411 0 : nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(int32_t aChromeWidth,
2412 : int32_t aChromeHeight,
2413 : int32_t aScreenWidth,
2414 : int32_t aScreenHeight,
2415 : int32_t aInputWidth,
2416 : int32_t aInputHeight,
2417 : bool aSetOuterWidth,
2418 : bool aSetOuterHeight,
2419 : int32_t* aOutputWidth,
2420 : int32_t* aOutputHeight)
2421 : {
2422 0 : MOZ_ASSERT(aOutputWidth);
2423 0 : MOZ_ASSERT(aOutputHeight);
2424 :
2425 0 : int32_t availContentWidth = 0;
2426 0 : int32_t availContentHeight = 0;
2427 :
2428 0 : availContentWidth = std::min(sPrivacyMaxInnerWidth,
2429 0 : aScreenWidth - aChromeWidth);
2430 : #ifdef MOZ_WIDGET_GTK
2431 : // In the GTK window, it will not report outside system decorations
2432 : // when we get available window size, see Bug 581863. So, we leave a
2433 : // 40 pixels space for them when calculating the available content
2434 : // height. It is not necessary for the width since the content width
2435 : // is usually pretty much the same as the chrome width.
2436 0 : availContentHeight = std::min(sPrivacyMaxInnerHeight,
2437 0 : (-40 + aScreenHeight) - aChromeHeight);
2438 : #else
2439 : availContentHeight = std::min(sPrivacyMaxInnerHeight,
2440 : aScreenHeight - aChromeHeight);
2441 : #endif
2442 :
2443 : // Ideally, we'd like to round window size to 1000x1000, but the
2444 : // screen space could be too small to accommodate this size in some
2445 : // cases. If it happens, we would round the window size to the nearest
2446 : // 200x100.
2447 0 : availContentWidth = availContentWidth - (availContentWidth % 200);
2448 0 : availContentHeight = availContentHeight - (availContentHeight % 100);
2449 :
2450 : // If aIsOuter is true, we are setting the outer window. So we
2451 : // have to consider the chrome UI.
2452 0 : int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
2453 0 : int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
2454 0 : int32_t resultWidth = 0, resultHeight = 0;
2455 :
2456 : // if the original size is greater than the maximum available size, we set
2457 : // it to the maximum size. And if the original value is less than the
2458 : // minimum rounded size, we set it to the minimum 200x100.
2459 0 : if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
2460 0 : resultWidth = availContentWidth + chromeOffsetWidth;
2461 0 : } else if (aInputWidth < (200 + chromeOffsetWidth)) {
2462 0 : resultWidth = 200 + chromeOffsetWidth;
2463 : } else {
2464 : // Otherwise, we round the window to the nearest upper rounded 200x100.
2465 0 : resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 + chromeOffsetWidth;
2466 : }
2467 :
2468 0 : if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
2469 0 : resultHeight = availContentHeight + chromeOffsetHeight;
2470 0 : } else if (aInputHeight < (100 + chromeOffsetHeight)) {
2471 0 : resultHeight = 100 + chromeOffsetHeight;
2472 : } else {
2473 0 : resultHeight = NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 + chromeOffsetHeight;
2474 : }
2475 :
2476 0 : *aOutputWidth = resultWidth;
2477 0 : *aOutputHeight = resultHeight;
2478 0 : }
2479 :
2480 : bool
2481 0 : nsContentUtils::ThreadsafeIsCallerChrome()
2482 : {
2483 0 : return NS_IsMainThread() ?
2484 : IsCallerChrome() :
2485 0 : mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
2486 : }
2487 :
2488 : bool
2489 0 : nsContentUtils::IsCallerContentXBL()
2490 : {
2491 0 : JSContext *cx = GetCurrentJSContext();
2492 0 : if (!cx)
2493 0 : return false;
2494 :
2495 0 : JSCompartment *c = js::GetContextCompartment(cx);
2496 :
2497 : // For remote XUL, we run XBL in the XUL scope. Given that we care about
2498 : // compat and not security for remote XUL, just always claim to be XBL.
2499 0 : if (!xpc::AllowContentXBLScope(c)) {
2500 0 : MOZ_ASSERT(nsContentUtils::AllowXULXBLForPrincipal(xpc::GetCompartmentPrincipal(c)));
2501 0 : return true;
2502 : }
2503 :
2504 0 : return xpc::IsContentXBLScope(c);
2505 : }
2506 :
2507 : bool
2508 1439 : nsContentUtils::IsSystemCaller(JSContext* aCx)
2509 : {
2510 : // Note that SubjectPrincipal() assumes we are in a compartment here.
2511 1439 : return SubjectPrincipal(aCx) == sSystemPrincipal;
2512 : }
2513 :
2514 : bool
2515 199 : nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx)
2516 : {
2517 199 : if (NS_IsMainThread()) {
2518 183 : return IsSystemCaller(aCx);
2519 : }
2520 :
2521 16 : return workers::GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal();
2522 : }
2523 :
2524 : // static
2525 : bool
2526 0 : nsContentUtils::LookupBindingMember(JSContext* aCx, nsIContent *aContent,
2527 : JS::Handle<jsid> aId,
2528 : JS::MutableHandle<JS::PropertyDescriptor> aDesc)
2529 : {
2530 0 : nsXBLBinding* binding = aContent->GetXBLBinding();
2531 0 : if (!binding)
2532 0 : return true;
2533 0 : return binding->LookupMember(aCx, aId, aDesc);
2534 : }
2535 :
2536 : // static
2537 : nsINode*
2538 0 : nsContentUtils::GetCrossDocParentNode(nsINode* aChild)
2539 : {
2540 0 : NS_PRECONDITION(aChild, "The child is null!");
2541 :
2542 0 : nsINode* parent = aChild->GetParentNode();
2543 0 : if (parent && parent->IsContent() && aChild->IsContent()) {
2544 0 : parent = aChild->AsContent()->GetFlattenedTreeParent();
2545 : }
2546 :
2547 0 : if (parent || !aChild->IsNodeOfType(nsINode::eDOCUMENT))
2548 0 : return parent;
2549 :
2550 0 : nsIDocument* doc = static_cast<nsIDocument*>(aChild);
2551 0 : nsIDocument* parentDoc = doc->GetParentDocument();
2552 0 : return parentDoc ? parentDoc->FindContentForSubDocument(doc) : nullptr;
2553 : }
2554 :
2555 : // static
2556 : bool
2557 73 : nsContentUtils::ContentIsDescendantOf(const nsINode* aPossibleDescendant,
2558 : const nsINode* aPossibleAncestor)
2559 : {
2560 73 : NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
2561 73 : NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
2562 :
2563 253 : do {
2564 326 : if (aPossibleDescendant == aPossibleAncestor)
2565 42 : return true;
2566 284 : aPossibleDescendant = aPossibleDescendant->GetParentNode();
2567 284 : } while (aPossibleDescendant);
2568 :
2569 31 : return false;
2570 : }
2571 :
2572 : bool
2573 9 : nsContentUtils::ContentIsHostIncludingDescendantOf(
2574 : const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor)
2575 : {
2576 9 : NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
2577 9 : NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
2578 :
2579 39 : do {
2580 48 : if (aPossibleDescendant == aPossibleAncestor)
2581 0 : return true;
2582 48 : if (aPossibleDescendant->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
2583 : aPossibleDescendant =
2584 0 : static_cast<const DocumentFragment*>(aPossibleDescendant)->GetHost();
2585 : } else {
2586 48 : aPossibleDescendant = aPossibleDescendant->GetParentNode();
2587 : }
2588 48 : } while (aPossibleDescendant);
2589 :
2590 9 : return false;
2591 : }
2592 :
2593 : // static
2594 : bool
2595 0 : nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
2596 : nsINode* aPossibleAncestor)
2597 : {
2598 0 : NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
2599 0 : NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
2600 :
2601 0 : do {
2602 0 : if (aPossibleDescendant == aPossibleAncestor)
2603 0 : return true;
2604 :
2605 0 : aPossibleDescendant = GetCrossDocParentNode(aPossibleDescendant);
2606 0 : } while (aPossibleDescendant);
2607 :
2608 0 : return false;
2609 : }
2610 :
2611 : // static
2612 : bool
2613 0 : nsContentUtils::ContentIsFlattenedTreeDescendantOf(
2614 : const nsINode* aPossibleDescendant,
2615 : const nsINode* aPossibleAncestor)
2616 : {
2617 0 : NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
2618 0 : NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
2619 :
2620 0 : do {
2621 0 : if (aPossibleDescendant == aPossibleAncestor) {
2622 0 : return true;
2623 : }
2624 0 : aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
2625 0 : } while (aPossibleDescendant);
2626 :
2627 0 : return false;
2628 : }
2629 :
2630 : // static
2631 : nsresult
2632 0 : nsContentUtils::GetAncestors(nsINode* aNode,
2633 : nsTArray<nsINode*>& aArray)
2634 : {
2635 0 : while (aNode) {
2636 0 : aArray.AppendElement(aNode);
2637 0 : aNode = aNode->GetParentNode();
2638 : }
2639 0 : return NS_OK;
2640 : }
2641 :
2642 : // static
2643 : nsresult
2644 0 : nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode* aNode,
2645 : int32_t aOffset,
2646 : nsTArray<nsIContent*>* aAncestorNodes,
2647 : nsTArray<int32_t>* aAncestorOffsets)
2648 : {
2649 0 : NS_ENSURE_ARG_POINTER(aNode);
2650 :
2651 0 : nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
2652 :
2653 0 : if (!content) {
2654 0 : return NS_ERROR_FAILURE;
2655 : }
2656 :
2657 0 : if (!aAncestorNodes->IsEmpty()) {
2658 0 : NS_WARNING("aAncestorNodes is not empty");
2659 0 : aAncestorNodes->Clear();
2660 : }
2661 :
2662 0 : if (!aAncestorOffsets->IsEmpty()) {
2663 0 : NS_WARNING("aAncestorOffsets is not empty");
2664 0 : aAncestorOffsets->Clear();
2665 : }
2666 :
2667 : // insert the node itself
2668 0 : aAncestorNodes->AppendElement(content.get());
2669 0 : aAncestorOffsets->AppendElement(aOffset);
2670 :
2671 : // insert all the ancestors
2672 0 : nsIContent* child = content;
2673 0 : nsIContent* parent = child->GetParent();
2674 0 : while (parent) {
2675 0 : aAncestorNodes->AppendElement(parent);
2676 0 : aAncestorOffsets->AppendElement(parent->IndexOf(child));
2677 0 : child = parent;
2678 0 : parent = parent->GetParent();
2679 : }
2680 :
2681 0 : return NS_OK;
2682 : }
2683 :
2684 : // static
2685 : nsresult
2686 0 : nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
2687 : nsIDOMNode *aOther,
2688 : nsIDOMNode** aCommonAncestor)
2689 : {
2690 0 : *aCommonAncestor = nullptr;
2691 :
2692 0 : nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode);
2693 0 : nsCOMPtr<nsINode> node2 = do_QueryInterface(aOther);
2694 :
2695 0 : NS_ENSURE_TRUE(node1 && node2, NS_ERROR_UNEXPECTED);
2696 :
2697 0 : nsINode* common = GetCommonAncestor(node1, node2);
2698 0 : NS_ENSURE_TRUE(common, NS_ERROR_NOT_AVAILABLE);
2699 :
2700 0 : return CallQueryInterface(common, aCommonAncestor);
2701 : }
2702 :
2703 : template <typename Node, typename GetParentFunc>
2704 : static Node*
2705 30 : GetCommonAncestorInternal(Node* aNode1,
2706 : Node* aNode2,
2707 : GetParentFunc aGetParentFunc)
2708 : {
2709 30 : if (aNode1 == aNode2) {
2710 30 : return aNode1;
2711 : }
2712 :
2713 : // Build the chain of parents
2714 0 : AutoTArray<Node*, 30> parents1, parents2;
2715 0 : do {
2716 0 : parents1.AppendElement(aNode1);
2717 0 : aNode1 = aGetParentFunc(aNode1);
2718 : } while (aNode1);
2719 0 : do {
2720 0 : parents2.AppendElement(aNode2);
2721 0 : aNode2 = aGetParentFunc(aNode2);
2722 : } while (aNode2);
2723 :
2724 : // Find where the parent chain differs
2725 0 : uint32_t pos1 = parents1.Length();
2726 0 : uint32_t pos2 = parents2.Length();
2727 0 : Node* parent = nullptr;
2728 : uint32_t len;
2729 0 : for (len = std::min(pos1, pos2); len > 0; --len) {
2730 0 : Node* child1 = parents1.ElementAt(--pos1);
2731 0 : Node* child2 = parents2.ElementAt(--pos2);
2732 0 : if (child1 != child2) {
2733 0 : break;
2734 : }
2735 0 : parent = child1;
2736 : }
2737 :
2738 0 : return parent;
2739 : }
2740 :
2741 : /* static */
2742 : nsINode*
2743 30 : nsContentUtils::GetCommonAncestor(nsINode* aNode1, nsINode* aNode2)
2744 : {
2745 30 : return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
2746 : return aNode->GetParentNode();
2747 60 : });
2748 : }
2749 :
2750 : /* static */
2751 : nsIContent*
2752 0 : nsContentUtils::GetCommonFlattenedTreeAncestor(nsIContent* aContent1,
2753 : nsIContent* aContent2)
2754 : {
2755 0 : return GetCommonAncestorInternal(aContent1, aContent2, [](nsIContent* aContent) {
2756 : return aContent->GetFlattenedTreeParent();
2757 0 : });
2758 : }
2759 :
2760 : /* static */
2761 : bool
2762 8 : nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2)
2763 : {
2764 8 : return (aNode2->CompareDocumentPosition(*aNode1) &
2765 : (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
2766 : nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED)) ==
2767 8 : nsIDOMNode::DOCUMENT_POSITION_PRECEDING;
2768 : }
2769 :
2770 : /* static */
2771 : int32_t
2772 14 : nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
2773 : nsINode* aParent2, int32_t aOffset2,
2774 : bool* aDisconnected)
2775 : {
2776 14 : if (aParent1 == aParent2) {
2777 22 : return aOffset1 < aOffset2 ? -1 :
2778 8 : aOffset1 > aOffset2 ? 1 :
2779 14 : 0;
2780 : }
2781 :
2782 0 : AutoTArray<nsINode*, 32> parents1, parents2;
2783 0 : nsINode* node1 = aParent1;
2784 0 : nsINode* node2 = aParent2;
2785 0 : do {
2786 0 : parents1.AppendElement(node1);
2787 0 : node1 = node1->GetParentNode();
2788 0 : } while (node1);
2789 0 : do {
2790 0 : parents2.AppendElement(node2);
2791 0 : node2 = node2->GetParentNode();
2792 0 : } while (node2);
2793 :
2794 0 : uint32_t pos1 = parents1.Length() - 1;
2795 0 : uint32_t pos2 = parents2.Length() - 1;
2796 :
2797 0 : bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
2798 0 : if (aDisconnected) {
2799 0 : *aDisconnected = disconnected;
2800 : }
2801 0 : if (disconnected) {
2802 0 : NS_ASSERTION(aDisconnected, "unexpected disconnected nodes");
2803 0 : return 1;
2804 : }
2805 :
2806 : // Find where the parent chains differ
2807 0 : nsINode* parent = parents1.ElementAt(pos1);
2808 : uint32_t len;
2809 0 : for (len = std::min(pos1, pos2); len > 0; --len) {
2810 0 : nsINode* child1 = parents1.ElementAt(--pos1);
2811 0 : nsINode* child2 = parents2.ElementAt(--pos2);
2812 0 : if (child1 != child2) {
2813 0 : return parent->IndexOf(child1) < parent->IndexOf(child2) ? -1 : 1;
2814 : }
2815 0 : parent = child1;
2816 : }
2817 :
2818 :
2819 : // The parent chains never differed, so one of the nodes is an ancestor of
2820 : // the other
2821 :
2822 0 : NS_ASSERTION(!pos1 || !pos2,
2823 : "should have run out of parent chain for one of the nodes");
2824 :
2825 0 : if (!pos1) {
2826 0 : nsINode* child2 = parents2.ElementAt(--pos2);
2827 0 : return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
2828 : }
2829 :
2830 0 : nsINode* child1 = parents1.ElementAt(--pos1);
2831 0 : return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
2832 : }
2833 :
2834 : /* static */
2835 : int32_t
2836 0 : nsContentUtils::ComparePoints(nsIDOMNode* aParent1, int32_t aOffset1,
2837 : nsIDOMNode* aParent2, int32_t aOffset2,
2838 : bool* aDisconnected)
2839 : {
2840 0 : nsCOMPtr<nsINode> parent1 = do_QueryInterface(aParent1);
2841 0 : nsCOMPtr<nsINode> parent2 = do_QueryInterface(aParent2);
2842 0 : NS_ENSURE_TRUE(parent1 && parent2, -1);
2843 0 : return ComparePoints(parent1, aOffset1, parent2, aOffset2);
2844 : }
2845 :
2846 : inline bool
2847 0 : IsCharInSet(const char* aSet,
2848 : const char16_t aChar)
2849 : {
2850 : char16_t ch;
2851 0 : while ((ch = *aSet)) {
2852 0 : if (aChar == char16_t(ch)) {
2853 0 : return true;
2854 : }
2855 0 : ++aSet;
2856 : }
2857 0 : return false;
2858 : }
2859 :
2860 : /**
2861 : * This method strips leading/trailing chars, in given set, from string.
2862 : */
2863 :
2864 : // static
2865 : const nsDependentSubstring
2866 0 : nsContentUtils::TrimCharsInSet(const char* aSet,
2867 : const nsAString& aValue)
2868 : {
2869 0 : nsAString::const_iterator valueCurrent, valueEnd;
2870 :
2871 0 : aValue.BeginReading(valueCurrent);
2872 0 : aValue.EndReading(valueEnd);
2873 :
2874 : // Skip characters in the beginning
2875 0 : while (valueCurrent != valueEnd) {
2876 0 : if (!IsCharInSet(aSet, *valueCurrent)) {
2877 0 : break;
2878 : }
2879 0 : ++valueCurrent;
2880 : }
2881 :
2882 0 : if (valueCurrent != valueEnd) {
2883 : for (;;) {
2884 0 : --valueEnd;
2885 0 : if (!IsCharInSet(aSet, *valueEnd)) {
2886 0 : break;
2887 : }
2888 : }
2889 0 : ++valueEnd; // Step beyond the last character we want in the value.
2890 : }
2891 :
2892 : // valueEnd should point to the char after the last to copy
2893 0 : return Substring(valueCurrent, valueEnd);
2894 : }
2895 :
2896 : /**
2897 : * This method strips leading and trailing whitespace from a string.
2898 : */
2899 :
2900 : // static
2901 : template<bool IsWhitespace(char16_t)>
2902 : const nsDependentSubstring
2903 0 : nsContentUtils::TrimWhitespace(const nsAString& aStr, bool aTrimTrailing)
2904 : {
2905 0 : nsAString::const_iterator start, end;
2906 :
2907 0 : aStr.BeginReading(start);
2908 0 : aStr.EndReading(end);
2909 :
2910 : // Skip whitespace characters in the beginning
2911 0 : while (start != end && IsWhitespace(*start)) {
2912 0 : ++start;
2913 : }
2914 :
2915 0 : if (aTrimTrailing) {
2916 : // Skip whitespace characters in the end.
2917 0 : while (end != start) {
2918 0 : --end;
2919 :
2920 0 : if (!IsWhitespace(*end)) {
2921 : // Step back to the last non-whitespace character.
2922 0 : ++end;
2923 :
2924 0 : break;
2925 : }
2926 : }
2927 : }
2928 :
2929 : // Return a substring for the string w/o leading and/or trailing
2930 : // whitespace
2931 :
2932 0 : return Substring(start, end);
2933 : }
2934 :
2935 : // Declaring the templates we are going to use avoid linking issues without
2936 : // inlining the method. Considering there is not so much spaces checking
2937 : // methods we can consider this to be better than inlining.
2938 : template
2939 : const nsDependentSubstring
2940 : nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
2941 : template
2942 : const nsDependentSubstring
2943 : nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
2944 : template
2945 : const nsDependentSubstring
2946 : nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
2947 :
2948 44 : static inline void KeyAppendSep(nsACString& aKey)
2949 : {
2950 44 : if (!aKey.IsEmpty()) {
2951 40 : aKey.Append('>');
2952 : }
2953 44 : }
2954 :
2955 4 : static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
2956 : {
2957 4 : KeyAppendSep(aKey);
2958 :
2959 : // Could escape separator here if collisions happen. > is not a legal char
2960 : // for a name or type attribute, so we should be safe avoiding that extra work.
2961 :
2962 4 : AppendUTF16toUTF8(aString, aKey);
2963 4 : }
2964 :
2965 0 : static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
2966 : {
2967 0 : KeyAppendSep(aKey);
2968 :
2969 : // Could escape separator here if collisions happen. > is not a legal char
2970 : // for a name or type attribute, so we should be safe avoiding that extra work.
2971 :
2972 0 : aKey.Append(aString);
2973 0 : }
2974 :
2975 40 : static inline void KeyAppendInt(int32_t aInt, nsACString& aKey)
2976 : {
2977 40 : KeyAppendSep(aKey);
2978 :
2979 40 : aKey.Append(nsPrintfCString("%d", aInt));
2980 40 : }
2981 :
2982 4 : static inline bool IsAutocompleteOff(const nsIContent* aElement)
2983 : {
2984 4 : return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
2985 8 : NS_LITERAL_STRING("off"), eIgnoreCase);
2986 : }
2987 :
2988 : /*static*/ nsresult
2989 10 : nsContentUtils::GenerateStateKey(nsIContent* aContent,
2990 : const nsIDocument* aDocument,
2991 : nsACString& aKey)
2992 : {
2993 10 : aKey.Truncate();
2994 :
2995 10 : uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
2996 :
2997 : // We must have content if we're not using a special state id
2998 10 : NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
2999 :
3000 : // Don't capture state for anonymous content
3001 10 : if (aContent->IsInAnonymousSubtree()) {
3002 6 : return NS_OK;
3003 : }
3004 :
3005 4 : if (IsAutocompleteOff(aContent)) {
3006 0 : return NS_OK;
3007 : }
3008 :
3009 : nsCOMPtr<nsIHTMLDocument> htmlDocument =
3010 8 : do_QueryInterface(aContent->GetUncomposedDoc());
3011 :
3012 4 : KeyAppendInt(partID, aKey); // first append a partID
3013 4 : bool generatedUniqueKey = false;
3014 :
3015 4 : if (htmlDocument) {
3016 : // Flush our content model so it'll be up to date
3017 : // If this becomes unnecessary and the following line is removed,
3018 : // please also remove the corresponding flush operation from
3019 : // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
3020 0 : aContent->GetUncomposedDoc()->FlushPendingNotifications(FlushType::Content);
3021 :
3022 0 : nsContentList *htmlForms = htmlDocument->GetForms();
3023 0 : nsContentList *htmlFormControls = htmlDocument->GetFormControls();
3024 :
3025 0 : NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
3026 :
3027 : // If we have a form control and can calculate form information, use that
3028 : // as the key - it is more reliable than just recording position in the
3029 : // DOM.
3030 : // XXXbz Is it, really? We have bugs on this, I think...
3031 : // Important to have a unique key, and tag/type/name may not be.
3032 : //
3033 : // If the control has a form, the format of the key is:
3034 : // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
3035 : // else:
3036 : // d>type>IndOfControlInDoc>name
3037 : //
3038 : // XXX We don't need to use index if name is there
3039 : // XXXbz We don't? Why not? I don't follow.
3040 : //
3041 0 : nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
3042 0 : if (control && htmlFormControls && htmlForms) {
3043 :
3044 : // Append the control type
3045 0 : KeyAppendInt(control->ControlType(), aKey);
3046 :
3047 : // If in a form, add form name / index of form / index in form
3048 0 : int32_t index = -1;
3049 0 : Element *formElement = control->GetFormElement();
3050 0 : if (formElement) {
3051 0 : if (IsAutocompleteOff(formElement)) {
3052 0 : aKey.Truncate();
3053 0 : return NS_OK;
3054 : }
3055 :
3056 0 : KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
3057 :
3058 : // Append the index of the form in the document
3059 0 : index = htmlForms->IndexOf(formElement, false);
3060 0 : if (index <= -1) {
3061 : //
3062 : // XXX HACK this uses some state that was dumped into the document
3063 : // specifically to fix bug 138892. What we are trying to do is *guess*
3064 : // which form this control's state is found in, with the highly likely
3065 : // guess that the highest form parsed so far is the one.
3066 : // This code should not be on trunk, only branch.
3067 : //
3068 0 : index = htmlDocument->GetNumFormsSynchronous() - 1;
3069 : }
3070 0 : if (index > -1) {
3071 0 : KeyAppendInt(index, aKey);
3072 :
3073 : // Append the index of the control in the form
3074 0 : nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
3075 0 : index = form->IndexOfControl(control);
3076 :
3077 0 : if (index > -1) {
3078 0 : KeyAppendInt(index, aKey);
3079 0 : generatedUniqueKey = true;
3080 : }
3081 : }
3082 :
3083 : // Append the form name
3084 0 : nsAutoString formName;
3085 0 : formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
3086 0 : KeyAppendString(formName, aKey);
3087 :
3088 : } else {
3089 :
3090 0 : KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
3091 :
3092 : // If not in a form, add index of control in document
3093 : // Less desirable than indexing by form info.
3094 :
3095 : // Hash by index of control in doc (we are not in a form)
3096 : // These are important as they are unique, and type/name may not be.
3097 :
3098 : // We have to flush sink notifications at this point to make
3099 : // sure that htmlFormControls is up to date.
3100 0 : index = htmlFormControls->IndexOf(aContent, true);
3101 0 : if (index > -1) {
3102 0 : KeyAppendInt(index, aKey);
3103 0 : generatedUniqueKey = true;
3104 : }
3105 : }
3106 :
3107 : // Append the control name
3108 0 : nsAutoString name;
3109 0 : aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
3110 0 : KeyAppendString(name, aKey);
3111 : }
3112 : }
3113 :
3114 4 : if (!generatedUniqueKey) {
3115 : // Either we didn't have a form control or we aren't in an HTML document so
3116 : // we can't figure out form info. Append the tag name if it's an element
3117 : // to avoid restoring state for one type of element on another type.
3118 4 : if (aContent->IsElement()) {
3119 8 : KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
3120 4 : aKey);
3121 : }
3122 : else {
3123 : // Append a character that is not "d" or "f" to disambiguate from
3124 : // the case when we were a form control in an HTML document.
3125 0 : KeyAppendString(NS_LITERAL_CSTRING("o"), aKey);
3126 : }
3127 :
3128 : // Now start at aContent and append the indices of it and all its ancestors
3129 : // in their containers. That should at least pin down its position in the
3130 : // DOM...
3131 4 : nsINode* parent = aContent->GetParentNode();
3132 4 : nsINode* content = aContent;
3133 76 : while (parent) {
3134 36 : KeyAppendInt(parent->IndexOf(content), aKey);
3135 36 : content = parent;
3136 36 : parent = content->GetParentNode();
3137 : }
3138 : }
3139 :
3140 4 : return NS_OK;
3141 : }
3142 :
3143 : // static
3144 : nsIPrincipal*
3145 11290 : nsContentUtils::SubjectPrincipal(JSContext* aCx)
3146 : {
3147 11290 : MOZ_ASSERT(NS_IsMainThread());
3148 :
3149 : // As opposed to SubjectPrincipal(), we do in fact assume that
3150 : // we're in a compartment here; anyone who calls this function
3151 : // in situations where that's not the case is doing it wrong.
3152 11290 : JSCompartment* compartment = js::GetContextCompartment(aCx);
3153 11290 : MOZ_ASSERT(compartment);
3154 :
3155 11290 : JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
3156 11290 : return nsJSPrincipals::get(principals);
3157 : }
3158 :
3159 : // static
3160 : nsIPrincipal*
3161 9896 : nsContentUtils::SubjectPrincipal()
3162 : {
3163 9896 : MOZ_ASSERT(IsInitialized());
3164 9896 : MOZ_ASSERT(NS_IsMainThread());
3165 9896 : JSContext* cx = GetCurrentJSContext();
3166 9896 : if (!cx) {
3167 0 : MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
3168 : }
3169 :
3170 9896 : JSCompartment *compartment = js::GetContextCompartment(cx);
3171 :
3172 : // When an AutoJSAPI is instantiated, we are in a null compartment until the
3173 : // first JSAutoCompartment, which is kind of a purgatory as far as permissions
3174 : // go. It would be nice to just hard-abort if somebody does a security check
3175 : // in this purgatory zone, but that would be too fragile, since it could be
3176 : // triggered by random IsCallerChrome() checks 20-levels deep.
3177 : //
3178 : // So we want to return _something_ here - and definitely not the System
3179 : // Principal, since that would make an AutoJSAPI a very dangerous thing to
3180 : // instantiate.
3181 : //
3182 : // The natural thing to return is a null principal. Ideally, we'd return a
3183 : // different null principal each time, to avoid any unexpected interactions
3184 : // when the principal accidentally gets inherited somewhere. But
3185 : // SubjectPrincipal doesn't return strong references, so there's no way to
3186 : // sanely manage the lifetime of multiple null principals.
3187 : //
3188 : // So we use a singleton null principal. To avoid it being accidentally
3189 : // inherited and becoming a "real" subject or object principal, we do a
3190 : // release-mode assert during compartment creation against using this
3191 : // principal on an actual global.
3192 9896 : if (!compartment) {
3193 45 : return sNullSubjectPrincipal;
3194 : }
3195 :
3196 9851 : return SubjectPrincipal(cx);
3197 : }
3198 :
3199 : // static
3200 : nsIPrincipal*
3201 681 : nsContentUtils::ObjectPrincipal(JSObject* aObj)
3202 : {
3203 681 : MOZ_ASSERT(NS_IsMainThread());
3204 :
3205 : #ifdef DEBUG
3206 681 : JS::AssertObjectBelongsToCurrentThread(aObj);
3207 : #endif
3208 :
3209 : // This is duplicated from nsScriptSecurityManager. We don't call through there
3210 : // because the API unnecessarily requires a JSContext for historical reasons.
3211 681 : JSCompartment *compartment = js::GetObjectCompartment(aObj);
3212 681 : JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
3213 681 : return nsJSPrincipals::get(principals);
3214 : }
3215 :
3216 : // static
3217 : nsresult
3218 29 : nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
3219 : const nsAString& aSpec,
3220 : nsIDocument* aDocument,
3221 : nsIURI* aBaseURI)
3222 : {
3223 29 : if (aDocument) {
3224 28 : return NS_NewURI(aResult, aSpec,
3225 : aDocument->GetDocumentCharacterSet(),
3226 28 : aBaseURI, sIOService);
3227 : }
3228 1 : return NS_NewURI(aResult, aSpec, nullptr, aBaseURI, sIOService);
3229 : }
3230 :
3231 : // static
3232 : bool
3233 883 : nsContentUtils::IsCustomElementName(nsIAtom* aName)
3234 : {
3235 : // A valid custom element name is a sequence of characters name which
3236 : // must match the PotentialCustomElementName production:
3237 : // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
3238 883 : const char16_t* name = aName->GetUTF16String();
3239 883 : uint32_t len = aName->GetLength();
3240 883 : bool hasDash = false;
3241 :
3242 883 : if (!len || name[0] < 'a' || name[0] > 'z') {
3243 0 : return false;
3244 : }
3245 :
3246 883 : uint32_t i = 1;
3247 11175 : while (i < len) {
3248 5146 : if (NS_IS_HIGH_SURROGATE(name[i]) && i + 1 < len &&
3249 0 : NS_IS_LOW_SURROGATE(name[i + 1])) {
3250 : // Merged two 16-bit surrogate pairs into code point.
3251 0 : char32_t code = SURROGATE_TO_UCS4(name[i], name[i + 1]);
3252 :
3253 0 : if (code < 0x10000 || code > 0xEFFFF) {
3254 0 : return false;
3255 : }
3256 :
3257 0 : i += 2;
3258 : } else {
3259 5146 : if (name[i] == '-') {
3260 0 : hasDash = true;
3261 : }
3262 :
3263 10292 : if (name[i] != '-' && name[i] != '.' &&
3264 15438 : name[i] != '_' && name[i] != 0xB7 &&
3265 15438 : (name[i] < '0' || name[i] > '9') &&
3266 10292 : (name[i] < 'a' || name[i] > 'z') &&
3267 0 : (name[i] < 0xC0 || name[i] > 0xD6) &&
3268 0 : (name[i] < 0xF8 || name[i] > 0x37D) &&
3269 0 : (name[i] < 0x37F || name[i] > 0x1FFF) &&
3270 0 : (name[i] < 0x200C || name[i] > 0x200D) &&
3271 0 : (name[i] < 0x203F || name[i] > 0x2040) &&
3272 0 : (name[i] < 0x2070 || name[i] > 0x218F) &&
3273 0 : (name[i] < 0x2C00 || name[i] > 0x2FEF) &&
3274 0 : (name[i] < 0x3001 || name[i] > 0xD7FF) &&
3275 0 : (name[i] < 0xF900 || name[i] > 0xFDCF) &&
3276 0 : (name[i] < 0xFDF0 || name[i] > 0xFFFD)) {
3277 0 : return false;
3278 : }
3279 :
3280 5146 : i++;
3281 : }
3282 : }
3283 :
3284 883 : if (!hasDash) {
3285 883 : return false;
3286 : }
3287 :
3288 : // The custom element name must not be one of the following values:
3289 : // annotation-xml
3290 : // color-profile
3291 : // font-face
3292 : // font-face-src
3293 : // font-face-uri
3294 : // font-face-format
3295 : // font-face-name
3296 : // missing-glyph
3297 0 : return aName != nsGkAtoms::annotation_xml_ &&
3298 0 : aName != nsGkAtoms::colorProfile &&
3299 0 : aName != nsGkAtoms::font_face &&
3300 0 : aName != nsGkAtoms::font_face_src &&
3301 0 : aName != nsGkAtoms::font_face_uri &&
3302 0 : aName != nsGkAtoms::font_face_format &&
3303 0 : aName != nsGkAtoms::font_face_name &&
3304 0 : aName != nsGkAtoms::missingGlyph;
3305 : }
3306 :
3307 : // static
3308 : nsresult
3309 672 : nsContentUtils::CheckQName(const nsAString& aQualifiedName,
3310 : bool aNamespaceAware,
3311 : const char16_t** aColon)
3312 : {
3313 672 : const char* colon = nullptr;
3314 672 : const char16_t* begin = aQualifiedName.BeginReading();
3315 672 : const char16_t* end = aQualifiedName.EndReading();
3316 :
3317 672 : int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
3318 : reinterpret_cast<const char*>(end),
3319 672 : aNamespaceAware, &colon);
3320 :
3321 672 : if (!result) {
3322 672 : if (aColon) {
3323 66 : *aColon = reinterpret_cast<const char16_t*>(colon);
3324 : }
3325 :
3326 672 : return NS_OK;
3327 : }
3328 :
3329 0 : return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
3330 : }
3331 :
3332 : //static
3333 : nsresult
3334 33 : nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
3335 : const nsString& aQName,
3336 : int32_t *aNamespace, nsIAtom **aLocalName)
3337 : {
3338 : const char16_t* colon;
3339 33 : nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
3340 33 : NS_ENSURE_SUCCESS(rv, rv);
3341 :
3342 33 : if (colon) {
3343 : const char16_t* end;
3344 0 : aQName.EndReading(end);
3345 0 : nsAutoString nameSpace;
3346 0 : rv = aNamespaceResolver->LookupNamespaceURIInternal(Substring(aQName.get(),
3347 : colon),
3348 0 : nameSpace);
3349 0 : NS_ENSURE_SUCCESS(rv, rv);
3350 :
3351 0 : *aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace,
3352 0 : nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
3353 0 : if (*aNamespace == kNameSpaceID_Unknown)
3354 0 : return NS_ERROR_FAILURE;
3355 :
3356 0 : *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
3357 : }
3358 : else {
3359 33 : *aNamespace = kNameSpaceID_None;
3360 33 : *aLocalName = NS_AtomizeMainThread(aQName).take();
3361 : }
3362 33 : NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
3363 33 : return NS_OK;
3364 : }
3365 :
3366 : // static
3367 : nsresult
3368 33 : nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
3369 : const nsAString& aQualifiedName,
3370 : nsNodeInfoManager* aNodeInfoManager,
3371 : uint16_t aNodeType,
3372 : mozilla::dom::NodeInfo** aNodeInfo)
3373 : {
3374 66 : const nsString& qName = PromiseFlatString(aQualifiedName);
3375 : const char16_t* colon;
3376 33 : nsresult rv = nsContentUtils::CheckQName(qName, true, &colon);
3377 33 : NS_ENSURE_SUCCESS(rv, rv);
3378 :
3379 : int32_t nsID;
3380 33 : sNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsID);
3381 33 : if (colon) {
3382 : const char16_t* end;
3383 0 : qName.EndReading(end);
3384 :
3385 : nsCOMPtr<nsIAtom> prefix =
3386 0 : NS_AtomizeMainThread(Substring(qName.get(), colon));
3387 :
3388 0 : rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
3389 0 : nsID, aNodeType, aNodeInfo);
3390 : }
3391 : else {
3392 33 : rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID,
3393 33 : aNodeType, aNodeInfo);
3394 : }
3395 33 : NS_ENSURE_SUCCESS(rv, rv);
3396 :
3397 33 : return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
3398 : (*aNodeInfo)->GetPrefixAtom(),
3399 33 : (*aNodeInfo)->NamespaceID()) ?
3400 33 : NS_OK : NS_ERROR_DOM_NAMESPACE_ERR;
3401 : }
3402 :
3403 : // static
3404 : void
3405 660 : nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix,
3406 : nsIAtom **aLocalName, int32_t* aNameSpaceID)
3407 : {
3408 : /**
3409 : * Expat can send the following:
3410 : * localName
3411 : * namespaceURI<separator>localName
3412 : * namespaceURI<separator>localName<separator>prefix
3413 : *
3414 : * and we use 0xFFFF for the <separator>.
3415 : *
3416 : */
3417 :
3418 660 : const char16_t *uriEnd = nullptr;
3419 660 : const char16_t *nameEnd = nullptr;
3420 : const char16_t *pos;
3421 14565 : for (pos = aExpatName; *pos; ++pos) {
3422 13905 : if (*pos == 0xFFFF) {
3423 431 : if (uriEnd) {
3424 69 : nameEnd = pos;
3425 : }
3426 : else {
3427 362 : uriEnd = pos;
3428 : }
3429 : }
3430 : }
3431 :
3432 : const char16_t *nameStart;
3433 660 : if (uriEnd) {
3434 362 : if (sNameSpaceManager) {
3435 724 : sNameSpaceManager->RegisterNameSpace(nsDependentSubstring(aExpatName,
3436 : uriEnd),
3437 362 : *aNameSpaceID);
3438 : }
3439 : else {
3440 0 : *aNameSpaceID = kNameSpaceID_Unknown;
3441 : }
3442 :
3443 362 : nameStart = (uriEnd + 1);
3444 362 : if (nameEnd) {
3445 69 : const char16_t *prefixStart = nameEnd + 1;
3446 69 : *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
3447 : }
3448 : else {
3449 293 : nameEnd = pos;
3450 293 : *aPrefix = nullptr;
3451 : }
3452 : }
3453 : else {
3454 298 : *aNameSpaceID = kNameSpaceID_None;
3455 298 : nameStart = aExpatName;
3456 298 : nameEnd = pos;
3457 298 : *aPrefix = nullptr;
3458 : }
3459 660 : *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
3460 660 : }
3461 :
3462 : // static
3463 : nsPresContext*
3464 48 : nsContentUtils::GetContextForContent(const nsIContent* aContent)
3465 : {
3466 48 : nsIDocument* doc = aContent->GetComposedDoc();
3467 48 : if (doc) {
3468 48 : nsIPresShell *presShell = doc->GetShell();
3469 48 : if (presShell) {
3470 48 : return presShell->GetPresContext();
3471 : }
3472 : }
3473 0 : return nullptr;
3474 : }
3475 :
3476 : // static
3477 : bool
3478 0 : nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
3479 : nsIDocument* aLoadingDocument,
3480 : nsIPrincipal* aLoadingPrincipal,
3481 : int16_t* aImageBlockingStatus,
3482 : uint32_t aContentType)
3483 : {
3484 0 : NS_PRECONDITION(aURI, "Must have a URI");
3485 0 : NS_PRECONDITION(aLoadingDocument, "Must have a document");
3486 0 : NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal");
3487 :
3488 : nsresult rv;
3489 :
3490 0 : uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
3491 :
3492 : {
3493 0 : nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aLoadingDocument->GetDocShell();
3494 0 : if (docShellTreeItem) {
3495 0 : nsCOMPtr<nsIDocShellTreeItem> root;
3496 0 : docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
3497 :
3498 0 : nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
3499 :
3500 0 : if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
3501 0 : appType = nsIDocShell::APP_TYPE_UNKNOWN;
3502 : }
3503 : }
3504 : }
3505 :
3506 0 : if (appType != nsIDocShell::APP_TYPE_EDITOR) {
3507 : // Editor apps get special treatment here, editors can load images
3508 : // from anywhere. This allows editor to insert images from file://
3509 : // into documents that are being edited.
3510 : rv = sSecurityManager->
3511 0 : CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
3512 0 : nsIScriptSecurityManager::ALLOW_CHROME);
3513 0 : if (NS_FAILED(rv)) {
3514 0 : if (aImageBlockingStatus) {
3515 : // Reject the request itself, not all requests to the relevant
3516 : // server...
3517 0 : *aImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
3518 : }
3519 0 : return false;
3520 : }
3521 : }
3522 :
3523 0 : int16_t decision = nsIContentPolicy::ACCEPT;
3524 :
3525 0 : rv = NS_CheckContentLoadPolicy(aContentType,
3526 : aURI,
3527 : aLoadingPrincipal,
3528 : aContext,
3529 0 : EmptyCString(), //mime guess
3530 : nullptr, //extra
3531 : &decision,
3532 : GetContentPolicy(),
3533 0 : sSecurityManager);
3534 :
3535 0 : if (aImageBlockingStatus) {
3536 0 : *aImageBlockingStatus =
3537 0 : NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
3538 : }
3539 0 : return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
3540 : }
3541 :
3542 : // static
3543 : mozilla::OriginAttributes
3544 0 : nsContentUtils::GetOriginAttributes(nsIDocument* aDocument)
3545 : {
3546 0 : if (!aDocument) {
3547 0 : return mozilla::OriginAttributes();
3548 : }
3549 :
3550 0 : nsCOMPtr<nsILoadGroup> loadGroup = aDocument->GetDocumentLoadGroup();
3551 0 : if (loadGroup) {
3552 0 : return GetOriginAttributes(loadGroup);
3553 : }
3554 :
3555 0 : mozilla::OriginAttributes attrs;
3556 0 : nsCOMPtr<nsIChannel> channel = aDocument->GetChannel();
3557 0 : if (channel) {
3558 0 : NS_GetOriginAttributes(channel, attrs);
3559 : }
3560 0 : return attrs;
3561 : }
3562 :
3563 : // static
3564 : mozilla::OriginAttributes
3565 2 : nsContentUtils::GetOriginAttributes(nsILoadGroup* aLoadGroup)
3566 : {
3567 2 : if (!aLoadGroup) {
3568 0 : return mozilla::OriginAttributes();
3569 : }
3570 4 : mozilla::OriginAttributes attrs;
3571 4 : nsCOMPtr<nsIInterfaceRequestor> callbacks;
3572 2 : aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3573 2 : if (callbacks) {
3574 4 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
3575 2 : if (loadContext) {
3576 2 : loadContext->GetOriginAttributes(attrs);
3577 : }
3578 : }
3579 2 : return attrs;
3580 : }
3581 :
3582 : // static
3583 : bool
3584 103 : nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc)
3585 : {
3586 103 : if (!aDoc) {
3587 0 : return false;
3588 : }
3589 :
3590 206 : nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
3591 103 : if (loadGroup) {
3592 103 : return IsInPrivateBrowsing(loadGroup);
3593 : }
3594 :
3595 0 : nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
3596 0 : return channel && NS_UsePrivateBrowsing(channel);
3597 : }
3598 :
3599 : // static
3600 : bool
3601 103 : nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup)
3602 : {
3603 103 : if (!aLoadGroup) {
3604 0 : return false;
3605 : }
3606 103 : bool isPrivate = false;
3607 206 : nsCOMPtr<nsIInterfaceRequestor> callbacks;
3608 103 : aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
3609 103 : if (callbacks) {
3610 206 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
3611 103 : isPrivate = loadContext && loadContext->UsePrivateBrowsing();
3612 : }
3613 103 : return isPrivate;
3614 : }
3615 :
3616 : bool
3617 68 : nsContentUtils::DocumentInactiveForImageLoads(nsIDocument* aDocument)
3618 : {
3619 68 : if (aDocument && !IsChromeDoc(aDocument) && !aDocument->IsResourceDoc()) {
3620 : nsCOMPtr<nsPIDOMWindowInner> win =
3621 0 : do_QueryInterface(aDocument->GetScopeObject());
3622 0 : return !win || !win->GetDocShell();
3623 : }
3624 68 : return false;
3625 : }
3626 :
3627 : imgLoader*
3628 45 : nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
3629 : {
3630 45 : NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr);
3631 :
3632 45 : if (!aDoc) {
3633 0 : return imgLoader::NormalLoader();
3634 : }
3635 45 : bool isPrivate = IsInPrivateBrowsing(aDoc);
3636 45 : return isPrivate ? imgLoader::PrivateBrowsingLoader()
3637 45 : : imgLoader::NormalLoader();
3638 : }
3639 :
3640 : // static
3641 : imgLoader*
3642 11 : nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
3643 : nsIDocument* aContext)
3644 : {
3645 11 : NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr);
3646 :
3647 11 : if (!aChannel) {
3648 11 : return imgLoader::NormalLoader();
3649 : }
3650 0 : nsCOMPtr<nsILoadContext> context;
3651 0 : NS_QueryNotificationCallbacks(aChannel, context);
3652 0 : return context && context->UsePrivateBrowsing() ?
3653 : imgLoader::PrivateBrowsingLoader() :
3654 0 : imgLoader::NormalLoader();
3655 : }
3656 :
3657 : // static
3658 : bool
3659 0 : nsContentUtils::IsImageInCache(nsIURI* aURI, nsIDocument* aDocument)
3660 : {
3661 0 : imgILoader* loader = GetImgLoaderForDocument(aDocument);
3662 0 : nsCOMPtr<imgICache> cache = do_QueryInterface(loader);
3663 :
3664 : // If something unexpected happened we return false, otherwise if props
3665 : // is set, the image is cached and we return true
3666 0 : nsCOMPtr<nsIProperties> props;
3667 0 : nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
3668 0 : nsresult rv = cache->FindEntryProperties(aURI, domDoc, getter_AddRefs(props));
3669 0 : return (NS_SUCCEEDED(rv) && props);
3670 : }
3671 :
3672 : // static
3673 : nsresult
3674 45 : nsContentUtils::LoadImage(nsIURI* aURI, nsINode* aContext,
3675 : nsIDocument* aLoadingDocument,
3676 : nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
3677 : net::ReferrerPolicy aReferrerPolicy,
3678 : imgINotificationObserver* aObserver, int32_t aLoadFlags,
3679 : const nsAString& initiatorType,
3680 : imgRequestProxy** aRequest,
3681 : uint32_t aContentPolicyType,
3682 : bool aUseUrgentStartForChannel)
3683 : {
3684 45 : NS_PRECONDITION(aURI, "Must have a URI");
3685 45 : NS_PRECONDITION(aContext, "Must have a context");
3686 45 : NS_PRECONDITION(aLoadingDocument, "Must have a document");
3687 45 : NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
3688 45 : NS_PRECONDITION(aRequest, "Null out param");
3689 :
3690 45 : imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
3691 45 : if (!imgLoader) {
3692 : // nothing we can do here
3693 0 : return NS_ERROR_FAILURE;
3694 : }
3695 :
3696 90 : nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
3697 :
3698 45 : nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
3699 :
3700 45 : NS_ASSERTION(loadGroup || IsFontTableURI(documentURI),
3701 : "Could not get loadgroup; onload may fire too early");
3702 :
3703 : // Make the URI immutable so people won't change it under us
3704 45 : NS_TryToSetImmutable(aURI);
3705 :
3706 : // XXXbz using "documentURI" for the initialDocumentURI is not quite
3707 : // right, but the best we can do here...
3708 45 : return imgLoader->LoadImage(aURI, /* uri to load */
3709 : documentURI, /* initialDocumentURI */
3710 : aReferrer, /* referrer */
3711 : aReferrerPolicy, /* referrer policy */
3712 : aLoadingPrincipal, /* loading principal */
3713 : loadGroup, /* loadgroup */
3714 : aObserver, /* imgINotificationObserver */
3715 : aContext, /* loading context */
3716 : aLoadingDocument, /* uniquification key */
3717 : aLoadFlags, /* load flags */
3718 : nullptr, /* cache key */
3719 : aContentPolicyType, /* content policy type */
3720 : initiatorType, /* the load initiator */
3721 : aUseUrgentStartForChannel, /* urgent-start flag */
3722 45 : aRequest);
3723 : }
3724 :
3725 : // static
3726 : already_AddRefed<imgIContainer>
3727 0 : nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
3728 : imgIRequest **aRequest)
3729 : {
3730 0 : if (aRequest) {
3731 0 : *aRequest = nullptr;
3732 : }
3733 :
3734 0 : NS_ENSURE_TRUE(aContent, nullptr);
3735 :
3736 0 : nsCOMPtr<imgIRequest> imgRequest;
3737 0 : aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
3738 0 : getter_AddRefs(imgRequest));
3739 0 : if (!imgRequest) {
3740 0 : return nullptr;
3741 : }
3742 :
3743 0 : nsCOMPtr<imgIContainer> imgContainer;
3744 0 : imgRequest->GetImage(getter_AddRefs(imgContainer));
3745 :
3746 0 : if (!imgContainer) {
3747 0 : return nullptr;
3748 : }
3749 :
3750 0 : if (aRequest) {
3751 0 : imgRequest.swap(*aRequest);
3752 : }
3753 :
3754 0 : return imgContainer.forget();
3755 : }
3756 :
3757 : //static
3758 : already_AddRefed<imgRequestProxy>
3759 0 : nsContentUtils::GetStaticRequest(imgRequestProxy* aRequest)
3760 : {
3761 0 : NS_ENSURE_TRUE(aRequest, nullptr);
3762 0 : RefPtr<imgRequestProxy> retval;
3763 0 : aRequest->GetStaticRequest(getter_AddRefs(retval));
3764 0 : return retval.forget();
3765 : }
3766 :
3767 : // static
3768 : bool
3769 0 : nsContentUtils::ContentIsDraggable(nsIContent* aContent)
3770 : {
3771 0 : nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aContent);
3772 0 : if (htmlElement) {
3773 0 : bool draggable = false;
3774 0 : htmlElement->GetDraggable(&draggable);
3775 0 : if (draggable)
3776 0 : return true;
3777 :
3778 0 : if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
3779 : nsGkAtoms::_false, eIgnoreCase))
3780 0 : return false;
3781 : }
3782 :
3783 : // special handling for content area image and link dragging
3784 0 : return IsDraggableImage(aContent) || IsDraggableLink(aContent);
3785 : }
3786 :
3787 : // static
3788 : bool
3789 0 : nsContentUtils::IsDraggableImage(nsIContent* aContent)
3790 : {
3791 0 : NS_PRECONDITION(aContent, "Must have content node to test");
3792 :
3793 0 : nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aContent));
3794 0 : if (!imageContent) {
3795 0 : return false;
3796 : }
3797 :
3798 0 : nsCOMPtr<imgIRequest> imgRequest;
3799 0 : imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
3800 0 : getter_AddRefs(imgRequest));
3801 :
3802 : // XXXbz It may be draggable even if the request resulted in an error. Why?
3803 : // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
3804 0 : return imgRequest != nullptr;
3805 : }
3806 :
3807 : // static
3808 : bool
3809 0 : nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
3810 0 : nsCOMPtr<nsIURI> absURI;
3811 0 : return aContent->IsLink(getter_AddRefs(absURI));
3812 : }
3813 :
3814 : // static
3815 : nsresult
3816 0 : nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo, nsIAtom* aName,
3817 : mozilla::dom::NodeInfo** aResult)
3818 : {
3819 0 : nsNodeInfoManager *niMgr = aNodeInfo->NodeInfoManager();
3820 :
3821 0 : *aResult = niMgr->GetNodeInfo(aName, nullptr,
3822 : aNodeInfo->NamespaceID(),
3823 0 : aNodeInfo->NodeType(),
3824 0 : aNodeInfo->GetExtraName()).take();
3825 0 : return NS_OK;
3826 : }
3827 :
3828 :
3829 : static bool
3830 13 : TestSitePerm(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPerm, bool aExactHostMatch)
3831 : {
3832 13 : if (!aPrincipal) {
3833 : // We always deny (i.e. don't allow) the permission if we don't have a
3834 : // principal.
3835 0 : return aPerm != nsIPermissionManager::ALLOW_ACTION;
3836 : }
3837 :
3838 26 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
3839 13 : NS_ENSURE_TRUE(permMgr, false);
3840 :
3841 : uint32_t perm;
3842 : nsresult rv;
3843 13 : if (aExactHostMatch) {
3844 0 : rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
3845 : } else {
3846 13 : rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
3847 : }
3848 13 : NS_ENSURE_SUCCESS(rv, false);
3849 :
3850 13 : return perm == aPerm;
3851 : }
3852 :
3853 : bool
3854 13 : nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
3855 : {
3856 13 : return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, false);
3857 : }
3858 :
3859 : bool
3860 0 : nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal, const char* aType)
3861 : {
3862 0 : return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, false);
3863 : }
3864 :
3865 : bool
3866 0 : nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
3867 : {
3868 0 : return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION, true);
3869 : }
3870 :
3871 : bool
3872 0 : nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal, const char* aType)
3873 : {
3874 0 : return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION, true);
3875 : }
3876 :
3877 : static const char *gEventNames[] = {"event"};
3878 : static const char *gSVGEventNames[] = {"evt"};
3879 : // for b/w compat, the first name to onerror is still 'event', even though it
3880 : // is actually the error message
3881 : static const char *gOnErrorNames[] = {"event", "source", "lineno",
3882 : "colno", "error"};
3883 :
3884 : // static
3885 : void
3886 11 : nsContentUtils::GetEventArgNames(int32_t aNameSpaceID,
3887 : nsIAtom *aEventName,
3888 : bool aIsForWindow,
3889 : uint32_t *aArgCount,
3890 : const char*** aArgArray)
3891 : {
3892 : #define SET_EVENT_ARG_NAMES(names) \
3893 : *aArgCount = sizeof(names)/sizeof(names[0]); \
3894 : *aArgArray = names;
3895 :
3896 : // JSEventHandler is what does the arg magic for onerror, and it does
3897 : // not seem to take the namespace into account. So we let onerror in all
3898 : // namespaces get the 3 arg names.
3899 11 : if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
3900 0 : SET_EVENT_ARG_NAMES(gOnErrorNames);
3901 11 : } else if (aNameSpaceID == kNameSpaceID_SVG) {
3902 0 : SET_EVENT_ARG_NAMES(gSVGEventNames);
3903 : } else {
3904 11 : SET_EVENT_ARG_NAMES(gEventNames);
3905 : }
3906 11 : }
3907 :
3908 : static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
3909 : // Must line up with the enum values in |PropertiesFile| enum.
3910 : "chrome://global/locale/css.properties",
3911 : "chrome://global/locale/xbl.properties",
3912 : "chrome://global/locale/xul.properties",
3913 : "chrome://global/locale/layout_errors.properties",
3914 : "chrome://global/locale/layout/HtmlForm.properties",
3915 : "chrome://global/locale/printing.properties",
3916 : "chrome://global/locale/dom/dom.properties",
3917 : "chrome://global/locale/layout/htmlparser.properties",
3918 : "chrome://global/locale/svg/svg.properties",
3919 : "chrome://branding/locale/brand.properties",
3920 : "chrome://global/locale/commonDialogs.properties",
3921 : "chrome://global/locale/mathml/mathml.properties",
3922 : "chrome://global/locale/security/security.properties",
3923 : "chrome://necko/locale/necko.properties"
3924 : };
3925 :
3926 : /* static */ nsresult
3927 0 : nsContentUtils::EnsureStringBundle(PropertiesFile aFile)
3928 : {
3929 0 : if (!sStringBundles[aFile]) {
3930 0 : if (!sStringBundleService) {
3931 : nsresult rv =
3932 0 : CallGetService(NS_STRINGBUNDLE_CONTRACTID, &sStringBundleService);
3933 0 : NS_ENSURE_SUCCESS(rv, rv);
3934 : }
3935 : nsIStringBundle *bundle;
3936 : nsresult rv =
3937 0 : sStringBundleService->CreateBundle(gPropertiesFiles[aFile], &bundle);
3938 0 : NS_ENSURE_SUCCESS(rv, rv);
3939 0 : sStringBundles[aFile] = bundle; // transfer ownership
3940 : }
3941 0 : return NS_OK;
3942 : }
3943 :
3944 : /* static */
3945 0 : nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
3946 : const char* aKey,
3947 : nsXPIDLString& aResult)
3948 : {
3949 0 : nsresult rv = EnsureStringBundle(aFile);
3950 0 : NS_ENSURE_SUCCESS(rv, rv);
3951 0 : nsIStringBundle *bundle = sStringBundles[aFile];
3952 :
3953 0 : return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
3954 0 : getter_Copies(aResult));
3955 : }
3956 :
3957 : /* static */
3958 0 : nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile,
3959 : const char* aKey,
3960 : const char16_t **aParams,
3961 : uint32_t aParamsLength,
3962 : nsXPIDLString& aResult)
3963 : {
3964 0 : nsresult rv = EnsureStringBundle(aFile);
3965 0 : NS_ENSURE_SUCCESS(rv, rv);
3966 0 : nsIStringBundle *bundle = sStringBundles[aFile];
3967 :
3968 0 : if (!aParams || !aParamsLength) {
3969 0 : return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
3970 0 : getter_Copies(aResult));
3971 : }
3972 :
3973 0 : return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
3974 : aParams, aParamsLength,
3975 0 : getter_Copies(aResult));
3976 : }
3977 :
3978 : /* static */
3979 0 : nsresult nsContentUtils::FormatLocalizedString(
3980 : PropertiesFile aFile,
3981 : const char* aKey,
3982 : const nsTArray<nsString>& aParamArray,
3983 : nsXPIDLString& aResult)
3984 : {
3985 0 : MOZ_ASSERT(NS_IsMainThread());
3986 :
3987 0 : UniquePtr<const char16_t*[]> params;
3988 0 : uint32_t paramsLength = aParamArray.Length();
3989 0 : if (paramsLength > 0) {
3990 0 : params = MakeUnique<const char16_t*[]>(paramsLength);
3991 0 : for (uint32_t i = 0; i < paramsLength; ++i) {
3992 0 : params[i] = aParamArray[i].get();
3993 : }
3994 : }
3995 0 : return FormatLocalizedString(aFile, aKey, params.get(), paramsLength,
3996 0 : aResult);
3997 : }
3998 :
3999 :
4000 : /* static */ void
4001 0 : nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
4002 : const char * classification)
4003 : {
4004 : nsCOMPtr<nsIScriptError> scriptError =
4005 0 : do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
4006 0 : if (scriptError) {
4007 : nsCOMPtr<nsIConsoleService> console =
4008 0 : do_GetService(NS_CONSOLESERVICE_CONTRACTID);
4009 0 : if (console && NS_SUCCEEDED(scriptError->Init(aErrorText, EmptyString(),
4010 : EmptyString(), 0, 0,
4011 : nsIScriptError::errorFlag,
4012 : classification))) {
4013 0 : console->LogMessage(scriptError);
4014 : }
4015 : }
4016 0 : }
4017 :
4018 : /* static */ nsresult
4019 0 : nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
4020 : const nsACString& aCategory,
4021 : const nsIDocument* aDocument,
4022 : PropertiesFile aFile,
4023 : const char *aMessageName,
4024 : const char16_t **aParams,
4025 : uint32_t aParamsLength,
4026 : nsIURI* aURI,
4027 : const nsString& aSourceLine,
4028 : uint32_t aLineNumber,
4029 : uint32_t aColumnNumber)
4030 : {
4031 0 : NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
4032 : "Supply either both parameters and their number or no"
4033 : "parameters and 0.");
4034 :
4035 : nsresult rv;
4036 0 : nsXPIDLString errorText;
4037 0 : if (aParams) {
4038 : rv = FormatLocalizedString(aFile, aMessageName, aParams, aParamsLength,
4039 0 : errorText);
4040 : }
4041 : else {
4042 0 : rv = GetLocalizedString(aFile, aMessageName, errorText);
4043 : }
4044 0 : NS_ENSURE_SUCCESS(rv, rv);
4045 :
4046 : return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
4047 : aDocument, aURI, aSourceLine,
4048 0 : aLineNumber, aColumnNumber);
4049 : }
4050 :
4051 :
4052 : /* static */ nsresult
4053 0 : nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
4054 : uint32_t aErrorFlags,
4055 : const nsACString& aCategory,
4056 : const nsIDocument* aDocument,
4057 : nsIURI* aURI,
4058 : const nsString& aSourceLine,
4059 : uint32_t aLineNumber,
4060 : uint32_t aColumnNumber,
4061 : MissingErrorLocationMode aLocationMode)
4062 : {
4063 0 : uint64_t innerWindowID = 0;
4064 0 : if (aDocument) {
4065 0 : if (!aURI) {
4066 0 : aURI = aDocument->GetDocumentURI();
4067 : }
4068 0 : innerWindowID = aDocument->InnerWindowID();
4069 : }
4070 :
4071 : return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
4072 : innerWindowID, aURI, aSourceLine,
4073 0 : aLineNumber, aColumnNumber, aLocationMode);
4074 : }
4075 :
4076 : /* static */ nsresult
4077 0 : nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
4078 : uint32_t aErrorFlags,
4079 : const nsACString& aCategory,
4080 : uint64_t aInnerWindowID,
4081 : nsIURI* aURI,
4082 : const nsString& aSourceLine,
4083 : uint32_t aLineNumber,
4084 : uint32_t aColumnNumber,
4085 : MissingErrorLocationMode aLocationMode)
4086 : {
4087 : nsresult rv;
4088 0 : if (!sConsoleService) { // only need to bother null-checking here
4089 0 : rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
4090 0 : NS_ENSURE_SUCCESS(rv, rv);
4091 : }
4092 :
4093 0 : nsAutoCString spec;
4094 0 : if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
4095 0 : JSContext *cx = GetCurrentJSContext();
4096 0 : if (cx) {
4097 0 : nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
4098 : }
4099 : }
4100 0 : if (spec.IsEmpty() && aURI) {
4101 0 : spec = aURI->GetSpecOrDefault();
4102 : }
4103 :
4104 : nsCOMPtr<nsIScriptError> errorObject =
4105 0 : do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
4106 0 : NS_ENSURE_SUCCESS(rv, rv);
4107 :
4108 0 : rv = errorObject->InitWithWindowID(aErrorText,
4109 0 : NS_ConvertUTF8toUTF16(spec), // file name
4110 : aSourceLine,
4111 : aLineNumber, aColumnNumber,
4112 : aErrorFlags, aCategory,
4113 0 : aInnerWindowID);
4114 0 : NS_ENSURE_SUCCESS(rv, rv);
4115 :
4116 0 : return sConsoleService->LogMessage(errorObject);
4117 : }
4118 :
4119 : void
4120 0 : nsContentUtils::LogMessageToConsole(const char* aMsg)
4121 : {
4122 0 : if (!sConsoleService) { // only need to bother null-checking here
4123 0 : CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
4124 0 : if (!sConsoleService) {
4125 0 : return;
4126 : }
4127 : }
4128 0 : sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
4129 : }
4130 :
4131 : bool
4132 1540 : nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
4133 : {
4134 1540 : if (!aDocument) {
4135 0 : return false;
4136 : }
4137 1540 : return aDocument->NodePrincipal() == sSystemPrincipal;
4138 : }
4139 :
4140 : bool
4141 0 : nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
4142 : {
4143 0 : nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
4144 0 : nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
4145 0 : if (docShellAsItem) {
4146 0 : docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
4147 : }
4148 0 : return sameTypeParent != nullptr;
4149 : }
4150 :
4151 : bool
4152 22 : nsContentUtils::IsScriptType(const nsACString& aContentType)
4153 : {
4154 : // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
4155 : // define in nsContentDLF.h as well.
4156 44 : return aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
4157 44 : aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
4158 44 : aContentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
4159 44 : aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
4160 44 : aContentType.EqualsLiteral(TEXT_JAVASCRIPT) ||
4161 66 : aContentType.EqualsLiteral(APPLICATION_JSON) ||
4162 44 : aContentType.EqualsLiteral(TEXT_JSON);
4163 : }
4164 :
4165 : bool
4166 22 : nsContentUtils::IsPlainTextType(const nsACString& aContentType)
4167 : {
4168 : // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
4169 : // define in nsContentDLF.h as well.
4170 44 : return aContentType.EqualsLiteral(TEXT_PLAIN) ||
4171 44 : aContentType.EqualsLiteral(TEXT_CSS) ||
4172 44 : aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
4173 66 : aContentType.EqualsLiteral(TEXT_VTT) ||
4174 44 : IsScriptType(aContentType);
4175 : }
4176 :
4177 : bool
4178 0 : nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType)
4179 : {
4180 : // NOTE: This must be a subset of the list in IsPlainTextType().
4181 0 : return aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
4182 0 : aContentType.EqualsLiteral(APPLICATION_JSON) ||
4183 0 : aContentType.EqualsLiteral(TEXT_JSON) ||
4184 0 : aContentType.EqualsLiteral(TEXT_VTT);
4185 : }
4186 :
4187 : bool
4188 375 : nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument* aDocument,
4189 : nsIURI* aURI,
4190 : nsACString& aScriptURI,
4191 : nsresult* aRv)
4192 : {
4193 375 : MOZ_ASSERT(aRv);
4194 375 : bool scriptFileNameModified = false;
4195 375 : *aRv = NS_OK;
4196 :
4197 375 : *aRv = aURI->GetSpec(aScriptURI);
4198 375 : NS_ENSURE_SUCCESS(*aRv, false);
4199 :
4200 375 : if (IsChromeDoc(aDocument)) {
4201 : nsCOMPtr<nsIChromeRegistry> chromeReg =
4202 714 : mozilla::services::GetChromeRegistryService();
4203 :
4204 357 : if (!chromeReg) {
4205 : // If we're running w/o a chrome registry we won't modify any
4206 : // script file names.
4207 :
4208 0 : return scriptFileNameModified;
4209 : }
4210 :
4211 : bool docWrappersEnabled =
4212 357 : chromeReg->WrappersEnabled(aDocument->GetDocumentURI());
4213 :
4214 357 : bool uriWrappersEnabled = chromeReg->WrappersEnabled(aURI);
4215 :
4216 357 : nsIURI *docURI = aDocument->GetDocumentURI();
4217 :
4218 357 : if (docURI && docWrappersEnabled && !uriWrappersEnabled) {
4219 : // aURI is a script from a URL that doesn't get wrapper
4220 : // automation. aDocument is a chrome document that does get
4221 : // wrapper automation. Prepend the chrome document's URI
4222 : // followed by the string " -> " to the URI of the script we're
4223 : // loading here so that script in that URI gets the same wrapper
4224 : // automation that the chrome document expects.
4225 0 : nsAutoCString spec;
4226 0 : *aRv = docURI->GetSpec(spec);
4227 0 : if (NS_WARN_IF(NS_FAILED(*aRv))) {
4228 0 : return false;
4229 : }
4230 :
4231 0 : spec.AppendLiteral(" -> ");
4232 0 : spec.Append(aScriptURI);
4233 :
4234 0 : aScriptURI = spec;
4235 :
4236 0 : scriptFileNameModified = true;
4237 : }
4238 : }
4239 :
4240 375 : return scriptFileNameModified;
4241 : }
4242 :
4243 : // static
4244 : bool
4245 14 : nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
4246 : {
4247 14 : if (!aDocument) {
4248 0 : return false;
4249 : }
4250 :
4251 14 : if (aDocument->GetDisplayDocument()) {
4252 0 : return IsInChromeDocshell(aDocument->GetDisplayDocument());
4253 : }
4254 :
4255 28 : nsCOMPtr<nsIDocShellTreeItem> docShell = aDocument->GetDocShell();
4256 14 : if (!docShell) {
4257 0 : return false;
4258 : }
4259 :
4260 14 : return docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
4261 : }
4262 :
4263 : // static
4264 : nsIContentPolicy*
4265 204 : nsContentUtils::GetContentPolicy()
4266 : {
4267 204 : if (!sTriedToGetContentPolicy) {
4268 3 : CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
4269 : // It's OK to not have a content policy service
4270 3 : sTriedToGetContentPolicy = true;
4271 : }
4272 :
4273 204 : return sContentPolicyService;
4274 : }
4275 :
4276 : // static
4277 : bool
4278 6050 : nsContentUtils::IsEventAttributeName(nsIAtom* aName, int32_t aType)
4279 : {
4280 6050 : const char16_t* name = aName->GetUTF16String();
4281 6050 : if (name[0] != 'o' || name[1] != 'n')
4282 5494 : return false;
4283 :
4284 : EventNameMapping mapping;
4285 556 : return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
4286 : }
4287 :
4288 : // static
4289 : EventMessage
4290 707 : nsContentUtils::GetEventMessage(nsIAtom* aName)
4291 : {
4292 707 : if (aName) {
4293 : EventNameMapping mapping;
4294 707 : if (sAtomEventTable->Get(aName, &mapping)) {
4295 556 : return mapping.mMessage;
4296 : }
4297 : }
4298 :
4299 151 : return eUnidentifiedEvent;
4300 : }
4301 :
4302 : // static
4303 : mozilla::EventClassID
4304 133 : nsContentUtils::GetEventClassID(const nsAString& aName)
4305 : {
4306 : EventNameMapping mapping;
4307 133 : if (sStringEventTable->Get(aName, &mapping))
4308 118 : return mapping.mEventClassID;
4309 :
4310 15 : return eBasicEventClass;
4311 : }
4312 :
4313 : nsIAtom*
4314 425 : nsContentUtils::GetEventMessageAndAtom(const nsAString& aName,
4315 : mozilla::EventClassID aEventClassID,
4316 : EventMessage* aEventMessage)
4317 : {
4318 : EventNameMapping mapping;
4319 425 : if (sStringEventTable->Get(aName, &mapping)) {
4320 274 : *aEventMessage =
4321 274 : mapping.mEventClassID == aEventClassID ? mapping.mMessage :
4322 : eUnidentifiedEvent;
4323 274 : return mapping.mAtom;
4324 : }
4325 :
4326 : // If we have cached lots of user defined event names, clear some of them.
4327 151 : if (sUserDefinedEvents->Count() > 127) {
4328 0 : while (sUserDefinedEvents->Count() > 64) {
4329 0 : nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
4330 0 : sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
4331 0 : sUserDefinedEvents->RemoveObjectAt(0);
4332 : }
4333 : }
4334 :
4335 151 : *aEventMessage = eUnidentifiedEvent;
4336 : nsCOMPtr<nsIAtom> atom =
4337 302 : NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
4338 151 : sUserDefinedEvents->AppendObject(atom);
4339 151 : mapping.mAtom = atom;
4340 151 : mapping.mMessage = eUnidentifiedEvent;
4341 151 : mapping.mType = EventNameType_None;
4342 151 : mapping.mEventClassID = eBasicEventClass;
4343 : // This is a slow hashtable call, but at least we cache the result for the
4344 : // following calls. Because GetEventMessageAndAtomForListener utilizes
4345 : // sStringEventTable, it needs to know in which cases sStringEventTable
4346 : // doesn't contain the information it needs so that it can use
4347 : // sAtomEventTable instead.
4348 151 : mapping.mMaybeSpecialSVGorSMILEvent =
4349 151 : GetEventMessage(atom) != eUnidentifiedEvent;
4350 151 : sStringEventTable->Put(aName, mapping);
4351 151 : return mapping.mAtom;
4352 : }
4353 :
4354 : // static
4355 : EventMessage
4356 1852 : nsContentUtils::GetEventMessageAndAtomForListener(const nsAString& aName,
4357 : nsIAtom** aOnName)
4358 : {
4359 : // Because of SVG/SMIL sStringEventTable contains a subset of the event names
4360 : // comparing to the sAtomEventTable. However, usually sStringEventTable
4361 : // contains the information we need, so in order to reduce hashtable
4362 : // lookups, start from it.
4363 : EventNameMapping mapping;
4364 1852 : EventMessage msg = eUnidentifiedEvent;
4365 3704 : nsCOMPtr<nsIAtom> atom;
4366 1852 : if (sStringEventTable->Get(aName, &mapping)) {
4367 1720 : if (mapping.mMaybeSpecialSVGorSMILEvent) {
4368 : // Try the atom version so that we should get the right message for
4369 : // SVG/SMIL.
4370 0 : atom = NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
4371 0 : msg = GetEventMessage(atom);
4372 : } else {
4373 1720 : atom = mapping.mAtom;
4374 1720 : msg = mapping.mMessage;
4375 : }
4376 1720 : atom.forget(aOnName);
4377 1720 : return msg;
4378 : }
4379 :
4380 : // GetEventMessageAndAtom will cache the event type for the future usage...
4381 132 : GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
4382 :
4383 : // ...and then call this method recursively to get the message and atom from
4384 : // now updated sStringEventTable.
4385 132 : return GetEventMessageAndAtomForListener(aName, aOnName);
4386 : }
4387 :
4388 : static
4389 123 : nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
4390 : const nsAString& aEventName,
4391 : bool aCanBubble, bool aCancelable,
4392 : bool aTrusted, nsIDOMEvent** aEvent,
4393 : EventTarget** aTargetOut)
4394 : {
4395 246 : nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
4396 246 : nsCOMPtr<EventTarget> target(do_QueryInterface(aTarget));
4397 123 : NS_ENSURE_TRUE(domDoc && target, NS_ERROR_INVALID_ARG);
4398 :
4399 246 : nsCOMPtr<nsIDOMEvent> event;
4400 : nsresult rv =
4401 123 : domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
4402 123 : NS_ENSURE_SUCCESS(rv, rv);
4403 :
4404 123 : event->InitEvent(aEventName, aCanBubble, aCancelable);
4405 123 : event->SetTrusted(aTrusted);
4406 :
4407 123 : rv = event->SetTarget(target);
4408 123 : NS_ENSURE_SUCCESS(rv, rv);
4409 :
4410 123 : event.forget(aEvent);
4411 123 : target.forget(aTargetOut);
4412 123 : return NS_OK;
4413 : }
4414 :
4415 : // static
4416 : nsresult
4417 52 : nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
4418 : const nsAString& aEventName,
4419 : bool aCanBubble, bool aCancelable,
4420 : bool* aDefaultAction)
4421 : {
4422 52 : return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4423 52 : true, aDefaultAction);
4424 : }
4425 :
4426 : // static
4427 : nsresult
4428 0 : nsContentUtils::DispatchUntrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
4429 : const nsAString& aEventName,
4430 : bool aCanBubble, bool aCancelable,
4431 : bool* aDefaultAction)
4432 : {
4433 0 : return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4434 0 : false, aDefaultAction);
4435 : }
4436 :
4437 : // static
4438 : nsresult
4439 56 : nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
4440 : const nsAString& aEventName,
4441 : bool aCanBubble, bool aCancelable,
4442 : bool aTrusted, bool* aDefaultAction,
4443 : bool aOnlyChromeDispatch)
4444 : {
4445 112 : nsCOMPtr<nsIDOMEvent> event;
4446 112 : nsCOMPtr<EventTarget> target;
4447 112 : nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
4448 112 : aCancelable, aTrusted, getter_AddRefs(event),
4449 168 : getter_AddRefs(target));
4450 56 : NS_ENSURE_SUCCESS(rv, rv);
4451 56 : event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
4452 :
4453 : bool dummy;
4454 56 : return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
4455 : }
4456 :
4457 : // static
4458 : nsresult
4459 4 : nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
4460 : WidgetEvent& aEvent,
4461 : EventMessage aEventMessage,
4462 : bool aCanBubble, bool aCancelable,
4463 : bool aTrusted, bool *aDefaultAction,
4464 : bool aOnlyChromeDispatch)
4465 : {
4466 4 : MOZ_ASSERT_IF(aOnlyChromeDispatch, aTrusted);
4467 :
4468 8 : nsCOMPtr<EventTarget> target(do_QueryInterface(aTarget));
4469 :
4470 4 : aEvent.mTime = PR_Now();
4471 :
4472 4 : aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
4473 4 : aEvent.SetDefaultComposed();
4474 4 : aEvent.SetDefaultComposedInNativeAnonymousContent();
4475 :
4476 4 : aEvent.mFlags.mBubbles = aCanBubble;
4477 4 : aEvent.mFlags.mCancelable = aCancelable;
4478 4 : aEvent.mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
4479 :
4480 4 : aEvent.mTarget = target;
4481 :
4482 4 : nsEventStatus status = nsEventStatus_eIgnore;
4483 : nsresult rv = EventDispatcher::DispatchDOMEvent(target, &aEvent, nullptr,
4484 4 : nullptr, &status);
4485 4 : if (aDefaultAction) {
4486 0 : *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
4487 : }
4488 8 : return rv;
4489 : }
4490 :
4491 : nsresult
4492 67 : nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
4493 : nsISupports *aTarget,
4494 : const nsAString& aEventName,
4495 : bool aCanBubble, bool aCancelable,
4496 : bool* aDefaultAction)
4497 : {
4498 :
4499 134 : nsCOMPtr<nsIDOMEvent> event;
4500 134 : nsCOMPtr<EventTarget> target;
4501 134 : nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
4502 134 : aCancelable, true, getter_AddRefs(event),
4503 201 : getter_AddRefs(target));
4504 67 : NS_ENSURE_SUCCESS(rv, rv);
4505 :
4506 67 : NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
4507 67 : if (!aDoc->GetWindow())
4508 44 : return NS_ERROR_INVALID_ARG;
4509 :
4510 23 : EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
4511 23 : if (!piTarget)
4512 0 : return NS_ERROR_INVALID_ARG;
4513 :
4514 23 : nsEventStatus status = nsEventStatus_eIgnore;
4515 23 : rv = piTarget->DispatchDOMEvent(nullptr, event, nullptr, &status);
4516 23 : if (aDefaultAction) {
4517 0 : *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
4518 : }
4519 23 : return rv;
4520 : }
4521 :
4522 : /* static */
4523 : nsresult
4524 0 : nsContentUtils::DispatchFocusChromeEvent(nsPIDOMWindowOuter* aWindow)
4525 : {
4526 0 : MOZ_ASSERT(aWindow);
4527 :
4528 0 : nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
4529 0 : if (!doc) {
4530 0 : return NS_ERROR_FAILURE;
4531 : }
4532 :
4533 0 : return DispatchChromeEvent(doc, aWindow,
4534 0 : NS_LITERAL_STRING("DOMWindowFocus"),
4535 0 : true, true);
4536 : }
4537 :
4538 : nsresult
4539 4 : nsContentUtils::DispatchEventOnlyToChrome(nsIDocument* aDoc,
4540 : nsISupports* aTarget,
4541 : const nsAString& aEventName,
4542 : bool aCanBubble, bool aCancelable,
4543 : bool* aDefaultAction)
4544 : {
4545 4 : return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
4546 4 : true, aDefaultAction, true);
4547 : }
4548 :
4549 : /* static */
4550 : Element*
4551 0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId)
4552 : {
4553 0 : for (nsIContent* cur = aContent;
4554 0 : cur;
4555 0 : cur = cur->GetNextNode(aContent)) {
4556 0 : if (aId == cur->GetID()) {
4557 0 : return cur->AsElement();
4558 : }
4559 : }
4560 :
4561 0 : return nullptr;
4562 : }
4563 :
4564 : /* static */
4565 : Element *
4566 0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
4567 : {
4568 0 : NS_PRECONDITION(!aId.IsEmpty(), "Will match random elements");
4569 :
4570 : // ID attrs are generally stored as atoms, so just atomize this up front
4571 0 : nsCOMPtr<nsIAtom> id(NS_Atomize(aId));
4572 0 : if (!id) {
4573 : // OOM, so just bail
4574 0 : return nullptr;
4575 : }
4576 :
4577 0 : return MatchElementId(aContent, id);
4578 : }
4579 :
4580 : /* static */
4581 : nsIDocument*
4582 0 : nsContentUtils::GetSubdocumentWithOuterWindowId(nsIDocument *aDocument,
4583 : uint64_t aOuterWindowId)
4584 : {
4585 0 : if (!aDocument || !aOuterWindowId) {
4586 0 : return nullptr;
4587 : }
4588 :
4589 0 : RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(aOuterWindowId);
4590 0 : if (!window) {
4591 0 : return nullptr;
4592 : }
4593 :
4594 0 : nsCOMPtr<nsPIDOMWindowOuter> outerWindow = window->AsOuter();
4595 0 : nsCOMPtr<nsIDocument> foundDoc = outerWindow->GetDoc();
4596 0 : if (nsContentUtils::ContentIsCrossDocDescendantOf(foundDoc, aDocument)) {
4597 : // Note that ContentIsCrossDocDescendantOf will return true if
4598 : // foundDoc == aDocument.
4599 0 : return foundDoc;
4600 : }
4601 :
4602 0 : return nullptr;
4603 : }
4604 :
4605 : /* static */
4606 : void
4607 8 : nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver)
4608 : {
4609 : nsCOMPtr<nsIObserverService> observerService =
4610 16 : mozilla::services::GetObserverService();
4611 8 : if (observerService) {
4612 8 : observerService->AddObserver(aObserver,
4613 : NS_XPCOM_SHUTDOWN_OBSERVER_ID,
4614 8 : false);
4615 : }
4616 8 : }
4617 :
4618 : /* static */
4619 : void
4620 0 : nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver)
4621 : {
4622 : nsCOMPtr<nsIObserverService> observerService =
4623 0 : mozilla::services::GetObserverService();
4624 0 : if (observerService) {
4625 0 : observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
4626 : }
4627 0 : }
4628 :
4629 : /* static */
4630 : bool
4631 94 : nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, int32_t aNameSpaceID,
4632 : nsIAtom* aName)
4633 : {
4634 : static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nullptr};
4635 94 : return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
4636 94 : == nsIContent::ATTR_VALUE_NO_MATCH;
4637 : }
4638 :
4639 : /* static */
4640 : bool
4641 836 : nsContentUtils::HasMutationListeners(nsINode* aNode,
4642 : uint32_t aType,
4643 : nsINode* aTargetForSubtreeModified)
4644 : {
4645 836 : nsIDocument* doc = aNode->OwnerDoc();
4646 :
4647 : // global object will be null for documents that don't have windows.
4648 836 : nsPIDOMWindowInner* window = doc->GetInnerWindow();
4649 : // This relies on EventListenerManager::AddEventListener, which sets
4650 : // all mutation bits when there is a listener for DOMSubtreeModified event.
4651 836 : if (window && !window->HasMutationListeners(aType)) {
4652 748 : return false;
4653 : }
4654 :
4655 176 : if (aNode->IsNodeOfType(nsINode::eCONTENT) &&
4656 88 : static_cast<nsIContent*>(aNode)->ChromeOnlyAccess()) {
4657 0 : return false;
4658 : }
4659 :
4660 88 : doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
4661 :
4662 : // If we have a window, we can check it for mutation listeners now.
4663 88 : if (aNode->IsInUncomposedDoc()) {
4664 92 : nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
4665 46 : if (piTarget) {
4666 0 : EventListenerManager* manager = piTarget->GetExistingListenerManager();
4667 0 : if (manager && manager->HasMutationListeners()) {
4668 0 : return true;
4669 : }
4670 : }
4671 : }
4672 :
4673 : // If we have a window, we know a mutation listener is registered, but it
4674 : // might not be in our chain. If we don't have a window, we might have a
4675 : // mutation listener. Check quickly to see.
4676 356 : while (aNode) {
4677 134 : EventListenerManager* manager = aNode->GetExistingListenerManager();
4678 134 : if (manager && manager->HasMutationListeners()) {
4679 0 : return true;
4680 : }
4681 :
4682 134 : if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
4683 88 : nsIContent* content = static_cast<nsIContent*>(aNode);
4684 88 : nsIContent* insertionParent = content->GetXBLInsertionParent();
4685 88 : if (insertionParent) {
4686 0 : aNode = insertionParent;
4687 0 : continue;
4688 : }
4689 : }
4690 134 : aNode = aNode->GetParentNode();
4691 : }
4692 :
4693 88 : return false;
4694 : }
4695 :
4696 : /* static */
4697 : bool
4698 9 : nsContentUtils::HasMutationListeners(nsIDocument* aDocument,
4699 : uint32_t aType)
4700 : {
4701 9 : nsPIDOMWindowInner* window = aDocument ?
4702 9 : aDocument->GetInnerWindow() : nullptr;
4703 :
4704 : // This relies on EventListenerManager::AddEventListener, which sets
4705 : // all mutation bits when there is a listener for DOMSubtreeModified event.
4706 9 : return !window || window->HasMutationListeners(aType);
4707 : }
4708 :
4709 : void
4710 6 : nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
4711 : nsIDocument* aOwnerDoc)
4712 : {
4713 6 : NS_PRECONDITION(aChild, "Missing child");
4714 6 : NS_PRECONDITION(aChild->GetParentNode() == aParent, "Wrong parent");
4715 6 : NS_PRECONDITION(aChild->OwnerDoc() == aOwnerDoc, "Wrong owner-doc");
4716 :
4717 : // Having an explicit check here since it's an easy mistake to fall into,
4718 : // and there might be existing code with problems. We'd rather be safe
4719 : // than fire DOMNodeRemoved in all corner cases. We also rely on it for
4720 : // nsAutoScriptBlockerSuppressNodeRemoved.
4721 6 : if (!IsSafeToRunScript()) {
4722 : // This checks that IsSafeToRunScript is true since we don't want to fire
4723 : // events when that is false. We can't rely on EventDispatcher to assert
4724 : // this in this situation since most of the time there are no mutation
4725 : // event listeners, in which case we won't even attempt to dispatch events.
4726 : // However this also allows for two exceptions. First off, we don't assert
4727 : // if the mutation happens to native anonymous content since we never fire
4728 : // mutation events on such content anyway.
4729 : // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
4730 : // that is a know case when we'd normally fire a mutation event, but can't
4731 : // make that safe and so we suppress it at this time. Ideally this should
4732 : // go away eventually.
4733 1 : if (!(aChild->IsContent() && aChild->AsContent()->IsInNativeAnonymousSubtree()) &&
4734 0 : !sDOMNodeRemovedSuppressCount) {
4735 0 : NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe");
4736 0 : WarnScriptWasIgnored(aOwnerDoc);
4737 : }
4738 1 : return;
4739 : }
4740 :
4741 5 : if (HasMutationListeners(aChild,
4742 : NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
4743 0 : InternalMutationEvent mutation(true, eLegacyNodeRemoved);
4744 0 : mutation.mRelatedNode = do_QueryInterface(aParent);
4745 :
4746 0 : mozAutoSubtreeModified subtree(aOwnerDoc, aParent);
4747 0 : EventDispatcher::Dispatch(aChild, nullptr, &mutation);
4748 : }
4749 : }
4750 :
4751 : void
4752 0 : nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments()
4753 : {
4754 0 : if (!sEventListenerManagersHash) {
4755 0 : return;
4756 : }
4757 :
4758 0 : for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
4759 0 : auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
4760 0 : nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
4761 0 : if (n && n->IsInUncomposedDoc() &&
4762 0 : nsCCUncollectableMarker::InGeneration(n->OwnerDoc()->GetMarkedCCGeneration())) {
4763 0 : entry->mListenerManager->MarkForCC();
4764 : }
4765 : }
4766 : }
4767 :
4768 : /* static */
4769 : void
4770 178 : nsContentUtils::TraverseListenerManager(nsINode *aNode,
4771 : nsCycleCollectionTraversalCallback &cb)
4772 : {
4773 178 : if (!sEventListenerManagersHash) {
4774 : // We're already shut down, just return.
4775 0 : return;
4776 : }
4777 :
4778 : auto entry = static_cast<EventListenerManagerMapEntry*>
4779 178 : (sEventListenerManagersHash->Search(aNode));
4780 178 : if (entry) {
4781 178 : CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
4782 178 : "[via hash] mListenerManager");
4783 : }
4784 : }
4785 :
4786 : EventListenerManager*
4787 1209 : nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
4788 : {
4789 1209 : if (!sEventListenerManagersHash) {
4790 : // We're already shut down, don't bother creating an event listener
4791 : // manager.
4792 :
4793 0 : return nullptr;
4794 : }
4795 :
4796 : auto entry =
4797 : static_cast<EventListenerManagerMapEntry*>
4798 1209 : (sEventListenerManagersHash->Add(aNode, fallible));
4799 :
4800 1209 : if (!entry) {
4801 0 : return nullptr;
4802 : }
4803 :
4804 1209 : if (!entry->mListenerManager) {
4805 556 : entry->mListenerManager = new EventListenerManager(aNode);
4806 :
4807 556 : aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
4808 : }
4809 :
4810 1209 : return entry->mListenerManager;
4811 : }
4812 :
4813 : EventListenerManager*
4814 1185 : nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode)
4815 : {
4816 1185 : if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
4817 716 : return nullptr;
4818 : }
4819 :
4820 469 : if (!sEventListenerManagersHash) {
4821 : // We're already shut down, don't bother creating an event listener
4822 : // manager.
4823 :
4824 0 : return nullptr;
4825 : }
4826 :
4827 : auto entry = static_cast<EventListenerManagerMapEntry*>
4828 469 : (sEventListenerManagersHash->Search(aNode));
4829 469 : if (entry) {
4830 469 : return entry->mListenerManager;
4831 : }
4832 :
4833 0 : return nullptr;
4834 : }
4835 :
4836 : /* static */
4837 : void
4838 3 : nsContentUtils::RemoveListenerManager(nsINode *aNode)
4839 : {
4840 3 : if (sEventListenerManagersHash) {
4841 : auto entry = static_cast<EventListenerManagerMapEntry*>
4842 3 : (sEventListenerManagersHash->Search(aNode));
4843 3 : if (entry) {
4844 6 : RefPtr<EventListenerManager> listenerManager;
4845 3 : listenerManager.swap(entry->mListenerManager);
4846 : // Remove the entry and *then* do operations that could cause further
4847 : // modification of sEventListenerManagersHash. See bug 334177.
4848 3 : sEventListenerManagersHash->RawRemove(entry);
4849 3 : if (listenerManager) {
4850 3 : listenerManager->Disconnect();
4851 : }
4852 : }
4853 : }
4854 3 : }
4855 :
4856 : /* static */
4857 : bool
4858 33 : nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
4859 : int32_t aNamespaceID)
4860 : {
4861 33 : if (aNamespaceID == kNameSpaceID_Unknown) {
4862 0 : return false;
4863 : }
4864 :
4865 33 : if (!aPrefix) {
4866 : // If the prefix is null, then either the QName must be xmlns or the
4867 : // namespace must not be XMLNS.
4868 33 : return (aLocalName == nsGkAtoms::xmlns) ==
4869 33 : (aNamespaceID == kNameSpaceID_XMLNS);
4870 : }
4871 :
4872 : // If the prefix is non-null then the namespace must not be null.
4873 0 : if (aNamespaceID == kNameSpaceID_None) {
4874 0 : return false;
4875 : }
4876 :
4877 : // If the namespace is the XMLNS namespace then the prefix must be xmlns,
4878 : // but the localname must not be xmlns.
4879 0 : if (aNamespaceID == kNameSpaceID_XMLNS) {
4880 0 : return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
4881 : }
4882 :
4883 : // If the namespace is not the XMLNS namespace then the prefix must not be
4884 : // xmlns.
4885 : // If the namespace is the XML namespace then the prefix can be anything.
4886 : // If the namespace is not the XML namespace then the prefix must not be xml.
4887 0 : return aPrefix != nsGkAtoms::xmlns &&
4888 0 : (aNamespaceID == kNameSpaceID_XML || aPrefix != nsGkAtoms::xml);
4889 : }
4890 :
4891 : /* static */
4892 : nsresult
4893 0 : nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
4894 : const nsAString& aFragment,
4895 : bool aPreventScriptExecution,
4896 : nsIDOMDocumentFragment** aReturn)
4897 : {
4898 0 : ErrorResult rv;
4899 0 : *aReturn = CreateContextualFragment(aContextNode, aFragment,
4900 0 : aPreventScriptExecution, rv).take();
4901 0 : return rv.StealNSResult();
4902 : }
4903 :
4904 : already_AddRefed<DocumentFragment>
4905 0 : nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
4906 : const nsAString& aFragment,
4907 : bool aPreventScriptExecution,
4908 : ErrorResult& aRv)
4909 : {
4910 0 : if (!aContextNode) {
4911 0 : aRv.Throw(NS_ERROR_INVALID_ARG);
4912 0 : return nullptr;
4913 : }
4914 :
4915 : // If we don't have a document here, we can't get the right security context
4916 : // for compiling event handlers... so just bail out.
4917 0 : nsCOMPtr<nsIDocument> document = aContextNode->OwnerDoc();
4918 0 : bool isHTML = document->IsHTMLDocument();
4919 : #ifdef DEBUG
4920 0 : nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
4921 0 : NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
4922 : #endif
4923 :
4924 0 : if (isHTML) {
4925 : RefPtr<DocumentFragment> frag =
4926 0 : new DocumentFragment(document->NodeInfoManager());
4927 :
4928 0 : nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
4929 0 : if (contextAsContent && !contextAsContent->IsElement()) {
4930 0 : contextAsContent = contextAsContent->GetParent();
4931 0 : if (contextAsContent && !contextAsContent->IsElement()) {
4932 : // can this even happen?
4933 0 : contextAsContent = nullptr;
4934 : }
4935 : }
4936 :
4937 0 : if (contextAsContent && !contextAsContent->IsHTMLElement(nsGkAtoms::html)) {
4938 0 : aRv = ParseFragmentHTML(aFragment, frag,
4939 0 : contextAsContent->NodeInfo()->NameAtom(),
4940 : contextAsContent->GetNameSpaceID(),
4941 0 : (document->GetCompatibilityMode() ==
4942 : eCompatibility_NavQuirks),
4943 0 : aPreventScriptExecution);
4944 : } else {
4945 0 : aRv = ParseFragmentHTML(aFragment, frag,
4946 : nsGkAtoms::body,
4947 : kNameSpaceID_XHTML,
4948 0 : (document->GetCompatibilityMode() ==
4949 : eCompatibility_NavQuirks),
4950 0 : aPreventScriptExecution);
4951 : }
4952 :
4953 0 : return frag.forget();
4954 : }
4955 :
4956 0 : AutoTArray<nsString, 32> tagStack;
4957 0 : nsAutoString uriStr, nameStr;
4958 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
4959 : // just in case we have a text node
4960 0 : if (content && !content->IsElement())
4961 0 : content = content->GetParent();
4962 :
4963 0 : while (content && content->IsElement()) {
4964 0 : nsString& tagName = *tagStack.AppendElement();
4965 0 : tagName = content->NodeInfo()->QualifiedName();
4966 :
4967 : // see if we need to add xmlns declarations
4968 0 : uint32_t count = content->GetAttrCount();
4969 0 : bool setDefaultNamespace = false;
4970 0 : if (count > 0) {
4971 : uint32_t index;
4972 :
4973 0 : for (index = 0; index < count; index++) {
4974 0 : const BorrowedAttrInfo info = content->GetAttrInfoAt(index);
4975 0 : const nsAttrName* name = info.mName;
4976 0 : if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
4977 0 : info.mValue->ToString(uriStr);
4978 :
4979 : // really want something like nsXMLContentSerializer::SerializeAttr
4980 0 : tagName.AppendLiteral(" xmlns"); // space important
4981 0 : if (name->GetPrefix()) {
4982 0 : tagName.Append(char16_t(':'));
4983 0 : name->LocalName()->ToString(nameStr);
4984 0 : tagName.Append(nameStr);
4985 : } else {
4986 0 : setDefaultNamespace = true;
4987 : }
4988 0 : tagName.AppendLiteral(R"(=")");
4989 0 : tagName.Append(uriStr);
4990 0 : tagName.Append('"');
4991 : }
4992 : }
4993 : }
4994 :
4995 0 : if (!setDefaultNamespace) {
4996 0 : mozilla::dom::NodeInfo* info = content->NodeInfo();
4997 0 : if (!info->GetPrefixAtom() &&
4998 0 : info->NamespaceID() != kNameSpaceID_None) {
4999 : // We have no namespace prefix, but have a namespace ID. Push
5000 : // default namespace attr in, so that our kids will be in our
5001 : // namespace.
5002 0 : info->GetNamespaceURI(uriStr);
5003 0 : tagName.AppendLiteral(R"( xmlns=")");
5004 0 : tagName.Append(uriStr);
5005 0 : tagName.Append('"');
5006 : }
5007 : }
5008 :
5009 0 : content = content->GetParent();
5010 : }
5011 :
5012 0 : nsCOMPtr<nsIDOMDocumentFragment> frag;
5013 0 : aRv = ParseFragmentXML(aFragment, document, tagStack,
5014 0 : aPreventScriptExecution, getter_AddRefs(frag));
5015 0 : return frag.forget().downcast<DocumentFragment>();
5016 : }
5017 :
5018 : /* static */
5019 : void
5020 0 : nsContentUtils::DropFragmentParsers()
5021 : {
5022 0 : NS_IF_RELEASE(sHTMLFragmentParser);
5023 0 : NS_IF_RELEASE(sXMLFragmentParser);
5024 0 : NS_IF_RELEASE(sXMLFragmentSink);
5025 0 : }
5026 :
5027 : /* static */
5028 : void
5029 0 : nsContentUtils::XPCOMShutdown()
5030 : {
5031 0 : nsContentUtils::DropFragmentParsers();
5032 0 : }
5033 :
5034 : /* static */
5035 : nsresult
5036 0 : nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
5037 : nsIContent* aTargetNode,
5038 : nsIAtom* aContextLocalName,
5039 : int32_t aContextNamespace,
5040 : bool aQuirks,
5041 : bool aPreventScriptExecution)
5042 : {
5043 0 : AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
5044 :
5045 0 : if (nsContentUtils::sFragmentParsingActive) {
5046 0 : NS_NOTREACHED("Re-entrant fragment parsing attempted.");
5047 0 : return NS_ERROR_DOM_INVALID_STATE_ERR;
5048 : }
5049 0 : mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5050 0 : nsContentUtils::sFragmentParsingActive = true;
5051 0 : if (!sHTMLFragmentParser) {
5052 0 : NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
5053 : // Now sHTMLFragmentParser owns the object
5054 : }
5055 : nsresult rv =
5056 0 : sHTMLFragmentParser->ParseFragment(aSourceBuffer,
5057 : aTargetNode,
5058 : aContextLocalName,
5059 : aContextNamespace,
5060 : aQuirks,
5061 0 : aPreventScriptExecution);
5062 0 : return rv;
5063 : }
5064 :
5065 : /* static */
5066 : nsresult
5067 0 : nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
5068 : nsIDocument* aTargetDocument,
5069 : bool aScriptingEnabledForNoscriptParsing)
5070 : {
5071 0 : AutoTimelineMarker m(aTargetDocument->GetDocShell(), "Parse HTML");
5072 :
5073 0 : if (nsContentUtils::sFragmentParsingActive) {
5074 0 : NS_NOTREACHED("Re-entrant fragment parsing attempted.");
5075 0 : return NS_ERROR_DOM_INVALID_STATE_ERR;
5076 : }
5077 0 : mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5078 0 : nsContentUtils::sFragmentParsingActive = true;
5079 0 : if (!sHTMLFragmentParser) {
5080 0 : NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
5081 : // Now sHTMLFragmentParser owns the object
5082 : }
5083 : nsresult rv =
5084 0 : sHTMLFragmentParser->ParseDocument(aSourceBuffer,
5085 : aTargetDocument,
5086 0 : aScriptingEnabledForNoscriptParsing);
5087 0 : return rv;
5088 : }
5089 :
5090 : /* static */
5091 : nsresult
5092 0 : nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
5093 : nsIDocument* aDocument,
5094 : nsTArray<nsString>& aTagStack,
5095 : bool aPreventScriptExecution,
5096 : nsIDOMDocumentFragment** aReturn)
5097 : {
5098 0 : AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
5099 :
5100 0 : if (nsContentUtils::sFragmentParsingActive) {
5101 0 : NS_NOTREACHED("Re-entrant fragment parsing attempted.");
5102 0 : return NS_ERROR_DOM_INVALID_STATE_ERR;
5103 : }
5104 0 : mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
5105 0 : nsContentUtils::sFragmentParsingActive = true;
5106 0 : if (!sXMLFragmentParser) {
5107 0 : nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID);
5108 0 : parser.forget(&sXMLFragmentParser);
5109 : // sXMLFragmentParser now owns the parser
5110 : }
5111 0 : if (!sXMLFragmentSink) {
5112 0 : NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
5113 : // sXMLFragmentSink now owns the sink
5114 : }
5115 0 : nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
5116 0 : MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!");
5117 0 : sXMLFragmentParser->SetContentSink(contentsink);
5118 :
5119 0 : sXMLFragmentSink->SetTargetDocument(aDocument);
5120 0 : sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
5121 :
5122 : nsresult rv =
5123 0 : sXMLFragmentParser->ParseFragment(aSourceBuffer,
5124 0 : aTagStack);
5125 0 : if (NS_FAILED(rv)) {
5126 : // Drop the fragment parser and sink that might be in an inconsistent state
5127 0 : NS_IF_RELEASE(sXMLFragmentParser);
5128 0 : NS_IF_RELEASE(sXMLFragmentSink);
5129 0 : return rv;
5130 : }
5131 :
5132 0 : rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
5133 :
5134 0 : sXMLFragmentParser->Reset();
5135 :
5136 0 : return rv;
5137 : }
5138 :
5139 : /* static */
5140 : nsresult
5141 0 : nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
5142 : nsAString& aResultBuffer,
5143 : uint32_t aFlags,
5144 : uint32_t aWrapCol)
5145 : {
5146 0 : nsCOMPtr<nsIURI> uri;
5147 0 : NS_NewURI(getter_AddRefs(uri), "about:blank");
5148 0 : nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
5149 0 : nsCOMPtr<nsIDOMDocument> domDocument;
5150 0 : nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
5151 0 : EmptyString(),
5152 0 : EmptyString(),
5153 : nullptr,
5154 : uri,
5155 : uri,
5156 : principal,
5157 : true,
5158 : nullptr,
5159 0 : DocumentFlavorHTML);
5160 0 : NS_ENSURE_SUCCESS(rv, rv);
5161 :
5162 0 : nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
5163 0 : rv = nsContentUtils::ParseDocumentHTML(aSourceBuffer, document,
5164 0 : !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
5165 0 : NS_ENSURE_SUCCESS(rv, rv);
5166 :
5167 0 : nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(
5168 0 : "@mozilla.org/layout/documentEncoder;1?type=text/plain");
5169 :
5170 0 : rv = encoder->Init(domDocument, NS_LITERAL_STRING("text/plain"), aFlags);
5171 0 : NS_ENSURE_SUCCESS(rv, rv);
5172 :
5173 0 : encoder->SetWrapColumn(aWrapCol);
5174 :
5175 0 : return encoder->EncodeToString(aResultBuffer);
5176 : }
5177 :
5178 : /* static */
5179 : nsresult
5180 2 : nsContentUtils::SetNodeTextContent(nsIContent* aContent,
5181 : const nsAString& aValue,
5182 : bool aTryReuse)
5183 : {
5184 : // Fire DOMNodeRemoved mutation events before we do anything else.
5185 4 : nsCOMPtr<nsIContent> owningContent;
5186 :
5187 : // Batch possible DOMSubtreeModified events.
5188 4 : mozAutoSubtreeModified subtree(nullptr, nullptr);
5189 :
5190 : // Scope firing mutation events so that we don't carry any state that
5191 : // might be stale
5192 : {
5193 : // We're relying on mozAutoSubtreeModified to keep a strong reference if
5194 : // needed.
5195 2 : nsIDocument* doc = aContent->OwnerDoc();
5196 :
5197 : // Optimize the common case of there being no observers
5198 2 : if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
5199 0 : subtree.UpdateTarget(doc, nullptr);
5200 0 : owningContent = aContent;
5201 0 : nsCOMPtr<nsINode> child;
5202 0 : bool skipFirst = aTryReuse;
5203 0 : for (child = aContent->GetFirstChild();
5204 0 : child && child->GetParentNode() == aContent;
5205 0 : child = child->GetNextSibling()) {
5206 0 : if (skipFirst && child->IsNodeOfType(nsINode::eTEXT)) {
5207 0 : skipFirst = false;
5208 0 : continue;
5209 : }
5210 0 : nsContentUtils::MaybeFireNodeRemoved(child, aContent, doc);
5211 : }
5212 : }
5213 : }
5214 :
5215 : // Might as well stick a batch around this since we're performing several
5216 : // mutations.
5217 : mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(),
5218 4 : UPDATE_CONTENT_MODEL, true);
5219 4 : nsAutoMutationBatch mb;
5220 :
5221 2 : uint32_t childCount = aContent->GetChildCount();
5222 :
5223 2 : if (aTryReuse && !aValue.IsEmpty()) {
5224 0 : uint32_t removeIndex = 0;
5225 :
5226 0 : for (uint32_t i = 0; i < childCount; ++i) {
5227 0 : nsIContent* child = aContent->GetChildAt(removeIndex);
5228 0 : if (removeIndex == 0 && child && child->IsNodeOfType(nsINode::eTEXT)) {
5229 0 : nsresult rv = child->SetText(aValue, true);
5230 0 : NS_ENSURE_SUCCESS(rv, rv);
5231 :
5232 0 : removeIndex = 1;
5233 : }
5234 : else {
5235 0 : aContent->RemoveChildAt(removeIndex, true);
5236 : }
5237 : }
5238 :
5239 0 : if (removeIndex == 1) {
5240 0 : return NS_OK;
5241 : }
5242 : }
5243 : else {
5244 2 : mb.Init(aContent, true, false);
5245 4 : for (uint32_t i = 0; i < childCount; ++i) {
5246 2 : aContent->RemoveChildAt(0, true);
5247 : }
5248 : }
5249 2 : mb.RemovalDone();
5250 :
5251 2 : if (aValue.IsEmpty()) {
5252 0 : return NS_OK;
5253 : }
5254 :
5255 : RefPtr<nsTextNode> textContent =
5256 6 : new nsTextNode(aContent->NodeInfo()->NodeInfoManager());
5257 :
5258 2 : textContent->SetText(aValue, true);
5259 :
5260 2 : nsresult rv = aContent->AppendChildTo(textContent, true);
5261 2 : mb.NodesAdded();
5262 2 : return rv;
5263 : }
5264 :
5265 : static bool
5266 2 : AppendNodeTextContentsRecurse(nsINode* aNode, nsAString& aResult,
5267 : const fallible_t& aFallible)
5268 : {
5269 3 : for (nsIContent* child = aNode->GetFirstChild();
5270 3 : child;
5271 1 : child = child->GetNextSibling()) {
5272 1 : if (child->IsElement()) {
5273 : bool ok = AppendNodeTextContentsRecurse(child, aResult,
5274 0 : aFallible);
5275 0 : if (!ok) {
5276 0 : return false;
5277 : }
5278 : }
5279 1 : else if (child->IsNodeOfType(nsINode::eTEXT)) {
5280 1 : bool ok = child->AppendTextTo(aResult, aFallible);
5281 1 : if (!ok) {
5282 0 : return false;
5283 : }
5284 : }
5285 : }
5286 :
5287 2 : return true;
5288 : }
5289 :
5290 : /* static */
5291 : bool
5292 9 : nsContentUtils::AppendNodeTextContent(nsINode* aNode, bool aDeep,
5293 : nsAString& aResult,
5294 : const fallible_t& aFallible)
5295 : {
5296 9 : if (aNode->IsNodeOfType(nsINode::eTEXT)) {
5297 : return static_cast<nsIContent*>(aNode)->AppendTextTo(aResult,
5298 0 : aFallible);
5299 : }
5300 9 : if (aDeep) {
5301 2 : return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
5302 : }
5303 :
5304 13 : for (nsIContent* child = aNode->GetFirstChild();
5305 13 : child;
5306 6 : child = child->GetNextSibling()) {
5307 6 : if (child->IsNodeOfType(nsINode::eTEXT)) {
5308 6 : bool ok = child->AppendTextTo(aResult, fallible);
5309 6 : if (!ok) {
5310 0 : return false;
5311 : }
5312 : }
5313 : }
5314 7 : return true;
5315 : }
5316 :
5317 : bool
5318 1 : nsContentUtils::HasNonEmptyTextContent(nsINode* aNode,
5319 : TextContentDiscoverMode aDiscoverMode)
5320 : {
5321 1 : for (nsIContent* child = aNode->GetFirstChild();
5322 1 : child;
5323 0 : child = child->GetNextSibling()) {
5324 2 : if (child->IsNodeOfType(nsINode::eTEXT) &&
5325 1 : child->TextLength() > 0) {
5326 1 : return true;
5327 : }
5328 :
5329 0 : if (aDiscoverMode == eRecurseIntoChildren &&
5330 0 : HasNonEmptyTextContent(child, aDiscoverMode)) {
5331 0 : return true;
5332 : }
5333 : }
5334 :
5335 0 : return false;
5336 : }
5337 :
5338 : /* static */
5339 : bool
5340 14 : nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
5341 : const nsIContent* aContent)
5342 : {
5343 14 : NS_PRECONDITION(aNode,
5344 : "Must have a node to work with");
5345 14 : NS_PRECONDITION(aContent,
5346 : "Must have a content to work with");
5347 :
5348 14 : if (!aNode->IsNodeOfType(nsINode::eCONTENT)) {
5349 : /**
5350 : * The root isn't an nsIContent, so it's a document or attribute. The only
5351 : * nodes in the same anonymous subtree as it will have a null
5352 : * bindingParent.
5353 : *
5354 : * XXXbz strictly speaking, that's not true for attribute nodes.
5355 : */
5356 0 : return aContent->GetBindingParent() == nullptr;
5357 : }
5358 :
5359 14 : const nsIContent* nodeAsContent = static_cast<const nsIContent*>(aNode);
5360 :
5361 : // For nodes in a shadow tree, it is insufficient to simply compare
5362 : // the binding parent because a node may host multiple ShadowRoots,
5363 : // thus nodes in different shadow tree may have the same binding parent.
5364 14 : if (aNode->IsInShadowTree()) {
5365 0 : return nodeAsContent->GetContainingShadow() ==
5366 0 : aContent->GetContainingShadow();
5367 : }
5368 :
5369 14 : return nodeAsContent->GetBindingParent() == aContent->GetBindingParent();
5370 : }
5371 :
5372 12 : class AnonymousContentDestroyer : public Runnable {
5373 : public:
5374 0 : explicit AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent)
5375 0 : : mozilla::Runnable("AnonymousContentDestroyer")
5376 : {
5377 0 : mContent.swap(*aContent);
5378 0 : mParent = mContent->GetParent();
5379 0 : mDoc = mContent->OwnerDoc();
5380 0 : }
5381 4 : explicit AnonymousContentDestroyer(nsCOMPtr<Element>* aElement)
5382 4 : : mozilla::Runnable("AnonymousContentDestroyer")
5383 : {
5384 4 : mContent = aElement->forget();
5385 4 : mParent = mContent->GetParent();
5386 4 : mDoc = mContent->OwnerDoc();
5387 4 : }
5388 4 : NS_IMETHOD Run() override {
5389 4 : mContent->UnbindFromTree();
5390 4 : return NS_OK;
5391 : }
5392 : private:
5393 : nsCOMPtr<nsIContent> mContent;
5394 : // Hold strong refs to the parent content and document so that they
5395 : // don't die unexpectedly
5396 : nsCOMPtr<nsIDocument> mDoc;
5397 : nsCOMPtr<nsIContent> mParent;
5398 : };
5399 :
5400 : /* static */
5401 : void
5402 28 : nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
5403 : {
5404 28 : if (*aContent) {
5405 0 : AddScriptRunner(new AnonymousContentDestroyer(aContent));
5406 : }
5407 28 : }
5408 :
5409 : /* static */
5410 : void
5411 6 : nsContentUtils::DestroyAnonymousContent(nsCOMPtr<Element>* aElement)
5412 : {
5413 6 : if (*aElement) {
5414 4 : AddScriptRunner(new AnonymousContentDestroyer(aElement));
5415 : }
5416 6 : }
5417 :
5418 : /* static */
5419 : void
5420 0 : nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
5421 : {
5422 0 : IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
5423 0 : }
5424 :
5425 0 : static bool SchemeIs(nsIURI* aURI, const char* aScheme)
5426 : {
5427 0 : nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
5428 0 : NS_ENSURE_TRUE(baseURI, false);
5429 :
5430 0 : bool isScheme = false;
5431 0 : return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
5432 : }
5433 :
5434 : bool
5435 2284 : nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
5436 : {
5437 2284 : MOZ_ASSERT(IsInitialized());
5438 2284 : return aPrincipal == sSystemPrincipal;
5439 : }
5440 :
5441 : bool
5442 230 : nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal)
5443 : {
5444 460 : nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
5445 460 : return !!ep;
5446 : }
5447 :
5448 : nsIPrincipal*
5449 1654 : nsContentUtils::GetSystemPrincipal()
5450 : {
5451 1654 : MOZ_ASSERT(IsInitialized());
5452 1654 : return sSystemPrincipal;
5453 : }
5454 :
5455 : bool
5456 0 : nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrincipal,
5457 : nsIPrincipal* aExtraPrincipal)
5458 : {
5459 0 : if (!aExtraPrincipal) {
5460 0 : return false;
5461 : }
5462 0 : if (!*aResourcePrincipal) {
5463 0 : *aResourcePrincipal = aExtraPrincipal;
5464 0 : return true;
5465 : }
5466 0 : if (*aResourcePrincipal == aExtraPrincipal) {
5467 0 : return false;
5468 : }
5469 : bool subsumes;
5470 0 : if (NS_SUCCEEDED((*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes)) &&
5471 : subsumes) {
5472 0 : return false;
5473 : }
5474 0 : *aResourcePrincipal = sSystemPrincipal;
5475 0 : return true;
5476 : }
5477 :
5478 : /* static */
5479 : void
5480 0 : nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
5481 : nsIURI *aLinkURI, const nsString &aTargetSpec,
5482 : bool aClick, bool aIsUserTriggered,
5483 : bool aIsTrusted)
5484 : {
5485 0 : NS_ASSERTION(aPresContext, "Need a nsPresContext");
5486 0 : NS_PRECONDITION(aLinkURI, "No link URI");
5487 :
5488 0 : if (aContent->IsEditable()) {
5489 0 : return;
5490 : }
5491 :
5492 0 : nsILinkHandler *handler = aPresContext->GetLinkHandler();
5493 0 : if (!handler) {
5494 0 : return;
5495 : }
5496 :
5497 0 : if (!aClick) {
5498 0 : handler->OnOverLink(aContent, aLinkURI, aTargetSpec.get());
5499 0 : return;
5500 : }
5501 :
5502 : // Check that this page is allowed to load this URI.
5503 0 : nsresult proceed = NS_OK;
5504 :
5505 0 : if (sSecurityManager) {
5506 : uint32_t flag =
5507 0 : aIsUserTriggered ?
5508 : (uint32_t)nsIScriptSecurityManager::STANDARD :
5509 0 : (uint32_t)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT;
5510 : proceed =
5511 0 : sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(),
5512 0 : aLinkURI, flag);
5513 : }
5514 :
5515 : // Only pass off the click event if the script security manager says it's ok.
5516 : // We need to rest aTargetSpec for forced downloads.
5517 0 : if (NS_SUCCEEDED(proceed)) {
5518 :
5519 : // A link/area element with a download attribute is allowed to set
5520 : // a pseudo Content-Disposition header.
5521 : // For security reasons we only allow websites to declare same-origin resources
5522 : // as downloadable. If this check fails we will just do the normal thing
5523 : // (i.e. navigate to the resource).
5524 0 : nsAutoString fileName;
5525 0 : if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
5526 0 : !aContent->IsHTMLElement(nsGkAtoms::area) &&
5527 0 : !aContent->IsSVGElement(nsGkAtoms::a)) ||
5528 0 : !aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::download, fileName) ||
5529 0 : NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, false, true))) {
5530 0 : fileName.SetIsVoid(true); // No actionable download attribute was found.
5531 : }
5532 :
5533 0 : handler->OnLinkClick(aContent, aLinkURI,
5534 0 : fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
5535 0 : fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
5536 : }
5537 : }
5538 :
5539 : /* static */
5540 : void
5541 0 : nsContentUtils::GetLinkLocation(Element* aElement, nsString& aLocationString)
5542 : {
5543 0 : nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
5544 0 : if (hrefURI) {
5545 0 : nsAutoCString specUTF8;
5546 0 : nsresult rv = hrefURI->GetSpec(specUTF8);
5547 0 : if (NS_SUCCEEDED(rv))
5548 0 : CopyUTF8toUTF16(specUTF8, aLocationString);
5549 : }
5550 0 : }
5551 :
5552 : /* static */
5553 : nsIWidget*
5554 4 : nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)
5555 : {
5556 4 : if (!aWidget)
5557 0 : return nullptr;
5558 :
5559 4 : return aWidget->GetTopLevelWidget();
5560 : }
5561 :
5562 : /* static */
5563 : const nsDependentString
5564 1 : nsContentUtils::GetLocalizedEllipsis()
5565 : {
5566 : static char16_t sBuf[4] = { 0, 0, 0, 0 };
5567 1 : if (!sBuf[0]) {
5568 2 : nsAdoptingString tmp = Preferences::GetLocalizedString("intl.ellipsis");
5569 2 : uint32_t len = std::min(uint32_t(tmp.Length()),
5570 3 : uint32_t(ArrayLength(sBuf) - 1));
5571 1 : CopyUnicodeTo(tmp, 0, sBuf, len);
5572 1 : if (!sBuf[0])
5573 0 : sBuf[0] = char16_t(0x2026);
5574 : }
5575 1 : return nsDependentString(sBuf);
5576 : }
5577 :
5578 : /* static */
5579 : void
5580 10839 : nsContentUtils::AddScriptBlocker()
5581 : {
5582 10839 : MOZ_ASSERT(NS_IsMainThread());
5583 10839 : if (!sScriptBlockerCount) {
5584 5381 : MOZ_ASSERT(sRunnersCountAtFirstBlocker == 0,
5585 : "Should not already have a count");
5586 5381 : sRunnersCountAtFirstBlocker = sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
5587 : }
5588 10839 : ++sScriptBlockerCount;
5589 10839 : }
5590 :
5591 : #ifdef DEBUG
5592 : static bool sRemovingScriptBlockers = false;
5593 : #endif
5594 :
5595 : /* static */
5596 : void
5597 10839 : nsContentUtils::RemoveScriptBlocker()
5598 : {
5599 10839 : MOZ_ASSERT(NS_IsMainThread());
5600 10839 : MOZ_ASSERT(!sRemovingScriptBlockers);
5601 10839 : NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers");
5602 10839 : --sScriptBlockerCount;
5603 10839 : if (sScriptBlockerCount) {
5604 10916 : return;
5605 : }
5606 :
5607 5381 : if (!sBlockedScriptRunners) {
5608 0 : return;
5609 : }
5610 :
5611 5381 : uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
5612 5381 : uint32_t lastBlocker = sBlockedScriptRunners->Length();
5613 5381 : uint32_t originalFirstBlocker = firstBlocker;
5614 5381 : uint32_t blockersCount = lastBlocker - firstBlocker;
5615 5381 : sRunnersCountAtFirstBlocker = 0;
5616 5381 : NS_ASSERTION(firstBlocker <= lastBlocker,
5617 : "bad sRunnersCountAtFirstBlocker");
5618 :
5619 5799 : while (firstBlocker < lastBlocker) {
5620 418 : nsCOMPtr<nsIRunnable> runnable;
5621 209 : runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
5622 209 : ++firstBlocker;
5623 :
5624 : // Calling the runnable can reenter us
5625 209 : runnable->Run();
5626 : // So can dropping the reference to the runnable
5627 209 : runnable = nullptr;
5628 :
5629 209 : NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
5630 : "Bad count");
5631 209 : NS_ASSERTION(!sScriptBlockerCount, "This is really bad");
5632 : }
5633 : #ifdef DEBUG
5634 10762 : AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
5635 5381 : sRemovingScriptBlockers = true;
5636 : #endif
5637 5381 : sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
5638 : }
5639 :
5640 : /* static */
5641 : nsIWindowProvider*
5642 0 : nsContentUtils::GetWindowProviderForContentProcess()
5643 : {
5644 0 : MOZ_ASSERT(XRE_IsContentProcess());
5645 0 : return ContentChild::GetSingleton();
5646 : }
5647 :
5648 : /* static */
5649 : already_AddRefed<nsPIDOMWindowOuter>
5650 0 : nsContentUtils::GetMostRecentNonPBWindow()
5651 : {
5652 : nsCOMPtr<nsIWindowMediator> windowMediator =
5653 0 : do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
5654 0 : nsCOMPtr<nsIWindowMediator_44> wm = do_QueryInterface(windowMediator);
5655 :
5656 0 : nsCOMPtr<mozIDOMWindowProxy> window;
5657 0 : wm->GetMostRecentNonPBWindow(u"navigator:browser",
5658 0 : getter_AddRefs(window));
5659 0 : nsCOMPtr<nsPIDOMWindowOuter> pwindow;
5660 0 : pwindow = do_QueryInterface(window);
5661 :
5662 0 : return pwindow.forget();
5663 : }
5664 :
5665 : /* static */
5666 : void
5667 0 : nsContentUtils::WarnScriptWasIgnored(nsIDocument* aDocument)
5668 : {
5669 0 : nsAutoString msg;
5670 0 : if (aDocument) {
5671 0 : nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
5672 0 : if (uri) {
5673 0 : msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
5674 0 : msg.AppendLiteral(" : ");
5675 : }
5676 : }
5677 0 : msg.AppendLiteral("Unable to run script because scripts are blocked internally.");
5678 :
5679 0 : LogSimpleConsoleError(msg, "DOM");
5680 0 : }
5681 :
5682 : /* static */
5683 : void
5684 302 : nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable)
5685 : {
5686 395 : nsCOMPtr<nsIRunnable> runnable = aRunnable;
5687 302 : if (!runnable) {
5688 0 : return;
5689 : }
5690 :
5691 302 : if (sScriptBlockerCount) {
5692 209 : sBlockedScriptRunners->AppendElement(runnable.forget());
5693 209 : return;
5694 : }
5695 :
5696 93 : runnable->Run();
5697 : }
5698 :
5699 : /* static */
5700 : void
5701 262 : nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
5702 524 : nsCOMPtr<nsIRunnable> runnable = aRunnable;
5703 262 : AddScriptRunner(runnable.forget());
5704 262 : }
5705 :
5706 : /* static */
5707 : void
5708 0 : nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable)
5709 : {
5710 0 : MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
5711 0 : CycleCollectedJSContext::Get()->RunInStableState(Move(aRunnable));
5712 0 : }
5713 :
5714 : /* static */
5715 : void
5716 0 : nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
5717 : {
5718 0 : MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
5719 0 : CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
5720 0 : }
5721 :
5722 : /* static */
5723 : nsISerialEventTarget*
5724 0 : nsContentUtils::GetStableStateEventTarget()
5725 : {
5726 0 : return sStableStateEventTarget;
5727 : }
5728 :
5729 : void
5730 656 : nsContentUtils::EnterMicroTask()
5731 : {
5732 656 : MOZ_ASSERT(NS_IsMainThread());
5733 656 : ++sMicroTaskLevel;
5734 656 : }
5735 :
5736 : void
5737 656 : nsContentUtils::LeaveMicroTask()
5738 : {
5739 656 : MOZ_ASSERT(NS_IsMainThread());
5740 656 : if (--sMicroTaskLevel == 0) {
5741 506 : PerformMainThreadMicroTaskCheckpoint();
5742 : }
5743 656 : }
5744 :
5745 : bool
5746 117 : nsContentUtils::IsInMicroTask()
5747 : {
5748 117 : MOZ_ASSERT(NS_IsMainThread());
5749 117 : return sMicroTaskLevel != 0;
5750 : }
5751 :
5752 : uint32_t
5753 0 : nsContentUtils::MicroTaskLevel()
5754 : {
5755 0 : MOZ_ASSERT(NS_IsMainThread());
5756 0 : return sMicroTaskLevel;
5757 : }
5758 :
5759 : void
5760 0 : nsContentUtils::SetMicroTaskLevel(uint32_t aLevel)
5761 : {
5762 0 : MOZ_ASSERT(NS_IsMainThread());
5763 0 : sMicroTaskLevel = aLevel;
5764 0 : }
5765 :
5766 : void
5767 1733 : nsContentUtils::PerformMainThreadMicroTaskCheckpoint()
5768 : {
5769 1733 : MOZ_ASSERT(NS_IsMainThread());
5770 :
5771 1733 : nsDOMMutationObserver::HandleMutations();
5772 1733 : }
5773 :
5774 : /*
5775 : * Helper function for nsContentUtils::ProcessViewportInfo.
5776 : *
5777 : * Handles a single key=value pair. If it corresponds to a valid viewport
5778 : * attribute, add it to the document header data. No validation is done on the
5779 : * value itself (this is done at display time).
5780 : */
5781 0 : static void ProcessViewportToken(nsIDocument *aDocument,
5782 : const nsAString &token) {
5783 :
5784 : /* Iterators. */
5785 0 : nsAString::const_iterator tip, tail, end;
5786 0 : token.BeginReading(tip);
5787 0 : tail = tip;
5788 0 : token.EndReading(end);
5789 :
5790 : /* Move tip to the '='. */
5791 0 : while ((tip != end) && (*tip != '='))
5792 0 : ++tip;
5793 :
5794 : /* If we didn't find an '=', punt. */
5795 0 : if (tip == end)
5796 0 : return;
5797 :
5798 : /* Extract the key and value. */
5799 : const nsAString &key =
5800 0 : nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
5801 0 : true);
5802 : const nsAString &value =
5803 0 : nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
5804 0 : true);
5805 :
5806 : /* Check for known keys. If we find a match, insert the appropriate
5807 : * information into the document header. */
5808 0 : nsCOMPtr<nsIAtom> key_atom = NS_Atomize(key);
5809 0 : if (key_atom == nsGkAtoms::height)
5810 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_height, value);
5811 0 : else if (key_atom == nsGkAtoms::width)
5812 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_width, value);
5813 0 : else if (key_atom == nsGkAtoms::initial_scale)
5814 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_initial_scale, value);
5815 0 : else if (key_atom == nsGkAtoms::minimum_scale)
5816 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_minimum_scale, value);
5817 0 : else if (key_atom == nsGkAtoms::maximum_scale)
5818 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_maximum_scale, value);
5819 0 : else if (key_atom == nsGkAtoms::user_scalable)
5820 0 : aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
5821 : }
5822 :
5823 : #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
5824 : (c == '\t') || (c == '\n') || (c == '\r'))
5825 :
5826 : /* static */
5827 : nsresult
5828 0 : nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
5829 : const nsAString &viewportInfo) {
5830 :
5831 : /* We never fail. */
5832 0 : nsresult rv = NS_OK;
5833 :
5834 0 : aDocument->SetHeaderData(nsGkAtoms::viewport, viewportInfo);
5835 :
5836 : /* Iterators. */
5837 0 : nsAString::const_iterator tip, tail, end;
5838 0 : viewportInfo.BeginReading(tip);
5839 0 : tail = tip;
5840 0 : viewportInfo.EndReading(end);
5841 :
5842 : /* Read the tip to the first non-separator character. */
5843 0 : while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
5844 0 : ++tip;
5845 :
5846 : /* Read through and find tokens separated by separators. */
5847 0 : while (tip != end) {
5848 :
5849 : /* Synchronize tip and tail. */
5850 0 : tail = tip;
5851 :
5852 : /* Advance tip past non-separator characters. */
5853 0 : while ((tip != end) && !IS_SEPARATOR(*tip))
5854 0 : ++tip;
5855 :
5856 : /* Allow white spaces that surround the '=' character */
5857 0 : if ((tip != end) && (*tip == '=')) {
5858 0 : ++tip;
5859 :
5860 0 : while ((tip != end) && nsCRT::IsAsciiSpace(*tip))
5861 0 : ++tip;
5862 :
5863 0 : while ((tip != end) && !(IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
5864 0 : ++tip;
5865 : }
5866 :
5867 : /* Our token consists of the characters between tail and tip. */
5868 0 : ProcessViewportToken(aDocument, Substring(tail, tip));
5869 :
5870 : /* Skip separators. */
5871 0 : while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
5872 0 : ++tip;
5873 : }
5874 :
5875 0 : return rv;
5876 :
5877 : }
5878 :
5879 : #undef IS_SEPARATOR
5880 :
5881 : /* static */
5882 : void
5883 4 : nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
5884 : {
5885 : #ifdef MOZ_XUL
5886 4 : nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
5887 4 : if (pm && aDocument) {
5888 8 : nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
5889 4 : if (docShellToHide)
5890 4 : pm->HidePopupsInDocShell(docShellToHide);
5891 : }
5892 : #endif
5893 4 : }
5894 :
5895 : /* static */
5896 : already_AddRefed<nsIDragSession>
5897 1 : nsContentUtils::GetDragSession()
5898 : {
5899 2 : nsCOMPtr<nsIDragSession> dragSession;
5900 : nsCOMPtr<nsIDragService> dragService =
5901 2 : do_GetService("@mozilla.org/widget/dragservice;1");
5902 1 : if (dragService)
5903 1 : dragService->GetCurrentSession(getter_AddRefs(dragSession));
5904 2 : return dragSession.forget();
5905 : }
5906 :
5907 : /* static */
5908 : nsresult
5909 0 : nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent)
5910 : {
5911 0 : if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
5912 0 : return NS_OK;
5913 : }
5914 :
5915 : // For dragstart events, the data transfer object is
5916 : // created before the event fires, so it should already be set. For other
5917 : // drag events, get the object from the drag session.
5918 0 : NS_ASSERTION(aDragEvent->mMessage != eDragStart,
5919 : "draggesture event created without a dataTransfer");
5920 :
5921 0 : nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
5922 0 : NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
5923 :
5924 0 : nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
5925 0 : nsCOMPtr<DataTransfer> initialDataTransfer;
5926 0 : dragSession->GetDataTransfer(getter_AddRefs(dataTransfer));
5927 0 : if (dataTransfer) {
5928 0 : initialDataTransfer = do_QueryInterface(dataTransfer);
5929 0 : if (!initialDataTransfer) {
5930 0 : return NS_ERROR_FAILURE;
5931 : }
5932 : } else {
5933 : // A dataTransfer won't exist when a drag was started by some other
5934 : // means, for instance calling the drag service directly, or a drag
5935 : // from another application. In either case, a new dataTransfer should
5936 : // be created that reflects the data.
5937 : initialDataTransfer =
5938 0 : new DataTransfer(aDragEvent->mTarget, aDragEvent->mMessage, true, -1);
5939 :
5940 : // now set it in the drag session so we don't need to create it again
5941 0 : dragSession->SetDataTransfer(initialDataTransfer);
5942 : }
5943 :
5944 0 : bool isCrossDomainSubFrameDrop = false;
5945 0 : if (aDragEvent->mMessage == eDrop) {
5946 0 : isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
5947 : }
5948 :
5949 : // each event should use a clone of the original dataTransfer.
5950 0 : initialDataTransfer->Clone(aDragEvent->mTarget, aDragEvent->mMessage,
5951 0 : aDragEvent->mUserCancelled,
5952 : isCrossDomainSubFrameDrop,
5953 0 : getter_AddRefs(aDragEvent->mDataTransfer));
5954 0 : if (NS_WARN_IF(!aDragEvent->mDataTransfer)) {
5955 0 : return NS_ERROR_OUT_OF_MEMORY;
5956 : }
5957 :
5958 : // for the dragenter and dragover events, initialize the drop effect
5959 : // from the drop action, which platform specific widget code sets before
5960 : // the event is fired based on the keyboard state.
5961 0 : if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
5962 : uint32_t action, effectAllowed;
5963 0 : dragSession->GetDragAction(&action);
5964 0 : aDragEvent->mDataTransfer->GetEffectAllowedInt(&effectAllowed);
5965 0 : aDragEvent->mDataTransfer->SetDropEffectInt(
5966 0 : FilterDropEffect(action, effectAllowed));
5967 : }
5968 0 : else if (aDragEvent->mMessage == eDrop ||
5969 0 : aDragEvent->mMessage == eDragEnd) {
5970 : // For the drop and dragend events, set the drop effect based on the
5971 : // last value that the dropEffect had. This will have been set in
5972 : // EventStateManager::PostHandleEvent for the last dragenter or
5973 : // dragover event.
5974 : uint32_t dropEffect;
5975 0 : initialDataTransfer->GetDropEffectInt(&dropEffect);
5976 0 : aDragEvent->mDataTransfer->SetDropEffectInt(dropEffect);
5977 : }
5978 :
5979 0 : return NS_OK;
5980 : }
5981 :
5982 : /* static */
5983 : uint32_t
5984 0 : nsContentUtils::FilterDropEffect(uint32_t aAction, uint32_t aEffectAllowed)
5985 : {
5986 : // It is possible for the drag action to include more than one action, but
5987 : // the widget code which sets the action from the keyboard state should only
5988 : // be including one. If multiple actions were set, we just consider them in
5989 : // the following order:
5990 : // copy, link, move
5991 0 : if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
5992 0 : aAction = nsIDragService::DRAGDROP_ACTION_COPY;
5993 0 : else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
5994 0 : aAction = nsIDragService::DRAGDROP_ACTION_LINK;
5995 0 : else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
5996 0 : aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
5997 :
5998 : // Filter the action based on the effectAllowed. If the effectAllowed
5999 : // doesn't include the action, then that action cannot be done, so adjust
6000 : // the action to something that is allowed. For a copy, adjust to move or
6001 : // link. For a move, adjust to copy or link. For a link, adjust to move or
6002 : // link. Otherwise, use none.
6003 0 : if (aAction & aEffectAllowed ||
6004 : aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
6005 0 : return aAction;
6006 0 : if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
6007 0 : return nsIDragService::DRAGDROP_ACTION_MOVE;
6008 0 : if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
6009 0 : return nsIDragService::DRAGDROP_ACTION_COPY;
6010 0 : if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
6011 0 : return nsIDragService::DRAGDROP_ACTION_LINK;
6012 0 : return nsIDragService::DRAGDROP_ACTION_NONE;
6013 : }
6014 :
6015 : /* static */
6016 : bool
6017 0 : nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
6018 : WidgetDragEvent* aDropEvent)
6019 : {
6020 0 : nsCOMPtr<nsIContent> target = do_QueryInterface(aDropEvent->mOriginalTarget);
6021 0 : if (!target) {
6022 0 : return true;
6023 : }
6024 :
6025 0 : nsIDocument* targetDoc = target->OwnerDoc();
6026 0 : nsPIDOMWindowOuter* targetWin = targetDoc->GetWindow();
6027 0 : if (!targetWin) {
6028 0 : return true;
6029 : }
6030 :
6031 0 : nsCOMPtr<nsIDocShellTreeItem> tdsti = targetWin->GetDocShell();
6032 0 : if (!tdsti) {
6033 0 : return true;
6034 : }
6035 :
6036 : // Always allow dropping onto chrome shells.
6037 0 : if (tdsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
6038 0 : return false;
6039 : }
6040 :
6041 : // If there is no source node, then this is a drag from another
6042 : // application, which should be allowed.
6043 0 : nsCOMPtr<nsIDOMDocument> sourceDocument;
6044 0 : aDragSession->GetSourceDocument(getter_AddRefs(sourceDocument));
6045 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(sourceDocument);
6046 0 : if (doc) {
6047 : // Get each successive parent of the source document and compare it to
6048 : // the drop document. If they match, then this is a drag from a child frame.
6049 0 : do {
6050 0 : doc = doc->GetParentDocument();
6051 0 : if (doc == targetDoc) {
6052 : // The drag is from a child frame.
6053 0 : return true;
6054 : }
6055 : } while (doc);
6056 : }
6057 :
6058 0 : return false;
6059 : }
6060 :
6061 : /* static */
6062 : bool
6063 133 : nsContentUtils::URIIsLocalFile(nsIURI *aURI)
6064 : {
6065 : bool isFile;
6066 266 : nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
6067 :
6068 : // Important: we do NOT test the entire URI chain here!
6069 266 : return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
6070 : nsIProtocolHandler::URI_IS_LOCAL_FILE,
6071 266 : &isFile)) &&
6072 266 : isFile;
6073 : }
6074 :
6075 : /* static */
6076 : nsIScriptContext*
6077 2 : nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
6078 : nsresult* aRv)
6079 : {
6080 2 : *aRv = NS_OK;
6081 2 : bool hasHadScriptObject = true;
6082 : nsIScriptGlobalObject* sgo =
6083 2 : aNode->OwnerDoc()->GetScriptHandlingObject(hasHadScriptObject);
6084 : // It is bad if the document doesn't have event handling context,
6085 : // but it used to have one.
6086 2 : if (!sgo && hasHadScriptObject) {
6087 0 : *aRv = NS_ERROR_UNEXPECTED;
6088 0 : return nullptr;
6089 : }
6090 :
6091 2 : if (sgo) {
6092 0 : nsIScriptContext* scx = sgo->GetContext();
6093 : // Bad, no context from script global object!
6094 0 : if (!scx) {
6095 0 : *aRv = NS_ERROR_UNEXPECTED;
6096 0 : return nullptr;
6097 : }
6098 0 : return scx;
6099 : }
6100 :
6101 2 : return nullptr;
6102 : }
6103 :
6104 : /* static */
6105 : JSContext *
6106 65698 : nsContentUtils::GetCurrentJSContext()
6107 : {
6108 65698 : MOZ_ASSERT(NS_IsMainThread());
6109 65698 : MOZ_ASSERT(IsInitialized());
6110 65698 : if (!IsJSAPIActive()) {
6111 1467 : return nullptr;
6112 : }
6113 64231 : return danger::GetJSContext();
6114 : }
6115 :
6116 : /* static */
6117 : JSContext *
6118 2927 : nsContentUtils::GetCurrentJSContextForThread()
6119 : {
6120 2927 : MOZ_ASSERT(IsInitialized());
6121 2927 : if (MOZ_LIKELY(NS_IsMainThread())) {
6122 2927 : return GetCurrentJSContext();
6123 : }
6124 0 : return workers::GetCurrentThreadJSContext();
6125 : }
6126 :
6127 : template<typename StringType, typename CharType>
6128 : void
6129 3998 : _ASCIIToLowerInSitu(StringType& aStr)
6130 : {
6131 3998 : CharType* iter = aStr.BeginWriting();
6132 3998 : CharType* end = aStr.EndWriting();
6133 3998 : MOZ_ASSERT(iter && end);
6134 :
6135 92514 : while (iter != end) {
6136 44258 : CharType c = *iter;
6137 44258 : if (c >= 'A' && c <= 'Z') {
6138 8 : *iter = c + ('a' - 'A');
6139 : }
6140 44258 : ++iter;
6141 : }
6142 3998 : }
6143 :
6144 : /* static */
6145 : void
6146 3998 : nsContentUtils::ASCIIToLower(nsAString& aStr)
6147 : {
6148 3998 : return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
6149 : }
6150 :
6151 : /* static */
6152 : void
6153 0 : nsContentUtils::ASCIIToLower(nsACString& aStr)
6154 : {
6155 0 : return _ASCIIToLowerInSitu<nsACString, char>(aStr);
6156 : }
6157 :
6158 : template<typename StringType, typename CharType>
6159 : void
6160 6003 : _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest)
6161 : {
6162 6003 : uint32_t len = aSource.Length();
6163 6003 : aDest.SetLength(len);
6164 6003 : MOZ_ASSERT(aDest.Length() == len);
6165 :
6166 6003 : CharType* dest = aDest.BeginWriting();
6167 6003 : MOZ_ASSERT(dest);
6168 :
6169 6003 : const CharType* iter = aSource.BeginReading();
6170 6003 : const CharType* end = aSource.EndReading();
6171 90979 : while (iter != end) {
6172 42488 : CharType c = *iter;
6173 42488 : *dest = (c >= 'A' && c <= 'Z') ?
6174 0 : c + ('a' - 'A') : c;
6175 42488 : ++iter;
6176 42488 : ++dest;
6177 : }
6178 6003 : }
6179 :
6180 : /* static */
6181 : void
6182 6003 : nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
6183 6003 : return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
6184 : }
6185 :
6186 : /* static */
6187 : void
6188 0 : nsContentUtils::ASCIIToLower(const nsACString& aSource, nsACString& aDest) {
6189 0 : return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
6190 : }
6191 :
6192 :
6193 : template<typename StringType, typename CharType>
6194 : void
6195 0 : _ASCIIToUpperInSitu(StringType& aStr)
6196 : {
6197 0 : CharType* iter = aStr.BeginWriting();
6198 0 : CharType* end = aStr.EndWriting();
6199 0 : MOZ_ASSERT(iter && end);
6200 :
6201 0 : while (iter != end) {
6202 0 : CharType c = *iter;
6203 0 : if (c >= 'a' && c <= 'z') {
6204 0 : *iter = c + ('A' - 'a');
6205 : }
6206 0 : ++iter;
6207 : }
6208 0 : }
6209 :
6210 : /* static */
6211 : void
6212 0 : nsContentUtils::ASCIIToUpper(nsAString& aStr)
6213 : {
6214 0 : return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
6215 : }
6216 :
6217 : /* static */
6218 : void
6219 0 : nsContentUtils::ASCIIToUpper(nsACString& aStr)
6220 : {
6221 0 : return _ASCIIToUpperInSitu<nsACString, char>(aStr);
6222 : }
6223 :
6224 : template<typename StringType, typename CharType>
6225 : void
6226 27 : _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest)
6227 : {
6228 27 : uint32_t len = aSource.Length();
6229 27 : aDest.SetLength(len);
6230 27 : MOZ_ASSERT(aDest.Length() == len);
6231 :
6232 27 : CharType* dest = aDest.BeginWriting();
6233 27 : MOZ_ASSERT(dest);
6234 :
6235 27 : const CharType* iter = aSource.BeginReading();
6236 27 : const CharType* end = aSource.EndReading();
6237 245 : while (iter != end) {
6238 109 : CharType c = *iter;
6239 109 : *dest = (c >= 'a' && c <= 'z') ?
6240 0 : c + ('A' - 'a') : c;
6241 109 : ++iter;
6242 109 : ++dest;
6243 : }
6244 27 : }
6245 :
6246 : /* static */
6247 : void
6248 27 : nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
6249 : {
6250 27 : return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
6251 : }
6252 :
6253 : /* static */
6254 : void
6255 0 : nsContentUtils::ASCIIToUpper(const nsACString& aSource, nsACString& aDest)
6256 : {
6257 0 : return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
6258 : }
6259 :
6260 : /* static */
6261 : bool
6262 8 : nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
6263 : const nsAString& aStr2)
6264 : {
6265 8 : uint32_t len = aStr1.Length();
6266 8 : if (len != aStr2.Length()) {
6267 0 : return false;
6268 : }
6269 :
6270 8 : const char16_t* str1 = aStr1.BeginReading();
6271 8 : const char16_t* str2 = aStr2.BeginReading();
6272 8 : const char16_t* end = str1 + len;
6273 :
6274 168 : while (str1 < end) {
6275 80 : char16_t c1 = *str1++;
6276 80 : char16_t c2 = *str2++;
6277 :
6278 : // First check if any bits other than the 0x0020 differs
6279 80 : if ((c1 ^ c2) & 0xffdf) {
6280 0 : return false;
6281 : }
6282 :
6283 : // We know they can only differ in the 0x0020 bit.
6284 : // Likely the two chars are the same, so check that first
6285 80 : if (c1 != c2) {
6286 : // They do differ, but since it's only in the 0x0020 bit, check if it's
6287 : // the same ascii char, but just differing in case
6288 0 : char16_t c1Upper = c1 & 0xffdf;
6289 0 : if (!('A' <= c1Upper && c1Upper <= 'Z')) {
6290 0 : return false;
6291 : }
6292 : }
6293 : }
6294 :
6295 8 : return true;
6296 : }
6297 :
6298 : /* static */
6299 : bool
6300 7 : nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr)
6301 : {
6302 7 : const char16_t* iter = aStr.BeginReading();
6303 7 : const char16_t* end = aStr.EndReading();
6304 163 : while (iter != end) {
6305 78 : char16_t c = *iter;
6306 78 : if (c >= 'A' && c <= 'Z') {
6307 0 : return true;
6308 : }
6309 78 : ++iter;
6310 : }
6311 :
6312 7 : return false;
6313 : }
6314 :
6315 : /* static */
6316 : nsIInterfaceRequestor*
6317 0 : nsContentUtils::SameOriginChecker()
6318 : {
6319 0 : if (!sSameOriginChecker) {
6320 0 : sSameOriginChecker = new SameOriginCheckerImpl();
6321 0 : NS_ADDREF(sSameOriginChecker);
6322 : }
6323 0 : return sSameOriginChecker;
6324 : }
6325 :
6326 : /* static */
6327 : nsresult
6328 0 : nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel)
6329 : {
6330 0 : if (!nsContentUtils::GetSecurityManager())
6331 0 : return NS_ERROR_NOT_AVAILABLE;
6332 :
6333 0 : nsCOMPtr<nsIPrincipal> oldPrincipal;
6334 0 : nsContentUtils::GetSecurityManager()->
6335 0 : GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
6336 :
6337 0 : nsCOMPtr<nsIURI> newURI;
6338 0 : aNewChannel->GetURI(getter_AddRefs(newURI));
6339 0 : nsCOMPtr<nsIURI> newOriginalURI;
6340 0 : aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
6341 :
6342 0 : NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
6343 :
6344 0 : nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
6345 0 : if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
6346 0 : rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
6347 : }
6348 :
6349 0 : return rv;
6350 : }
6351 :
6352 0 : NS_IMPL_ISUPPORTS(SameOriginCheckerImpl,
6353 : nsIChannelEventSink,
6354 : nsIInterfaceRequestor)
6355 :
6356 : NS_IMETHODIMP
6357 0 : SameOriginCheckerImpl::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
6358 : nsIChannel* aNewChannel,
6359 : uint32_t aFlags,
6360 : nsIAsyncVerifyRedirectCallback* cb)
6361 : {
6362 0 : NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
6363 :
6364 0 : nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
6365 0 : if (NS_SUCCEEDED(rv)) {
6366 0 : cb->OnRedirectVerifyCallback(NS_OK);
6367 : }
6368 :
6369 0 : return rv;
6370 : }
6371 :
6372 : NS_IMETHODIMP
6373 0 : SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult)
6374 : {
6375 0 : return QueryInterface(aIID, aResult);
6376 : }
6377 :
6378 : /* static */
6379 : nsresult
6380 0 : nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal, nsACString& aOrigin)
6381 : {
6382 0 : NS_PRECONDITION(aPrincipal, "missing principal");
6383 :
6384 0 : aOrigin.Truncate();
6385 :
6386 0 : nsCOMPtr<nsIURI> uri;
6387 0 : nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
6388 0 : NS_ENSURE_SUCCESS(rv, rv);
6389 :
6390 0 : if (uri) {
6391 0 : return GetASCIIOrigin(uri, aOrigin);
6392 : }
6393 :
6394 0 : aOrigin.AssignLiteral("null");
6395 :
6396 0 : return NS_OK;
6397 : }
6398 :
6399 : /* static */
6400 : nsresult
6401 6 : nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin)
6402 : {
6403 6 : NS_PRECONDITION(aURI, "missing uri");
6404 :
6405 : // For Blob URI we have to return the origin of page using its principal.
6406 12 : nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(aURI);
6407 6 : if (uriWithPrincipal) {
6408 0 : nsCOMPtr<nsIPrincipal> principal;
6409 0 : uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
6410 :
6411 0 : if (principal) {
6412 0 : nsCOMPtr<nsIURI> uri;
6413 0 : nsresult rv = principal->GetURI(getter_AddRefs(uri));
6414 0 : NS_ENSURE_SUCCESS(rv, rv);
6415 :
6416 0 : if (uri && uri != aURI) {
6417 0 : return GetASCIIOrigin(uri, aOrigin);
6418 : }
6419 : }
6420 : }
6421 :
6422 6 : aOrigin.Truncate();
6423 :
6424 12 : nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
6425 6 : NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
6426 :
6427 12 : nsCString host;
6428 6 : nsresult rv = uri->GetAsciiHost(host);
6429 :
6430 6 : if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
6431 12 : nsCString scheme;
6432 6 : rv = uri->GetScheme(scheme);
6433 6 : NS_ENSURE_SUCCESS(rv, rv);
6434 :
6435 6 : int32_t port = -1;
6436 6 : uri->GetPort(&port);
6437 6 : if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
6438 0 : port = -1;
6439 :
6440 12 : nsCString hostPort;
6441 6 : rv = NS_GenerateHostPort(host, port, hostPort);
6442 6 : NS_ENSURE_SUCCESS(rv, rv);
6443 :
6444 6 : aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
6445 : }
6446 : else {
6447 0 : aOrigin.AssignLiteral("null");
6448 : }
6449 :
6450 6 : return NS_OK;
6451 : }
6452 :
6453 : /* static */
6454 : nsresult
6455 8 : nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin)
6456 : {
6457 8 : NS_PRECONDITION(aPrincipal, "missing principal");
6458 :
6459 8 : aOrigin.Truncate();
6460 :
6461 16 : nsCOMPtr<nsIURI> uri;
6462 8 : nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
6463 8 : NS_ENSURE_SUCCESS(rv, rv);
6464 :
6465 8 : if (uri) {
6466 3 : return GetUTFOrigin(uri, aOrigin);
6467 : }
6468 :
6469 5 : aOrigin.AssignLiteral("null");
6470 :
6471 5 : return NS_OK;
6472 : }
6473 :
6474 : /* static */
6475 : nsresult
6476 4 : nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin)
6477 : {
6478 4 : NS_PRECONDITION(aURI, "missing uri");
6479 :
6480 : // For Blob URI we have to return the origin of page using its principal.
6481 8 : nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(aURI);
6482 4 : if (uriWithPrincipal) {
6483 0 : nsCOMPtr<nsIPrincipal> principal;
6484 0 : uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
6485 :
6486 0 : if (principal) {
6487 0 : nsCOMPtr<nsIURI> uri;
6488 0 : nsresult rv = principal->GetURI(getter_AddRefs(uri));
6489 0 : NS_ENSURE_SUCCESS(rv, rv);
6490 :
6491 0 : if (uri && uri != aURI) {
6492 0 : return GetUTFOrigin(uri, aOrigin);
6493 : }
6494 : } else {
6495 : // We are probably dealing with an unknown blob URL.
6496 0 : bool isBlobURL = false;
6497 0 : nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
6498 0 : NS_ENSURE_SUCCESS(rv, rv);
6499 :
6500 0 : if (isBlobURL) {
6501 0 : nsAutoCString path;
6502 0 : rv = aURI->GetPath(path);
6503 0 : NS_ENSURE_SUCCESS(rv, rv);
6504 :
6505 0 : nsCOMPtr<nsIURI> uri;
6506 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), path);
6507 0 : if (NS_FAILED(rv)) {
6508 0 : aOrigin.AssignLiteral("null");
6509 0 : return NS_OK;
6510 : }
6511 :
6512 0 : return GetUTFOrigin(uri, aOrigin);
6513 : }
6514 : }
6515 : }
6516 :
6517 4 : aOrigin.Truncate();
6518 :
6519 8 : nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
6520 4 : NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
6521 :
6522 8 : nsCString host;
6523 4 : nsresult rv = uri->GetHost(host);
6524 :
6525 4 : if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
6526 4 : nsCString scheme;
6527 2 : rv = uri->GetScheme(scheme);
6528 2 : NS_ENSURE_SUCCESS(rv, rv);
6529 :
6530 2 : int32_t port = -1;
6531 2 : uri->GetPort(&port);
6532 2 : if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
6533 0 : port = -1;
6534 :
6535 4 : nsCString hostPort;
6536 2 : rv = NS_GenerateHostPort(host, port, hostPort);
6537 2 : NS_ENSURE_SUCCESS(rv, rv);
6538 :
6539 4 : aOrigin = NS_ConvertUTF8toUTF16(
6540 6 : scheme + NS_LITERAL_CSTRING("://") + hostPort);
6541 : }
6542 : else {
6543 2 : aOrigin.AssignLiteral("null");
6544 : }
6545 :
6546 4 : return NS_OK;
6547 : }
6548 :
6549 : /* static */
6550 : bool
6551 0 : nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal)
6552 : {
6553 0 : nsCOMPtr<nsIURI> channelURI;
6554 0 : nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
6555 0 : NS_ENSURE_SUCCESS(rv, false);
6556 :
6557 0 : return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false, aAllowIfInheritsPrincipal));
6558 : }
6559 :
6560 5 : nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
6561 5 : : mString(aString), mService(nullptr)
6562 : {
6563 5 : CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
6564 5 : }
6565 :
6566 10 : nsContentTypeParser::~nsContentTypeParser()
6567 : {
6568 5 : NS_IF_RELEASE(mService);
6569 5 : }
6570 :
6571 : nsresult
6572 10 : nsContentTypeParser::GetParameter(const char* aParameterName,
6573 : nsAString& aResult) const
6574 : {
6575 10 : NS_ENSURE_TRUE(mService, NS_ERROR_FAILURE);
6576 20 : return mService->GetParameterHTTP(mString, aParameterName,
6577 10 : EmptyCString(), false, nullptr,
6578 20 : aResult);
6579 : }
6580 :
6581 : nsresult
6582 5 : nsContentTypeParser::GetType(nsAString& aResult) const
6583 : {
6584 5 : nsresult rv = GetParameter(nullptr, aResult);
6585 5 : if (NS_FAILED(rv)) {
6586 0 : return rv;
6587 : }
6588 5 : nsContentUtils::ASCIIToLower(aResult);
6589 5 : return NS_OK;
6590 : }
6591 :
6592 : /* static */
6593 :
6594 : bool
6595 0 : nsContentUtils::CanAccessNativeAnon()
6596 : {
6597 0 : return LegacyIsCallerChromeOrNativeCode() || IsCallerContentXBL();
6598 : }
6599 :
6600 : /* static */ nsresult
6601 0 : nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
6602 : bool aTrusted,
6603 : nsIDOMEvent* aSourceEvent,
6604 : nsIPresShell* aShell,
6605 : bool aCtrl,
6606 : bool aAlt,
6607 : bool aShift,
6608 : bool aMeta)
6609 : {
6610 0 : NS_ENSURE_STATE(aTarget);
6611 0 : nsIDocument* doc = aTarget->OwnerDoc();
6612 0 : nsIPresShell* shell = doc->GetShell();
6613 0 : nsPresContext* presContext = nullptr;
6614 0 : if (shell) {
6615 0 : presContext = shell->GetPresContext();
6616 : }
6617 : RefPtr<XULCommandEvent> xulCommand = new XULCommandEvent(doc, presContext,
6618 0 : nullptr);
6619 0 : xulCommand->InitCommandEvent(NS_LITERAL_STRING("command"), true, true,
6620 0 : doc->GetInnerWindow(), 0, aCtrl, aAlt, aShift,
6621 0 : aMeta, aSourceEvent);
6622 :
6623 0 : if (aShell) {
6624 0 : nsEventStatus status = nsEventStatus_eIgnore;
6625 0 : nsCOMPtr<nsIPresShell> kungFuDeathGrip = aShell;
6626 0 : return aShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
6627 : }
6628 :
6629 0 : nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget);
6630 0 : NS_ENSURE_STATE(target);
6631 : bool dummy;
6632 0 : return target->DispatchEvent(xulCommand, &dummy);
6633 : }
6634 :
6635 : // static
6636 : nsresult
6637 975 : nsContentUtils::WrapNative(JSContext *cx, nsISupports *native,
6638 : nsWrapperCache *cache, const nsIID* aIID,
6639 : JS::MutableHandle<JS::Value> vp, bool aAllowWrapping)
6640 : {
6641 975 : MOZ_ASSERT(cx == GetCurrentJSContext());
6642 :
6643 975 : if (!native) {
6644 0 : vp.setNull();
6645 :
6646 0 : return NS_OK;
6647 : }
6648 :
6649 975 : JSObject *wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
6650 975 : if (wrapper) {
6651 0 : return NS_OK;
6652 : }
6653 :
6654 975 : NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
6655 :
6656 975 : if (!NS_IsMainThread()) {
6657 0 : MOZ_CRASH();
6658 : }
6659 :
6660 975 : nsresult rv = NS_OK;
6661 1950 : JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
6662 2925 : rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
6663 2925 : aAllowWrapping, vp);
6664 975 : return rv;
6665 : }
6666 :
6667 : nsresult
6668 0 : nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
6669 : JSObject** aResult)
6670 : {
6671 0 : if (!aCx) {
6672 0 : return NS_ERROR_FAILURE;
6673 : }
6674 :
6675 0 : int32_t dataLen = aData.Length();
6676 0 : *aResult = JS_NewArrayBuffer(aCx, dataLen);
6677 0 : if (!*aResult) {
6678 0 : return NS_ERROR_FAILURE;
6679 : }
6680 :
6681 0 : if (dataLen > 0) {
6682 0 : NS_ASSERTION(JS_IsArrayBufferObject(*aResult), "What happened?");
6683 0 : JS::AutoCheckCannotGC nogc;
6684 : bool isShared;
6685 0 : memcpy(JS_GetArrayBufferData(*aResult, &isShared, nogc), aData.BeginReading(), dataLen);
6686 0 : MOZ_ASSERT(!isShared);
6687 : }
6688 :
6689 0 : return NS_OK;
6690 : }
6691 :
6692 : void
6693 0 : nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
6694 : {
6695 : // In common cases where we don't have nulls in the
6696 : // string we can simple simply bypass the checking code.
6697 0 : int32_t firstNullPos = aInStr.FindChar('\0');
6698 0 : if (firstNullPos == kNotFound) {
6699 0 : aOutStr.Assign(aInStr);
6700 0 : return;
6701 : }
6702 :
6703 0 : aOutStr.SetCapacity(aInStr.Length() - 1);
6704 0 : nsAString::const_iterator start, end;
6705 0 : aInStr.BeginReading(start);
6706 0 : aInStr.EndReading(end);
6707 0 : while (start != end) {
6708 0 : if (*start != '\0')
6709 0 : aOutStr.Append(*start);
6710 0 : ++start;
6711 : }
6712 : }
6713 :
6714 0 : struct ClassMatchingInfo {
6715 : nsAttrValue::AtomArray mClasses;
6716 : nsCaseTreatment mCaseTreatment;
6717 : };
6718 :
6719 : // static
6720 : bool
6721 0 : nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
6722 : nsIAtom* aAtom, void* aData)
6723 : {
6724 : // We can't match if there are no class names
6725 0 : const nsAttrValue* classAttr = aElement->GetClasses();
6726 0 : if (!classAttr) {
6727 0 : return false;
6728 : }
6729 :
6730 : // need to match *all* of the classes
6731 0 : ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
6732 0 : uint32_t length = info->mClasses.Length();
6733 0 : if (!length) {
6734 : // If we actually had no classes, don't match.
6735 0 : return false;
6736 : }
6737 : uint32_t i;
6738 0 : for (i = 0; i < length; ++i) {
6739 0 : if (!classAttr->Contains(info->mClasses[i],
6740 : info->mCaseTreatment)) {
6741 0 : return false;
6742 : }
6743 : }
6744 :
6745 0 : return true;
6746 : }
6747 :
6748 : // static
6749 : void
6750 0 : nsContentUtils::DestroyClassNameArray(void* aData)
6751 : {
6752 0 : ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
6753 0 : delete info;
6754 0 : }
6755 :
6756 : // static
6757 : void*
6758 0 : nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
6759 : const nsString* aClasses)
6760 : {
6761 0 : nsAttrValue attrValue;
6762 0 : attrValue.ParseAtomArray(*aClasses);
6763 : // nsAttrValue::Equals is sensitive to order, so we'll send an array
6764 0 : auto* info = new ClassMatchingInfo;
6765 0 : if (attrValue.Type() == nsAttrValue::eAtomArray) {
6766 0 : info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
6767 0 : } else if (attrValue.Type() == nsAttrValue::eAtom) {
6768 0 : info->mClasses.AppendElement(attrValue.GetAtomValue());
6769 : }
6770 :
6771 0 : info->mCaseTreatment =
6772 0 : aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
6773 : eIgnoreCase : eCaseMatters;
6774 0 : return info;
6775 : }
6776 :
6777 : // static
6778 : bool
6779 4 : nsContentUtils::IsFocusedContent(const nsIContent* aContent)
6780 : {
6781 4 : nsFocusManager* fm = nsFocusManager::GetFocusManager();
6782 :
6783 4 : return fm && fm->GetFocusedContent() == aContent;
6784 : }
6785 :
6786 : bool
6787 0 : nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
6788 : {
6789 : //XXXsmaug Shadow DOM spec issue!
6790 : // We may need to change this to GetComposedDoc().
6791 0 : nsIDocument* doc = aContent->GetUncomposedDoc();
6792 0 : if (!doc) {
6793 0 : return false;
6794 : }
6795 :
6796 : // If the subdocument lives in another process, the frame is
6797 : // tabbable.
6798 0 : if (EventStateManager::IsRemoteTarget(aContent)) {
6799 0 : return true;
6800 : }
6801 :
6802 : // XXXbz should this use OwnerDoc() for GetSubDocumentFor?
6803 : // sXBL/XBL2 issue!
6804 0 : nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
6805 0 : if (!subDoc) {
6806 0 : return false;
6807 : }
6808 :
6809 0 : nsCOMPtr<nsIDocShell> docShell = subDoc->GetDocShell();
6810 0 : if (!docShell) {
6811 0 : return false;
6812 : }
6813 :
6814 0 : nsCOMPtr<nsIContentViewer> contentViewer;
6815 0 : docShell->GetContentViewer(getter_AddRefs(contentViewer));
6816 0 : if (!contentViewer) {
6817 0 : return false;
6818 : }
6819 :
6820 0 : nsCOMPtr<nsIContentViewer> zombieViewer;
6821 0 : contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
6822 :
6823 : // If there are 2 viewers for the current docshell, that
6824 : // means the current document is a zombie document.
6825 : // Only navigate into the subdocument if it's not a zombie.
6826 0 : return !zombieViewer;
6827 : }
6828 :
6829 : bool
6830 17 : nsContentUtils::IsUserFocusIgnored(nsINode* aNode)
6831 : {
6832 17 : if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) {
6833 0 : return false;
6834 : }
6835 :
6836 : // Check if our mozbrowser iframe ancestors has ignoreuserfocus attribute.
6837 51 : while (aNode) {
6838 34 : nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aNode);
6839 17 : if (browserFrame &&
6840 17 : aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::ignoreuserfocus) &&
6841 0 : browserFrame->GetReallyIsBrowser()) {
6842 0 : return true;
6843 : }
6844 17 : nsPIDOMWindowOuter* win = aNode->OwnerDoc()->GetWindow();
6845 17 : aNode = win ? win->GetFrameElementInternal() : nullptr;
6846 : }
6847 :
6848 17 : return false;
6849 : }
6850 :
6851 : bool
6852 268 : nsContentUtils::HasScrollgrab(nsIContent* aContent)
6853 : {
6854 : // If we ever standardize this feature we'll want to hook this up properly
6855 : // again. For now we're removing all the DOM-side code related to it but
6856 : // leaving the layout and APZ handling for it in place.
6857 268 : return false;
6858 : }
6859 :
6860 : void
6861 0 : nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow)
6862 : {
6863 0 : if (!aWindow) {
6864 0 : return;
6865 : }
6866 :
6867 : // Note that because FlushPendingNotifications flushes parents, this
6868 : // is O(N^2) in docshell tree depth. However, the docshell tree is
6869 : // usually pretty shallow.
6870 :
6871 0 : if (nsCOMPtr<nsIDocument> doc = aWindow->GetDoc()) {
6872 0 : doc->FlushPendingNotifications(FlushType::Layout);
6873 : }
6874 :
6875 0 : if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
6876 0 : int32_t i = 0, i_end;
6877 0 : docShell->GetChildCount(&i_end);
6878 0 : for (; i < i_end; ++i) {
6879 0 : nsCOMPtr<nsIDocShellTreeItem> item;
6880 0 : docShell->GetChildAt(i, getter_AddRefs(item));
6881 0 : if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
6882 0 : FlushLayoutForTree(win);
6883 : }
6884 : }
6885 : }
6886 : }
6887 :
6888 12 : void nsContentUtils::RemoveNewlines(nsString &aString)
6889 : {
6890 12 : aString.StripCRLF();
6891 12 : }
6892 :
6893 : void
6894 0 : nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
6895 : {
6896 0 : if (!PlatformToDOMLineBreaks(aString, fallible)) {
6897 0 : aString.AllocFailed(aString.Length());
6898 : }
6899 0 : }
6900 :
6901 : bool
6902 6 : nsContentUtils::PlatformToDOMLineBreaks(nsString& aString, const fallible_t& aFallible)
6903 : {
6904 6 : if (aString.FindChar(char16_t('\r')) != -1) {
6905 : // Windows linebreaks: Map CRLF to LF:
6906 0 : if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
6907 0 : return false;
6908 : }
6909 :
6910 : // Mac linebreaks: Map any remaining CR to LF:
6911 0 : if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
6912 0 : return false;
6913 : }
6914 : }
6915 :
6916 6 : return true;
6917 : }
6918 :
6919 : void
6920 0 : nsContentUtils::PopulateStringFromStringBuffer(nsStringBuffer* aBuf,
6921 : nsAString& aResultString)
6922 : {
6923 0 : MOZ_ASSERT(aBuf, "Expecting a non-null string buffer");
6924 :
6925 0 : uint32_t stringLen = NS_strlen(static_cast<char16_t*>(aBuf->Data()));
6926 :
6927 : // SANITY CHECK: In case the nsStringBuffer isn't correctly
6928 : // null-terminated, let's clamp its length using the allocated size, to be
6929 : // sure the resulting string doesn't sample past the end of the the buffer.
6930 : // (Note that StorageSize() is in units of bytes, so we have to convert that
6931 : // to units of PRUnichars, and subtract 1 for the null-terminator.)
6932 0 : uint32_t allocStringLen = (aBuf->StorageSize() / sizeof(char16_t)) - 1;
6933 0 : MOZ_ASSERT(stringLen <= allocStringLen,
6934 : "string buffer lacks null terminator!");
6935 0 : stringLen = std::min(stringLen, allocStringLen);
6936 :
6937 0 : aBuf->ToString(stringLen, aResultString);
6938 0 : }
6939 :
6940 : nsIPresShell*
6941 0 : nsContentUtils::FindPresShellForDocument(const nsIDocument* aDoc)
6942 : {
6943 0 : const nsIDocument* doc = aDoc;
6944 0 : nsIDocument* displayDoc = doc->GetDisplayDocument();
6945 0 : if (displayDoc) {
6946 0 : doc = displayDoc;
6947 : }
6948 :
6949 0 : nsIPresShell* shell = doc->GetShell();
6950 0 : if (shell) {
6951 0 : return shell;
6952 : }
6953 :
6954 0 : nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
6955 0 : while (docShellTreeItem) {
6956 : // We may be in a display:none subdocument, or we may not have a presshell
6957 : // created yet.
6958 : // Walk the docshell tree to find the nearest container that has a presshell,
6959 : // and return that.
6960 0 : nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
6961 0 : nsIPresShell* presShell = docShell->GetPresShell();
6962 0 : if (presShell) {
6963 0 : return presShell;
6964 : }
6965 0 : nsCOMPtr<nsIDocShellTreeItem> parent;
6966 0 : docShellTreeItem->GetParent(getter_AddRefs(parent));
6967 0 : docShellTreeItem = parent;
6968 : }
6969 :
6970 0 : return nullptr;
6971 : }
6972 :
6973 : nsIWidget*
6974 0 : nsContentUtils::WidgetForDocument(const nsIDocument* aDoc)
6975 : {
6976 0 : nsIPresShell* shell = FindPresShellForDocument(aDoc);
6977 0 : if (shell) {
6978 0 : nsViewManager* VM = shell->GetViewManager();
6979 0 : if (VM) {
6980 0 : nsView* rootView = VM->GetRootView();
6981 0 : if (rootView) {
6982 0 : nsView* displayRoot = nsViewManager::GetDisplayRootFor(rootView);
6983 0 : if (displayRoot) {
6984 0 : return displayRoot->GetNearestWidget(nullptr);
6985 : }
6986 : }
6987 : }
6988 : }
6989 :
6990 0 : return nullptr;
6991 : }
6992 :
6993 : nsIWidget*
6994 44 : nsContentUtils::WidgetForContent(const nsIContent* aContent)
6995 : {
6996 44 : nsIFrame* frame = aContent->GetPrimaryFrame();
6997 44 : if (frame) {
6998 44 : frame = nsLayoutUtils::GetDisplayRootFrame(frame);
6999 :
7000 44 : nsView* view = frame->GetView();
7001 44 : if (view) {
7002 44 : return view->GetWidget();
7003 : }
7004 : }
7005 :
7006 0 : return nullptr;
7007 : }
7008 :
7009 : already_AddRefed<LayerManager>
7010 3 : nsContentUtils::LayerManagerForContent(const nsIContent *aContent)
7011 : {
7012 3 : nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
7013 3 : if (widget) {
7014 6 : RefPtr<LayerManager> manager = widget->GetLayerManager();
7015 3 : return manager.forget();
7016 : }
7017 :
7018 0 : return nullptr;
7019 : }
7020 :
7021 : static already_AddRefed<LayerManager>
7022 0 : LayerManagerForDocumentInternal(const nsIDocument *aDoc, bool aRequirePersistent)
7023 : {
7024 0 : nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
7025 0 : if (widget) {
7026 : RefPtr<LayerManager> manager =
7027 : widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
7028 0 : nsIWidget::LAYER_MANAGER_CURRENT);
7029 0 : return manager.forget();
7030 : }
7031 :
7032 0 : return nullptr;
7033 : }
7034 :
7035 : already_AddRefed<LayerManager>
7036 0 : nsContentUtils::LayerManagerForDocument(const nsIDocument *aDoc)
7037 : {
7038 0 : return LayerManagerForDocumentInternal(aDoc, false);
7039 : }
7040 :
7041 : already_AddRefed<LayerManager>
7042 0 : nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc)
7043 : {
7044 0 : return LayerManagerForDocumentInternal(aDoc, true);
7045 : }
7046 :
7047 : bool
7048 35 : nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
7049 : {
7050 35 : if (IsSystemPrincipal(aPrincipal)) {
7051 22 : return true;
7052 : }
7053 :
7054 26 : nsCOMPtr<nsIURI> princURI;
7055 13 : aPrincipal->GetURI(getter_AddRefs(princURI));
7056 :
7057 13 : return princURI &&
7058 13 : ((sAllowXULXBL_for_file && SchemeIs(princURI, "file")) ||
7059 39 : IsSitePermAllow(aPrincipal, "allowXULXBL"));
7060 : }
7061 :
7062 : bool
7063 0 : nsContentUtils::IsPDFJSEnabled()
7064 : {
7065 : nsCOMPtr<nsIStreamConverterService> convServ =
7066 0 : do_GetService("@mozilla.org/streamConverters;1");
7067 0 : nsresult rv = NS_ERROR_FAILURE;
7068 0 : bool canConvert = false;
7069 0 : if (convServ) {
7070 0 : rv = convServ->CanConvert("application/pdf", "text/html", &canConvert);
7071 : }
7072 0 : return NS_SUCCEEDED(rv) && canConvert;
7073 : }
7074 :
7075 : already_AddRefed<nsIDocumentLoaderFactory>
7076 12 : nsContentUtils::FindInternalContentViewer(const nsACString& aType,
7077 : ContentViewerType* aLoaderType)
7078 : {
7079 12 : if (aLoaderType) {
7080 4 : *aLoaderType = TYPE_UNSUPPORTED;
7081 : }
7082 :
7083 : // one helper factory, please
7084 24 : nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
7085 12 : if (!catMan)
7086 0 : return nullptr;
7087 :
7088 24 : nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
7089 :
7090 24 : nsXPIDLCString contractID;
7091 36 : nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers",
7092 24 : PromiseFlatCString(aType).get(),
7093 36 : getter_Copies(contractID));
7094 12 : if (NS_SUCCEEDED(rv)) {
7095 12 : docFactory = do_GetService(contractID);
7096 12 : if (docFactory && aLoaderType) {
7097 4 : if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID))
7098 4 : *aLoaderType = TYPE_CONTENT;
7099 0 : else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID))
7100 0 : *aLoaderType = TYPE_PLUGIN;
7101 : else
7102 0 : *aLoaderType = TYPE_UNKNOWN;
7103 : }
7104 12 : return docFactory.forget();
7105 : }
7106 :
7107 0 : if (DecoderTraits::IsSupportedInVideoDocument(aType)) {
7108 0 : docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
7109 0 : if (docFactory && aLoaderType) {
7110 0 : *aLoaderType = TYPE_CONTENT;
7111 : }
7112 0 : return docFactory.forget();
7113 : }
7114 :
7115 0 : return nullptr;
7116 : }
7117 :
7118 : static void
7119 0 : ReportPatternCompileFailure(nsAString& aPattern, nsIDocument* aDocument,
7120 : JSContext* cx)
7121 : {
7122 0 : MOZ_ASSERT(JS_IsExceptionPending(cx));
7123 :
7124 0 : JS::RootedValue exn(cx);
7125 0 : if (!JS_GetPendingException(cx, &exn)) {
7126 0 : return;
7127 : }
7128 0 : if (!exn.isObject()) {
7129 : // If pending exception is not an object, it should be OOM.
7130 0 : return;
7131 : }
7132 :
7133 0 : JS::AutoSaveExceptionState savedExc(cx);
7134 0 : JS::RootedObject exnObj(cx, &exn.toObject());
7135 0 : JS::RootedValue messageVal(cx);
7136 0 : if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
7137 0 : return;
7138 : }
7139 0 : MOZ_ASSERT(messageVal.isString());
7140 :
7141 0 : JS::RootedString messageStr(cx, messageVal.toString());
7142 0 : MOZ_ASSERT(messageStr);
7143 :
7144 0 : nsAutoString wideMessage;
7145 0 : if (!AssignJSString(cx, wideMessage, messageStr)) {
7146 0 : return;
7147 : }
7148 :
7149 0 : const nsString& pattern = PromiseFlatString(aPattern);
7150 0 : const char16_t *strings[] = { pattern.get(), wideMessage.get() };
7151 0 : nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
7152 0 : NS_LITERAL_CSTRING("DOM"),
7153 : aDocument,
7154 : nsContentUtils::eDOM_PROPERTIES,
7155 : "PatternAttributeCompileFailure",
7156 0 : strings, ArrayLength(strings));
7157 0 : savedExc.drop();
7158 : }
7159 :
7160 : // static
7161 : bool
7162 0 : nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
7163 : nsIDocument* aDocument)
7164 : {
7165 0 : NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
7166 :
7167 0 : AutoJSAPI jsapi;
7168 0 : jsapi.Init();
7169 0 : JSContext* cx = jsapi.cx();
7170 :
7171 : // We can use the junk scope here, because we're just using it for
7172 : // regexp evaluation, not actual script execution.
7173 0 : JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope());
7174 :
7175 : // The pattern has to match the entire value.
7176 0 : aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
7177 0 : aPattern.AppendLiteral(")$");
7178 :
7179 : JS::Rooted<JSObject*> re(cx,
7180 0 : JS_NewUCRegExpObject(cx,
7181 0 : static_cast<char16_t*>(aPattern.BeginWriting()),
7182 0 : aPattern.Length(), JSREG_UNICODE));
7183 0 : if (!re) {
7184 : // Remove extra patterns added above to report with the original pattern.
7185 0 : aPattern.Cut(0, 4);
7186 0 : aPattern.Cut(aPattern.Length() - 2, 2);
7187 0 : ReportPatternCompileFailure(aPattern, aDocument, cx);
7188 0 : return true;
7189 : }
7190 :
7191 0 : JS::Rooted<JS::Value> rval(cx, JS::NullValue());
7192 0 : size_t idx = 0;
7193 0 : if (!JS_ExecuteRegExpNoStatics(cx, re,
7194 0 : static_cast<char16_t*>(aValue.BeginWriting()),
7195 0 : aValue.Length(), &idx, true, &rval)) {
7196 0 : return true;
7197 : }
7198 :
7199 0 : return !rval.isNull();
7200 : }
7201 :
7202 : // static
7203 : nsresult
7204 143 : nsContentUtils::URIInheritsSecurityContext(nsIURI *aURI, bool *aResult)
7205 : {
7206 : // Note: about:blank URIs do NOT inherit the security context from the
7207 : // current document, which is what this function tests for...
7208 : return NS_URIChainHasFlags(aURI,
7209 : nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
7210 143 : aResult);
7211 : }
7212 :
7213 : // static
7214 : bool
7215 135 : nsContentUtils::ChannelShouldInheritPrincipal(nsIPrincipal* aLoadingPrincipal,
7216 : nsIURI* aURI,
7217 : bool aInheritForAboutBlank,
7218 : bool aForceInherit)
7219 : {
7220 135 : MOZ_ASSERT(aLoadingPrincipal, "Can not check inheritance without a principal");
7221 :
7222 : // Only tell the channel to inherit if it can't provide its own security context.
7223 : //
7224 : // XXX: If this is ever changed, check all callers for what owners
7225 : // they're passing in. In particular, see the code and
7226 : // comments in nsDocShell::LoadURI where we fall back on
7227 : // inheriting the owner if called from chrome. That would be
7228 : // very wrong if this code changed anything but channels that
7229 : // can't provide their own security context!
7230 : //
7231 : // If aForceInherit is true, we will inherit, even for a channel that
7232 : // can provide its own security context. This is used for srcdoc loads.
7233 135 : bool inherit = aForceInherit;
7234 135 : if (!inherit) {
7235 : bool uriInherits;
7236 : // We expect URIInheritsSecurityContext to return success for an
7237 : // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
7238 : // This condition needs to match the one in nsDocShell::InternalLoad where
7239 : // we're checking for things that will use the owner.
7240 135 : inherit =
7241 270 : (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits)) &&
7242 405 : (uriInherits || (aInheritForAboutBlank && NS_IsAboutBlank(aURI)))) ||
7243 : //
7244 : // file: uri special-casing
7245 : //
7246 : // If this is a file: load opened from another file: then it may need
7247 : // to inherit the owner from the referrer so they can script each other.
7248 : // If we don't set the owner explicitly then each file: gets an owner
7249 : // based on its own codebase later.
7250 : //
7251 133 : (URIIsLocalFile(aURI) &&
7252 0 : NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false, false)) &&
7253 : // One more check here. CheckMayLoad will always return true for the
7254 : // system principal, but we do NOT want to inherit in that case.
7255 0 : !IsSystemPrincipal(aLoadingPrincipal));
7256 : }
7257 135 : return inherit;
7258 : }
7259 :
7260 : /* static */
7261 : bool
7262 0 : nsContentUtils::IsFullScreenApiEnabled()
7263 : {
7264 0 : return sIsFullScreenApiEnabled;
7265 : }
7266 :
7267 : /* static */
7268 : bool
7269 0 : nsContentUtils::IsRequestFullScreenAllowed(CallerType aCallerType)
7270 : {
7271 : // If more time has elapsed since the user input than is specified by the
7272 : // dom.event.handling-user-input-time-limit pref (default 1 second), this
7273 : // function also returns false.
7274 :
7275 0 : if (!sTrustedFullScreenOnly || aCallerType == CallerType::System) {
7276 0 : return true;
7277 : }
7278 :
7279 0 : if (EventStateManager::IsHandlingUserInput()) {
7280 0 : TimeDuration timeout = HandlingUserInputTimeout();
7281 0 : return timeout <= TimeDuration(nullptr) ||
7282 0 : (TimeStamp::Now() -
7283 0 : EventStateManager::GetHandlingInputStart()) <= timeout;
7284 : }
7285 :
7286 0 : return false;
7287 : }
7288 :
7289 : /* static */
7290 : bool
7291 0 : nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal)
7292 : {
7293 0 : if (!IsCutCopyRestricted() && EventStateManager::IsHandlingUserInput()) {
7294 0 : return true;
7295 : }
7296 :
7297 0 : return PrincipalHasPermission(aSubjectPrincipal, NS_LITERAL_STRING("clipboardWrite"));
7298 : }
7299 :
7300 : /* static */
7301 : bool
7302 0 : nsContentUtils::IsFrameTimingEnabled()
7303 : {
7304 0 : return sIsFrameTimingPrefEnabled;
7305 : }
7306 :
7307 : /* static */
7308 : bool
7309 0 : nsContentUtils::HaveEqualPrincipals(nsIDocument* aDoc1, nsIDocument* aDoc2)
7310 : {
7311 0 : if (!aDoc1 || !aDoc2) {
7312 0 : return false;
7313 : }
7314 0 : bool principalsEqual = false;
7315 0 : aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
7316 0 : return principalsEqual;
7317 : }
7318 :
7319 : /* static */
7320 : bool
7321 0 : nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
7322 : {
7323 : #ifdef XP_MACOSX
7324 : // We control dispatch to all mac plugins.
7325 : return false;
7326 : #else
7327 0 : if (!aContent || !aContent->IsInUncomposedDoc()) {
7328 0 : return false;
7329 : }
7330 :
7331 0 : nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aContent);
7332 0 : if (!olc) {
7333 0 : return false;
7334 : }
7335 :
7336 0 : RefPtr<nsNPAPIPluginInstance> plugin;
7337 0 : olc->GetPluginInstance(getter_AddRefs(plugin));
7338 0 : if (!plugin) {
7339 0 : return false;
7340 : }
7341 :
7342 0 : bool isWindowless = false;
7343 0 : nsresult res = plugin->IsWindowless(&isWindowless);
7344 0 : if (NS_FAILED(res)) {
7345 0 : return false;
7346 : }
7347 :
7348 0 : return !isWindowless;
7349 : #endif
7350 : }
7351 :
7352 : /* static */
7353 : void
7354 0 : nsContentUtils::FireMutationEventsForDirectParsing(nsIDocument* aDoc,
7355 : nsIContent* aDest,
7356 : int32_t aOldChildCount)
7357 : {
7358 : // Fire mutation events. Optimize for the case when there are no listeners
7359 0 : int32_t newChildCount = aDest->GetChildCount();
7360 0 : if (newChildCount && nsContentUtils::
7361 0 : HasMutationListeners(aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
7362 0 : AutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
7363 0 : NS_ASSERTION(newChildCount - aOldChildCount >= 0,
7364 : "What, some unexpected dom mutation has happened?");
7365 0 : childNodes.SetCapacity(newChildCount - aOldChildCount);
7366 0 : for (nsIContent* child = aDest->GetFirstChild();
7367 0 : child;
7368 0 : child = child->GetNextSibling()) {
7369 0 : childNodes.AppendElement(child);
7370 : }
7371 0 : FragmentOrElement::FireNodeInserted(aDoc, aDest, childNodes);
7372 : }
7373 0 : }
7374 :
7375 : /* static */
7376 : nsIDocument*
7377 1 : nsContentUtils::GetRootDocument(nsIDocument* aDoc)
7378 : {
7379 1 : if (!aDoc) {
7380 0 : return nullptr;
7381 : }
7382 1 : nsIDocument* doc = aDoc;
7383 1 : while (doc->GetParentDocument()) {
7384 0 : doc = doc->GetParentDocument();
7385 : }
7386 1 : return doc;
7387 : }
7388 :
7389 : /* static */
7390 : bool
7391 3 : nsContentUtils::IsInPointerLockContext(nsPIDOMWindowOuter* aWin)
7392 : {
7393 3 : if (!aWin) {
7394 2 : return false;
7395 : }
7396 :
7397 : nsCOMPtr<nsIDocument> pointerLockedDoc =
7398 2 : do_QueryReferent(EventStateManager::sPointerLockedDoc);
7399 1 : if (!pointerLockedDoc || !pointerLockedDoc->GetWindow()) {
7400 1 : return false;
7401 : }
7402 :
7403 : nsCOMPtr<nsPIDOMWindowOuter> lockTop =
7404 0 : pointerLockedDoc->GetWindow()->GetScriptableTop();
7405 0 : nsCOMPtr<nsPIDOMWindowOuter> top = aWin->GetScriptableTop();
7406 :
7407 0 : return top == lockTop;
7408 : }
7409 :
7410 : // static
7411 : int32_t
7412 0 : nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
7413 : int32_t aOffset)
7414 : {
7415 : // The structure of the anonymous frames within a text control frame is
7416 : // an optional block frame, followed by an optional br frame.
7417 :
7418 : // If the offset frame has a child, then this frame is the block which
7419 : // has the text frames (containing the content) as its children. This will
7420 : // be the case if we click to the right of any of the text frames, or at the
7421 : // bottom of the text area.
7422 0 : nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
7423 0 : if (firstChild) {
7424 : // In this case, the passed-in offset is incorrect, and we want the length
7425 : // of the entire content in the text control frame.
7426 0 : return firstChild->GetContent()->Length();
7427 : }
7428 :
7429 0 : if (aOffsetFrame->GetPrevSibling() &&
7430 0 : !aOffsetFrame->GetNextSibling()) {
7431 : // In this case, we're actually within the last frame, which is a br
7432 : // frame. Our offset should therefore be the length of the first child of
7433 : // our parent.
7434 : int32_t aOutOffset =
7435 0 : aOffsetFrame->GetParent()->PrincipalChildList().FirstChild()->GetContent()->Length();
7436 0 : return aOutOffset;
7437 : }
7438 :
7439 : // Otherwise, we're within one of the text frames, in which case our offset
7440 : // has already been correctly calculated.
7441 0 : return aOffset;
7442 : }
7443 :
7444 : // static
7445 : void
7446 3 : nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
7447 : Element* aRoot,
7448 : uint32_t& aOutStartOffset,
7449 : uint32_t& aOutEndOffset)
7450 : {
7451 3 : MOZ_ASSERT(aSelection && aRoot);
7452 :
7453 : // We don't care which end of this selection is anchor and which is focus. In
7454 : // fact, we explicitly want to know which is the _start_ and which is the
7455 : // _end_, not anchor vs focus.
7456 3 : const nsRange* range = aSelection->GetAnchorFocusRange();
7457 3 : if (!range) {
7458 : // Nothing selected
7459 0 : aOutStartOffset = aOutEndOffset = 0;
7460 0 : return;
7461 : }
7462 :
7463 : // All the node pointers here are raw pointers for performance. We shouldn't
7464 : // be doing anything in this function that invalidates the node tree.
7465 3 : nsINode* startContainer = range->GetStartContainer();
7466 3 : uint32_t startOffset = range->StartOffset();
7467 3 : nsINode* endContainer = range->GetEndContainer();
7468 3 : uint32_t endOffset = range->EndOffset();
7469 :
7470 : // We have at most two children, consisting of an optional text node followed
7471 : // by an optional <br>.
7472 3 : NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children");
7473 3 : nsIContent* firstChild = aRoot->GetFirstChild();
7474 : #ifdef DEBUG
7475 6 : nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
7476 3 : NS_ASSERTION(startContainer == aRoot || startContainer == firstChild ||
7477 : startContainer == lastChild, "Unexpected startContainer");
7478 3 : NS_ASSERTION(endContainer == aRoot || endContainer == firstChild ||
7479 : endContainer == lastChild, "Unexpected endContainer");
7480 : // firstChild is either text or a <br> (hence an element).
7481 3 : MOZ_ASSERT_IF(firstChild,
7482 : firstChild->IsNodeOfType(nsINode::eTEXT) || firstChild->IsElement());
7483 : #endif
7484 : // Testing IsElement() is faster than testing IsNodeOfType(), since it's
7485 : // non-virtual.
7486 3 : if (!firstChild || firstChild->IsElement()) {
7487 : // No text node, so everything is 0
7488 1 : startOffset = endOffset = 0;
7489 : } else {
7490 : // First child is text. If the start/end is already in the text node,
7491 : // or the start of the root node, no change needed. If it's in the root
7492 : // node but not the start, or in the trailing <br>, we need to set the
7493 : // offset to the end.
7494 2 : if ((startContainer == aRoot && startOffset != 0) ||
7495 1 : (startContainer != aRoot && startContainer != firstChild)) {
7496 1 : startOffset = firstChild->Length();
7497 : }
7498 2 : if ((endContainer == aRoot && endOffset != 0) ||
7499 1 : (endContainer != aRoot && endContainer != firstChild)) {
7500 1 : endOffset = firstChild->Length();
7501 : }
7502 : }
7503 :
7504 3 : MOZ_ASSERT(startOffset <= endOffset);
7505 3 : aOutStartOffset = startOffset;
7506 3 : aOutEndOffset = endOffset;
7507 : }
7508 :
7509 :
7510 : nsIEditor*
7511 0 : nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext)
7512 : {
7513 0 : nsCOMPtr<nsIDocShell> docShell(aPresContext->GetDocShell());
7514 : bool isEditable;
7515 0 : if (!docShell ||
7516 0 : NS_FAILED(docShell->GetEditable(&isEditable)) || !isEditable)
7517 0 : return nullptr;
7518 :
7519 0 : nsCOMPtr<nsIEditor> editor;
7520 0 : docShell->GetEditor(getter_AddRefs(editor));
7521 0 : return editor;
7522 : }
7523 :
7524 : bool
7525 5720 : nsContentUtils::IsContentInsertionPoint(nsIContent* aContent)
7526 : {
7527 : // Check if the content is a XBL insertion point.
7528 5720 : if (aContent->IsActiveChildrenElement()) {
7529 243 : return true;
7530 : }
7531 :
7532 : // Check if the content is a web components content insertion point.
7533 : HTMLContentElement* contentElement =
7534 5477 : HTMLContentElement::FromContent(aContent);
7535 5477 : return contentElement && contentElement->IsInsertionPoint();
7536 : }
7537 :
7538 : // static
7539 : bool
7540 4002 : nsContentUtils::HasDistributedChildren(nsIContent* aContent)
7541 : {
7542 4002 : if (!aContent) {
7543 0 : return false;
7544 : }
7545 :
7546 4002 : if (aContent->GetShadowRoot()) {
7547 : // Children of a shadow root host are distributed
7548 : // to content insertion points in the shadow root.
7549 0 : return true;
7550 : }
7551 :
7552 4002 : ShadowRoot* shadow = ShadowRoot::FromNode(aContent);
7553 4002 : if (shadow) {
7554 : // Children of a shadow root are distributed to
7555 : // the shadow insertion point of the younger shadow root.
7556 0 : return shadow->GetYoungerShadowRoot();
7557 : }
7558 :
7559 4002 : HTMLShadowElement* shadowEl = HTMLShadowElement::FromContent(aContent);
7560 4002 : if (shadowEl && shadowEl->IsInsertionPoint()) {
7561 : // Children of a shadow insertion points are distributed
7562 : // to the insertion points in the older shadow root.
7563 0 : return shadowEl->GetOlderShadowRoot();
7564 : }
7565 :
7566 4002 : HTMLContentElement* contentEl = HTMLContentElement::FromContent(aContent);
7567 4002 : if (contentEl && contentEl->IsInsertionPoint()) {
7568 : // Children of a content insertion point are distributed to the
7569 : // content insertion point if the content insertion point does
7570 : // not match any nodes (fallback content).
7571 0 : return contentEl->MatchedNodes().IsEmpty();
7572 : }
7573 :
7574 4002 : return false;
7575 : }
7576 :
7577 : // static
7578 : bool
7579 0 : nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader)
7580 : {
7581 0 : if (IsForbiddenSystemRequestHeader(aHeader)) {
7582 0 : return true;
7583 : }
7584 :
7585 0 : return StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"),
7586 0 : nsCaseInsensitiveCStringComparator()) ||
7587 0 : StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"),
7588 0 : nsCaseInsensitiveCStringComparator());
7589 : }
7590 :
7591 : // static
7592 : bool
7593 0 : nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader)
7594 : {
7595 : static const char *kInvalidHeaders[] = {
7596 : "accept-charset", "accept-encoding", "access-control-request-headers",
7597 : "access-control-request-method", "connection", "content-length",
7598 : "cookie", "cookie2", "date", "dnt", "expect", "host", "keep-alive",
7599 : "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", "via"
7600 : };
7601 0 : for (auto& kInvalidHeader : kInvalidHeaders) {
7602 0 : if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
7603 0 : return true;
7604 : }
7605 : }
7606 0 : return false;
7607 : }
7608 :
7609 : // static
7610 : bool
7611 4 : nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader)
7612 : {
7613 7 : return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
7614 7 : aHeader.LowerCaseEqualsASCII("set-cookie2"));
7615 : }
7616 :
7617 : // static
7618 : bool
7619 0 : nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
7620 : {
7621 0 : nsAutoCString contentType;
7622 0 : nsAutoCString unused;
7623 :
7624 0 : nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
7625 0 : if (NS_FAILED(rv)) {
7626 0 : return false;
7627 : }
7628 :
7629 0 : return contentType.LowerCaseEqualsLiteral("text/plain") ||
7630 0 : contentType.LowerCaseEqualsLiteral("application/x-www-form-urlencoded") ||
7631 0 : contentType.LowerCaseEqualsLiteral("multipart/form-data");
7632 : }
7633 :
7634 : bool
7635 1 : nsContentUtils::DOMWindowDumpEnabled()
7636 : {
7637 : #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
7638 : // In optimized builds we check a pref that controls if we should
7639 : // enable output from dump() or not, in debug builds it's always
7640 : // enabled.
7641 : return nsContentUtils::sDOMWindowDumpEnabled;
7642 : #else
7643 1 : return true;
7644 : #endif
7645 : }
7646 :
7647 : bool
7648 6 : nsContentUtils::DoNotTrackEnabled()
7649 : {
7650 6 : return nsContentUtils::sDoNotTrackEnabled;
7651 : }
7652 :
7653 : mozilla::LogModule*
7654 1 : nsContentUtils::DOMDumpLog()
7655 : {
7656 1 : return sDOMDumpLog;
7657 : }
7658 :
7659 : bool
7660 9 : nsContentUtils::GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult,
7661 : const fallible_t& aFallible)
7662 : {
7663 9 : aResult.Truncate();
7664 9 : return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7665 : }
7666 :
7667 : void
7668 1 : nsContentUtils::GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult)
7669 : {
7670 1 : if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
7671 0 : NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
7672 : }
7673 1 : }
7674 :
7675 : void
7676 0 : nsContentUtils::DestroyMatchString(void* aData)
7677 : {
7678 0 : if (aData) {
7679 0 : nsString* matchString = static_cast<nsString*>(aData);
7680 0 : delete matchString;
7681 : }
7682 0 : }
7683 :
7684 : bool
7685 7 : nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType)
7686 : {
7687 : // Table ordered from most to least likely JS MIME types.
7688 : static const char* jsTypes[] = {
7689 : "text/javascript",
7690 : "text/ecmascript",
7691 : "application/javascript",
7692 : "application/ecmascript",
7693 : "application/x-javascript",
7694 : "application/x-ecmascript",
7695 : "text/javascript1.0",
7696 : "text/javascript1.1",
7697 : "text/javascript1.2",
7698 : "text/javascript1.3",
7699 : "text/javascript1.4",
7700 : "text/javascript1.5",
7701 : "text/jscript",
7702 : "text/livescript",
7703 : "text/x-ecmascript",
7704 : "text/x-javascript",
7705 : nullptr
7706 : };
7707 :
7708 11 : for (uint32_t i = 0; jsTypes[i]; ++i) {
7709 11 : if (aMIMEType.LowerCaseEqualsASCII(jsTypes[i])) {
7710 7 : return true;
7711 : }
7712 : }
7713 :
7714 0 : return false;
7715 : }
7716 :
7717 : nsresult
7718 5 : nsContentUtils::GenerateUUIDInPlace(nsID& aUUID)
7719 : {
7720 5 : MOZ_ASSERT(sUUIDGenerator);
7721 :
7722 5 : nsresult rv = sUUIDGenerator->GenerateUUIDInPlace(&aUUID);
7723 5 : if (NS_WARN_IF(NS_FAILED(rv))) {
7724 0 : return rv;
7725 : }
7726 :
7727 5 : return NS_OK;
7728 : }
7729 :
7730 : bool
7731 0 : nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell)
7732 : {
7733 : //
7734 : // SECURITY CHECK: disable prefetching and preloading from mailnews!
7735 : //
7736 : // walk up the docshell tree to see if any containing
7737 : // docshell are of type MAIL.
7738 : //
7739 :
7740 0 : if (!aDocShell) {
7741 0 : return false;
7742 : }
7743 :
7744 0 : nsCOMPtr<nsIDocShell> docshell = aDocShell;
7745 0 : nsCOMPtr<nsIDocShellTreeItem> parentItem;
7746 :
7747 0 : do {
7748 0 : uint32_t appType = 0;
7749 0 : nsresult rv = docshell->GetAppType(&appType);
7750 0 : if (NS_FAILED(rv) || appType == nsIDocShell::APP_TYPE_MAIL) {
7751 0 : return false; // do not prefetch, preload, preconnect from mailnews
7752 : }
7753 :
7754 0 : docshell->GetParent(getter_AddRefs(parentItem));
7755 0 : if (parentItem) {
7756 0 : docshell = do_QueryInterface(parentItem);
7757 0 : if (!docshell) {
7758 0 : NS_ERROR("cannot get a docshell from a treeItem!");
7759 0 : return false;
7760 : }
7761 : }
7762 : } while (parentItem);
7763 :
7764 0 : return true;
7765 : }
7766 :
7767 : uint64_t
7768 0 : nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
7769 : {
7770 : // can't do anything if there's no nsIRequest!
7771 0 : if (!aRequest) {
7772 0 : return 0;
7773 : }
7774 :
7775 0 : nsCOMPtr<nsILoadGroup> loadGroup;
7776 0 : nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
7777 :
7778 0 : if (NS_FAILED(rv) || !loadGroup) {
7779 0 : return 0;
7780 : }
7781 :
7782 0 : return GetInnerWindowID(loadGroup);
7783 : }
7784 :
7785 : uint64_t
7786 2 : nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup)
7787 : {
7788 2 : if (!aLoadGroup) {
7789 0 : return 0;
7790 : }
7791 :
7792 4 : nsCOMPtr<nsIInterfaceRequestor> callbacks;
7793 2 : nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
7794 2 : if (NS_FAILED(rv) || !callbacks) {
7795 0 : return 0;
7796 : }
7797 :
7798 4 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
7799 2 : if (!loadContext) {
7800 0 : return 0;
7801 : }
7802 :
7803 4 : nsCOMPtr<mozIDOMWindowProxy> window;
7804 2 : rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
7805 2 : if (NS_FAILED(rv) || !window) {
7806 1 : return 0;
7807 : }
7808 :
7809 1 : auto* pwindow = nsPIDOMWindowOuter::From(window);
7810 1 : if (!pwindow) {
7811 0 : return 0;
7812 : }
7813 :
7814 1 : nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
7815 1 : return inner ? inner->WindowID() : 0;
7816 : }
7817 :
7818 : nsresult
7819 2 : nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost)
7820 : {
7821 2 : aHost.Truncate();
7822 2 : nsresult rv = aURI->GetHost(aHost);
7823 2 : if (NS_FAILED(rv)) { // Some URIs do not have a host
7824 0 : return rv;
7825 : }
7826 :
7827 2 : if (aHost.FindChar(':') != -1) { // Escape IPv6 address
7828 0 : MOZ_ASSERT(!aHost.Length() ||
7829 : (aHost[0] !='[' && aHost[aHost.Length() - 1] != ']'));
7830 0 : aHost.Insert('[', 0);
7831 0 : aHost.Append(']');
7832 : }
7833 :
7834 2 : return NS_OK;
7835 : }
7836 :
7837 : nsresult
7838 1 : nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost)
7839 : {
7840 2 : nsAutoCString hostname;
7841 1 : nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
7842 1 : if (NS_FAILED(rv)) {
7843 0 : return rv;
7844 : }
7845 1 : CopyUTF8toUTF16(hostname, aHost);
7846 1 : return NS_OK;
7847 : }
7848 :
7849 : bool
7850 4 : nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
7851 : CallOnRemoteChildFunction aCallback,
7852 : void* aArg)
7853 : {
7854 4 : uint32_t tabChildCount = 0;
7855 4 : aManager->GetChildCount(&tabChildCount);
7856 8 : for (uint32_t j = 0; j < tabChildCount; ++j) {
7857 6 : nsCOMPtr<nsIMessageListenerManager> childMM;
7858 4 : aManager->GetChildAt(j, getter_AddRefs(childMM));
7859 4 : if (!childMM) {
7860 0 : continue;
7861 : }
7862 :
7863 6 : nsCOMPtr<nsIMessageBroadcaster> nonLeafMM = do_QueryInterface(childMM);
7864 4 : if (nonLeafMM) {
7865 2 : if (CallOnAllRemoteChildren(nonLeafMM, aCallback, aArg)) {
7866 0 : return true;
7867 : }
7868 2 : continue;
7869 : }
7870 :
7871 4 : nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM);
7872 :
7873 : mozilla::dom::ipc::MessageManagerCallback* cb =
7874 2 : static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback();
7875 2 : if (cb) {
7876 2 : nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
7877 2 : TabParent* remote = TabParent::GetFrom(fl);
7878 2 : if (remote && aCallback) {
7879 2 : if (aCallback(remote, aArg)) {
7880 0 : return true;
7881 : }
7882 : }
7883 : }
7884 : }
7885 :
7886 4 : return false;
7887 : }
7888 :
7889 : void
7890 6 : nsContentUtils::CallOnAllRemoteChildren(nsPIDOMWindowOuter* aWindow,
7891 : CallOnRemoteChildFunction aCallback,
7892 : void* aArg)
7893 : {
7894 12 : nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aWindow));
7895 6 : if (chromeWindow) {
7896 4 : nsCOMPtr<nsIMessageBroadcaster> windowMM;
7897 2 : chromeWindow->GetMessageManager(getter_AddRefs(windowMM));
7898 2 : if (windowMM) {
7899 2 : CallOnAllRemoteChildren(windowMM, aCallback, aArg);
7900 : }
7901 : }
7902 6 : }
7903 :
7904 : struct UIStateChangeInfo {
7905 : UIStateChangeType mShowAccelerators;
7906 : UIStateChangeType mShowFocusRings;
7907 :
7908 1 : UIStateChangeInfo(UIStateChangeType aShowAccelerators,
7909 : UIStateChangeType aShowFocusRings)
7910 1 : : mShowAccelerators(aShowAccelerators),
7911 1 : mShowFocusRings(aShowFocusRings)
7912 1 : {}
7913 : };
7914 :
7915 : bool
7916 0 : SetKeyboardIndicatorsChild(TabParent* aParent, void* aArg)
7917 : {
7918 0 : UIStateChangeInfo* stateInfo = static_cast<UIStateChangeInfo*>(aArg);
7919 0 : Unused << aParent->SendSetKeyboardIndicators(stateInfo->mShowAccelerators,
7920 : stateInfo->mShowFocusRings);
7921 0 : return false;
7922 : }
7923 :
7924 : void
7925 1 : nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(nsPIDOMWindowOuter* aWindow,
7926 : UIStateChangeType aShowAccelerators,
7927 : UIStateChangeType aShowFocusRings)
7928 : {
7929 1 : UIStateChangeInfo stateInfo(aShowAccelerators, aShowFocusRings);
7930 : CallOnAllRemoteChildren(aWindow, SetKeyboardIndicatorsChild,
7931 1 : (void *)&stateInfo);
7932 1 : }
7933 :
7934 : nsresult
7935 0 : nsContentUtils::IPCTransferableToTransferable(const IPCDataTransfer& aDataTransfer,
7936 : const bool& aIsPrivateData,
7937 : nsIPrincipal* aRequestingPrincipal,
7938 : nsITransferable* aTransferable,
7939 : mozilla::dom::nsIContentParent* aContentParent,
7940 : mozilla::dom::TabChild* aTabChild)
7941 : {
7942 : nsresult rv;
7943 :
7944 0 : const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
7945 0 : for (const auto& item : items) {
7946 0 : aTransferable->AddDataFlavor(item.flavor().get());
7947 :
7948 0 : if (item.data().type() == IPCDataTransferData::TnsString) {
7949 : nsCOMPtr<nsISupportsString> dataWrapper =
7950 0 : do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
7951 0 : NS_ENSURE_SUCCESS(rv, rv);
7952 :
7953 0 : const nsString& text = item.data().get_nsString();
7954 0 : rv = dataWrapper->SetData(text);
7955 0 : NS_ENSURE_SUCCESS(rv, rv);
7956 :
7957 0 : rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
7958 0 : text.Length() * sizeof(char16_t));
7959 :
7960 0 : NS_ENSURE_SUCCESS(rv, rv);
7961 0 : } else if (item.data().type() == IPCDataTransferData::TShmem) {
7962 0 : if (nsContentUtils::IsFlavorImage(item.flavor())) {
7963 0 : nsCOMPtr<imgIContainer> imageContainer;
7964 0 : rv = nsContentUtils::DataTransferItemToImage(item,
7965 0 : getter_AddRefs(imageContainer));
7966 0 : NS_ENSURE_SUCCESS(rv, rv);
7967 :
7968 : nsCOMPtr<nsISupportsInterfacePointer> imgPtr =
7969 0 : do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
7970 0 : NS_ENSURE_TRUE(imgPtr, NS_ERROR_FAILURE);
7971 :
7972 0 : rv = imgPtr->SetData(imageContainer);
7973 0 : NS_ENSURE_SUCCESS(rv, rv);
7974 :
7975 0 : aTransferable->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
7976 : } else {
7977 : nsCOMPtr<nsISupportsCString> dataWrapper =
7978 0 : do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
7979 0 : NS_ENSURE_SUCCESS(rv, rv);
7980 :
7981 : // The buffer contains the terminating null.
7982 0 : Shmem itemData = item.data().get_Shmem();
7983 0 : const nsDependentCString text(itemData.get<char>(),
7984 0 : itemData.Size<char>());
7985 0 : rv = dataWrapper->SetData(text);
7986 0 : NS_ENSURE_SUCCESS(rv, rv);
7987 :
7988 0 : rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
7989 :
7990 0 : NS_ENSURE_SUCCESS(rv, rv);
7991 : }
7992 :
7993 0 : if (aContentParent) {
7994 0 : Unused << aContentParent->DeallocShmem(item.data().get_Shmem());
7995 0 : } else if (aTabChild) {
7996 0 : Unused << aTabChild->DeallocShmem(item.data().get_Shmem());
7997 : }
7998 : }
7999 : }
8000 :
8001 0 : aTransferable->SetIsPrivateData(aIsPrivateData);
8002 0 : aTransferable->SetRequestingPrincipal(aRequestingPrincipal);
8003 0 : return NS_OK;
8004 : }
8005 :
8006 : void
8007 0 : nsContentUtils::TransferablesToIPCTransferables(nsIArray* aTransferables,
8008 : nsTArray<IPCDataTransfer>& aIPC,
8009 : bool aInSyncMessage,
8010 : mozilla::dom::nsIContentChild* aChild,
8011 : mozilla::dom::nsIContentParent* aParent)
8012 : {
8013 0 : aIPC.Clear();
8014 0 : if (aTransferables) {
8015 0 : uint32_t transferableCount = 0;
8016 0 : aTransferables->GetLength(&transferableCount);
8017 0 : for (uint32_t i = 0; i < transferableCount; ++i) {
8018 0 : IPCDataTransfer* dt = aIPC.AppendElement();
8019 0 : nsCOMPtr<nsITransferable> transferable = do_QueryElementAt(aTransferables, i);
8020 0 : TransferableToIPCTransferable(transferable, dt, aInSyncMessage, aChild, aParent);
8021 : }
8022 : }
8023 0 : }
8024 :
8025 : nsresult
8026 0 : nsContentUtils::SlurpFileToString(nsIFile* aFile, nsACString& aString)
8027 : {
8028 0 : aString.Truncate();
8029 :
8030 0 : nsCOMPtr<nsIURI> fileURI;
8031 0 : nsresult rv = NS_NewFileURI(getter_AddRefs(fileURI), aFile);
8032 0 : if (NS_FAILED(rv)) {
8033 0 : return rv;
8034 : }
8035 :
8036 0 : nsCOMPtr<nsIChannel> channel;
8037 0 : rv = NS_NewChannel(getter_AddRefs(channel),
8038 : fileURI,
8039 : nsContentUtils::GetSystemPrincipal(),
8040 : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
8041 0 : nsIContentPolicy::TYPE_OTHER);
8042 0 : if (NS_FAILED(rv)) {
8043 0 : return rv;
8044 : }
8045 :
8046 0 : nsCOMPtr<nsIInputStream> stream;
8047 0 : rv = channel->Open2(getter_AddRefs(stream));
8048 0 : if (NS_FAILED(rv)) {
8049 0 : return rv;
8050 : }
8051 :
8052 0 : rv = NS_ConsumeStream(stream, UINT32_MAX, aString);
8053 0 : if (NS_FAILED(rv)) {
8054 0 : return rv;
8055 : }
8056 :
8057 0 : rv = stream->Close();
8058 0 : if (NS_FAILED(rv)) {
8059 0 : return rv;
8060 : }
8061 :
8062 0 : return NS_OK;
8063 : }
8064 :
8065 : bool
8066 0 : nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
8067 : {
8068 0 : nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
8069 0 : if (!mime) {
8070 0 : return false;
8071 : }
8072 :
8073 0 : nsresult rv = mime->GetTypeFromFile(aFile, aType);
8074 0 : if (NS_FAILED(rv)) {
8075 0 : return false;
8076 : }
8077 :
8078 0 : return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
8079 : }
8080 :
8081 : nsresult
8082 0 : nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
8083 : imgIContainer** aContainer)
8084 : {
8085 0 : MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TShmem);
8086 0 : MOZ_ASSERT(IsFlavorImage(aItem.flavor()));
8087 :
8088 0 : const IPCDataTransferImage& imageDetails = aItem.imageDetails();
8089 0 : const IntSize size(imageDetails.width(), imageDetails.height());
8090 0 : if (!size.width || !size.height) {
8091 0 : return NS_ERROR_FAILURE;
8092 : }
8093 :
8094 0 : Shmem data = aItem.data().get_Shmem();
8095 :
8096 : RefPtr<DataSourceSurface> image =
8097 0 : CreateDataSourceSurfaceFromData(size,
8098 0 : static_cast<SurfaceFormat>(imageDetails.format()),
8099 0 : data.get<uint8_t>(),
8100 0 : imageDetails.stride());
8101 :
8102 0 : RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
8103 : nsCOMPtr<imgIContainer> imageContainer =
8104 0 : image::ImageOps::CreateFromDrawable(drawable);
8105 0 : imageContainer.forget(aContainer);
8106 :
8107 0 : return NS_OK;
8108 : }
8109 :
8110 : bool
8111 0 : nsContentUtils::IsFlavorImage(const nsACString& aFlavor)
8112 : {
8113 0 : return aFlavor.EqualsLiteral(kNativeImageMime) ||
8114 0 : aFlavor.EqualsLiteral(kJPEGImageMime) ||
8115 0 : aFlavor.EqualsLiteral(kJPGImageMime) ||
8116 0 : aFlavor.EqualsLiteral(kPNGImageMime) ||
8117 0 : aFlavor.EqualsLiteral(kGIFImageMime);
8118 : }
8119 :
8120 : static Shmem
8121 0 : ConvertToShmem(mozilla::dom::nsIContentChild* aChild,
8122 : mozilla::dom::nsIContentParent* aParent,
8123 : const nsACString& aInput)
8124 : {
8125 0 : MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
8126 :
8127 : IShmemAllocator* allocator =
8128 0 : aChild ? static_cast<IShmemAllocator*>(aChild)
8129 0 : : static_cast<IShmemAllocator*>(aParent);
8130 :
8131 0 : Shmem result;
8132 0 : if (!allocator->AllocShmem(aInput.Length() + 1,
8133 : SharedMemory::TYPE_BASIC,
8134 0 : &result)) {
8135 0 : return result;
8136 : }
8137 :
8138 0 : memcpy(result.get<char>(),
8139 0 : aInput.BeginReading(),
8140 0 : aInput.Length() + 1);
8141 :
8142 0 : return result;
8143 : }
8144 :
8145 : void
8146 0 : nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
8147 : IPCDataTransfer* aIPCDataTransfer,
8148 : bool aInSyncMessage,
8149 : mozilla::dom::nsIContentChild* aChild,
8150 : mozilla::dom::nsIContentParent* aParent)
8151 : {
8152 0 : MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
8153 :
8154 0 : if (aTransferable) {
8155 0 : nsCOMPtr<nsIArray> flavorList;
8156 0 : aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
8157 0 : if (flavorList) {
8158 0 : uint32_t flavorCount = 0;
8159 0 : flavorList->GetLength(&flavorCount);
8160 0 : for (uint32_t j = 0; j < flavorCount; ++j) {
8161 0 : nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
8162 0 : if (!flavor) {
8163 0 : continue;
8164 : }
8165 :
8166 0 : nsAutoCString flavorStr;
8167 0 : flavor->GetData(flavorStr);
8168 0 : if (!flavorStr.Length()) {
8169 0 : continue;
8170 : }
8171 :
8172 0 : nsCOMPtr<nsISupports> data;
8173 0 : uint32_t dataLen = 0;
8174 0 : aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
8175 :
8176 0 : nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
8177 0 : nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
8178 0 : if (text) {
8179 0 : nsAutoString dataAsString;
8180 0 : text->GetData(dataAsString);
8181 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8182 0 : item->flavor() = flavorStr;
8183 0 : item->data() = dataAsString;
8184 0 : } else if (ctext) {
8185 0 : nsAutoCString dataAsString;
8186 0 : ctext->GetData(dataAsString);
8187 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8188 0 : item->flavor() = flavorStr;
8189 :
8190 0 : Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
8191 0 : if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
8192 0 : continue;
8193 : }
8194 :
8195 0 : item->data() = dataAsShmem;
8196 : } else {
8197 : nsCOMPtr<nsISupportsInterfacePointer> sip =
8198 0 : do_QueryInterface(data);
8199 0 : if (sip) {
8200 0 : sip->GetData(getter_AddRefs(data));
8201 : }
8202 :
8203 : // Images to be pasted on the clipboard are nsIInputStreams
8204 0 : nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
8205 0 : if (stream) {
8206 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8207 0 : item->flavor() = flavorStr;
8208 :
8209 0 : nsCString imageData;
8210 0 : NS_ConsumeStream(stream, UINT32_MAX, imageData);
8211 :
8212 0 : Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
8213 0 : if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
8214 0 : continue;
8215 : }
8216 :
8217 0 : item->data() = imageDataShmem;
8218 0 : continue;
8219 : }
8220 :
8221 : // Images to be placed on the clipboard are imgIContainers.
8222 0 : nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
8223 0 : if (image) {
8224 : RefPtr<mozilla::gfx::SourceSurface> surface =
8225 0 : image->GetFrame(imgIContainer::FRAME_CURRENT,
8226 0 : imgIContainer::FLAG_SYNC_DECODE);
8227 0 : if (!surface) {
8228 0 : continue;
8229 : }
8230 : RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
8231 0 : surface->GetDataSurface();
8232 0 : if (!dataSurface) {
8233 0 : continue;
8234 : }
8235 : size_t length;
8236 : int32_t stride;
8237 0 : IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
8238 0 : : static_cast<IShmemAllocator*>(aParent);
8239 : Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
8240 0 : allocator);
8241 :
8242 0 : if (surfaceData.isNothing()) {
8243 0 : continue;
8244 : }
8245 :
8246 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8247 0 : item->flavor() = flavorStr;
8248 : // Turn item->data() into an nsCString prior to accessing it.
8249 0 : item->data() = surfaceData.ref();
8250 :
8251 0 : IPCDataTransferImage& imageDetails = item->imageDetails();
8252 0 : mozilla::gfx::IntSize size = dataSurface->GetSize();
8253 0 : imageDetails.width() = size.width;
8254 0 : imageDetails.height() = size.height;
8255 0 : imageDetails.stride() = stride;
8256 0 : imageDetails.format() = static_cast<uint8_t>(dataSurface->GetFormat());
8257 :
8258 0 : continue;
8259 : }
8260 :
8261 : // Otherwise, handle this as a file.
8262 0 : nsCOMPtr<BlobImpl> blobImpl;
8263 0 : nsCOMPtr<nsIFile> file = do_QueryInterface(data);
8264 0 : if (file) {
8265 : // If we can send this over as a blob, do so. Otherwise, we're
8266 : // responding to a sync message and the child can't process the blob
8267 : // constructor before processing our response, which would crash. In
8268 : // that case, hope that the caller is nsClipboardProxy::GetData,
8269 : // called from editor and send over images as raw data.
8270 0 : if (aInSyncMessage) {
8271 0 : nsAutoCString type;
8272 0 : if (IsFileImage(file, type)) {
8273 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8274 0 : item->flavor() = type;
8275 0 : nsAutoCString data;
8276 0 : SlurpFileToString(file, data);
8277 :
8278 0 : Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
8279 0 : item->data() = dataAsShmem;
8280 : }
8281 :
8282 0 : continue;
8283 : }
8284 :
8285 0 : if (aParent) {
8286 0 : bool isDir = false;
8287 0 : if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
8288 0 : nsAutoString path;
8289 0 : if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
8290 0 : continue;
8291 : }
8292 :
8293 0 : RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
8294 0 : fss->GrantAccessToContentProcess(aParent->ChildID(), path);
8295 : }
8296 : }
8297 :
8298 0 : blobImpl = new FileBlobImpl(file);
8299 :
8300 0 : IgnoredErrorResult rv;
8301 :
8302 : // Ensure that file data is cached no that the content process
8303 : // has this data available to it when passed over:
8304 0 : blobImpl->GetSize(rv);
8305 0 : if (NS_WARN_IF(rv.Failed())) {
8306 0 : continue;
8307 : }
8308 :
8309 0 : blobImpl->GetLastModified(rv);
8310 0 : if (NS_WARN_IF(rv.Failed())) {
8311 0 : continue;
8312 : }
8313 : } else {
8314 0 : if (aInSyncMessage) {
8315 : // Can't do anything.
8316 0 : continue;
8317 : }
8318 0 : blobImpl = do_QueryInterface(data);
8319 : }
8320 0 : if (blobImpl) {
8321 0 : IPCDataTransferData data;
8322 0 : IPCBlob ipcBlob;
8323 :
8324 : // If we failed to create the blob actor, then this blob probably
8325 : // can't get the file size for the underlying file, ignore it for
8326 : // now. TODO pass this through anyway.
8327 0 : if (aChild) {
8328 0 : nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
8329 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
8330 0 : continue;
8331 : }
8332 :
8333 0 : data = ipcBlob;
8334 0 : } else if (aParent) {
8335 0 : nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
8336 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
8337 0 : continue;
8338 : }
8339 :
8340 0 : data = ipcBlob;
8341 : }
8342 :
8343 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8344 0 : item->flavor() = flavorStr;
8345 0 : item->data() = data;
8346 : } else {
8347 : // This is a hack to support kFilePromiseMime.
8348 : // On Windows there just needs to be an entry for it,
8349 : // and for OSX we need to create
8350 : // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
8351 0 : if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
8352 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8353 0 : item->flavor() = flavorStr;
8354 0 : item->data() = NS_ConvertUTF8toUTF16(flavorStr);
8355 0 : } else if (!data) {
8356 : // Empty element, transfer only the flavor
8357 0 : IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
8358 0 : item->flavor() = flavorStr;
8359 0 : item->data() = nsString();
8360 0 : continue;
8361 : }
8362 : }
8363 : }
8364 : }
8365 : }
8366 : }
8367 0 : }
8368 :
8369 : namespace {
8370 : // The default type used for calling GetSurfaceData(). Gets surface data as
8371 : // raw buffer.
8372 : struct GetSurfaceDataRawBuffer
8373 : {
8374 : using ReturnType = mozilla::UniquePtr<char[]>;
8375 : using BufferType = char*;
8376 :
8377 0 : ReturnType Allocate(size_t aSize)
8378 : {
8379 0 : return ReturnType(new char[aSize]);
8380 : }
8381 :
8382 : static BufferType
8383 0 : GetBuffer(const ReturnType& aReturnValue)
8384 : {
8385 0 : return aReturnValue.get();
8386 : }
8387 :
8388 : static ReturnType
8389 0 : NullValue()
8390 : {
8391 0 : return ReturnType();
8392 : }
8393 : };
8394 :
8395 : // The type used for calling GetSurfaceData() that allocates and writes to
8396 : // a shared memory buffer.
8397 : struct GetSurfaceDataShmem
8398 : {
8399 : using ReturnType = Maybe<Shmem>;
8400 : using BufferType = char*;
8401 :
8402 0 : explicit GetSurfaceDataShmem(IShmemAllocator* aAllocator)
8403 0 : : mAllocator(aAllocator)
8404 0 : { }
8405 :
8406 0 : ReturnType Allocate(size_t aSize)
8407 : {
8408 0 : Shmem shmem;
8409 0 : if (!mAllocator->AllocShmem(aSize, SharedMemory::TYPE_BASIC, &shmem)) {
8410 0 : return Nothing();
8411 : }
8412 :
8413 0 : return Some(shmem);
8414 : }
8415 :
8416 : static BufferType
8417 0 : GetBuffer(const ReturnType& aReturnValue)
8418 : {
8419 0 : return aReturnValue.isSome() ? aReturnValue.ref().get<char>() : nullptr;
8420 : }
8421 :
8422 : static ReturnType
8423 0 : NullValue()
8424 : {
8425 0 : return ReturnType();
8426 : }
8427 : private:
8428 : IShmemAllocator* mAllocator;
8429 : };
8430 :
8431 : /*
8432 : * Get the pixel data from the given source surface and return it as a buffer.
8433 : * The length and stride will be assigned from the surface.
8434 : */
8435 : template <typename GetSurfaceDataContext = GetSurfaceDataRawBuffer>
8436 : typename GetSurfaceDataContext::ReturnType
8437 0 : GetSurfaceDataImpl(mozilla::gfx::DataSourceSurface* aSurface,
8438 : size_t* aLength, int32_t* aStride,
8439 : GetSurfaceDataContext aContext = GetSurfaceDataContext())
8440 : {
8441 : mozilla::gfx::DataSourceSurface::MappedSurface map;
8442 0 : if (!aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
8443 0 : return GetSurfaceDataContext::NullValue();
8444 : }
8445 :
8446 0 : mozilla::gfx::IntSize size = aSurface->GetSize();
8447 : mozilla::CheckedInt32 requiredBytes =
8448 0 : mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
8449 0 : if (!requiredBytes.isValid()) {
8450 0 : return GetSurfaceDataContext::NullValue();
8451 : }
8452 :
8453 0 : size_t maxBufLen = requiredBytes.value();
8454 0 : mozilla::gfx::SurfaceFormat format = aSurface->GetFormat();
8455 :
8456 : // Surface data handling is totally nuts. This is the magic one needs to
8457 : // know to access the data.
8458 0 : size_t bufLen = maxBufLen - map.mStride + (size.width * BytesPerPixel(format));
8459 :
8460 : // nsDependentCString wants null-terminated string.
8461 0 : typename GetSurfaceDataContext::ReturnType surfaceData = aContext.Allocate(maxBufLen + 1);
8462 0 : if (GetSurfaceDataContext::GetBuffer(surfaceData)) {
8463 0 : memcpy(GetSurfaceDataContext::GetBuffer(surfaceData),
8464 0 : reinterpret_cast<char*>(map.mData),
8465 : bufLen);
8466 0 : memset(GetSurfaceDataContext::GetBuffer(surfaceData) + bufLen,
8467 : 0,
8468 0 : maxBufLen - bufLen + 1);
8469 : }
8470 :
8471 0 : *aLength = maxBufLen;
8472 0 : *aStride = map.mStride;
8473 :
8474 0 : aSurface->Unmap();
8475 0 : return surfaceData;
8476 : }
8477 : } // Anonymous namespace.
8478 :
8479 : mozilla::UniquePtr<char[]>
8480 0 : nsContentUtils::GetSurfaceData(
8481 : NotNull<mozilla::gfx::DataSourceSurface*> aSurface,
8482 : size_t* aLength, int32_t* aStride)
8483 : {
8484 0 : return GetSurfaceDataImpl(aSurface, aLength, aStride);
8485 : }
8486 :
8487 : Maybe<Shmem>
8488 0 : nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
8489 : size_t* aLength, int32_t* aStride,
8490 : IShmemAllocator* aAllocator)
8491 : {
8492 : return GetSurfaceDataImpl(aSurface, aLength, aStride,
8493 0 : GetSurfaceDataShmem(aAllocator));
8494 : }
8495 :
8496 : mozilla::Modifiers
8497 0 : nsContentUtils::GetWidgetModifiers(int32_t aModifiers)
8498 : {
8499 0 : Modifiers result = 0;
8500 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
8501 0 : result |= mozilla::MODIFIER_SHIFT;
8502 : }
8503 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
8504 0 : result |= mozilla::MODIFIER_CONTROL;
8505 : }
8506 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
8507 0 : result |= mozilla::MODIFIER_ALT;
8508 : }
8509 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
8510 0 : result |= mozilla::MODIFIER_META;
8511 : }
8512 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
8513 0 : result |= mozilla::MODIFIER_ALTGRAPH;
8514 : }
8515 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
8516 0 : result |= mozilla::MODIFIER_CAPSLOCK;
8517 : }
8518 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
8519 0 : result |= mozilla::MODIFIER_FN;
8520 : }
8521 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
8522 0 : result |= mozilla::MODIFIER_FNLOCK;
8523 : }
8524 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
8525 0 : result |= mozilla::MODIFIER_NUMLOCK;
8526 : }
8527 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
8528 0 : result |= mozilla::MODIFIER_SCROLLLOCK;
8529 : }
8530 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
8531 0 : result |= mozilla::MODIFIER_SYMBOL;
8532 : }
8533 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
8534 0 : result |= mozilla::MODIFIER_SYMBOLLOCK;
8535 : }
8536 0 : if (aModifiers & nsIDOMWindowUtils::MODIFIER_OS) {
8537 0 : result |= mozilla::MODIFIER_OS;
8538 : }
8539 0 : return result;
8540 : }
8541 :
8542 : nsIWidget*
8543 0 : nsContentUtils::GetWidget(nsIPresShell* aPresShell, nsPoint* aOffset) {
8544 0 : if (aPresShell) {
8545 0 : nsIFrame* frame = aPresShell->GetRootFrame();
8546 0 : if (frame)
8547 0 : return frame->GetView()->GetNearestWidget(aOffset);
8548 : }
8549 0 : return nullptr;
8550 : }
8551 :
8552 : int16_t
8553 0 : nsContentUtils::GetButtonsFlagForButton(int32_t aButton)
8554 : {
8555 0 : switch (aButton) {
8556 : case -1:
8557 0 : return WidgetMouseEvent::eNoButtonFlag;
8558 : case WidgetMouseEvent::eLeftButton:
8559 0 : return WidgetMouseEvent::eLeftButtonFlag;
8560 : case WidgetMouseEvent::eMiddleButton:
8561 0 : return WidgetMouseEvent::eMiddleButtonFlag;
8562 : case WidgetMouseEvent::eRightButton:
8563 0 : return WidgetMouseEvent::eRightButtonFlag;
8564 : case 4:
8565 0 : return WidgetMouseEvent::e4thButtonFlag;
8566 : case 5:
8567 0 : return WidgetMouseEvent::e5thButtonFlag;
8568 : default:
8569 0 : NS_ERROR("Button not known.");
8570 0 : return 0;
8571 : }
8572 : }
8573 :
8574 : LayoutDeviceIntPoint
8575 0 : nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
8576 : const nsPoint& aOffset,
8577 : nsPresContext* aPresContext)
8578 : {
8579 : return LayoutDeviceIntPoint::FromAppUnitsRounded(
8580 0 : (CSSPoint::ToAppUnits(aPoint) +
8581 0 : aOffset).ApplyResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(aPresContext->PresShell())),
8582 0 : aPresContext->AppUnitsPerDevPixel());
8583 : }
8584 :
8585 : nsView*
8586 0 : nsContentUtils::GetViewToDispatchEvent(nsPresContext* presContext,
8587 : nsIPresShell** presShell)
8588 : {
8589 0 : if (presContext && presShell) {
8590 0 : *presShell = presContext->PresShell();
8591 0 : if (*presShell) {
8592 0 : NS_ADDREF(*presShell);
8593 0 : if (nsViewManager* viewManager = (*presShell)->GetViewManager()) {
8594 0 : if (nsView* view = viewManager->GetRootView()) {
8595 0 : return view;
8596 : }
8597 : }
8598 : }
8599 : }
8600 0 : return nullptr;
8601 : }
8602 :
8603 : nsresult
8604 0 : nsContentUtils::SendKeyEvent(nsIWidget* aWidget,
8605 : const nsAString& aType,
8606 : int32_t aKeyCode,
8607 : int32_t aCharCode,
8608 : int32_t aModifiers,
8609 : uint32_t aAdditionalFlags,
8610 : bool* aDefaultActionTaken)
8611 : {
8612 : // get the widget to send the event to
8613 0 : if (!aWidget)
8614 0 : return NS_ERROR_FAILURE;
8615 :
8616 : EventMessage msg;
8617 0 : if (aType.EqualsLiteral("keydown"))
8618 0 : msg = eKeyDown;
8619 0 : else if (aType.EqualsLiteral("keyup"))
8620 0 : msg = eKeyUp;
8621 0 : else if (aType.EqualsLiteral("keypress"))
8622 0 : msg = eKeyPress;
8623 : else
8624 0 : return NS_ERROR_FAILURE;
8625 :
8626 0 : WidgetKeyboardEvent event(true, msg, aWidget);
8627 0 : event.mModifiers = GetWidgetModifiers(aModifiers);
8628 :
8629 0 : if (msg == eKeyPress) {
8630 0 : event.mKeyCode = aCharCode ? 0 : aKeyCode;
8631 0 : event.mCharCode = aCharCode;
8632 : } else {
8633 0 : event.mKeyCode = aKeyCode;
8634 0 : event.mCharCode = 0;
8635 : }
8636 :
8637 : uint32_t locationFlag = (aAdditionalFlags &
8638 : (nsIDOMWindowUtils::KEY_FLAG_LOCATION_STANDARD | nsIDOMWindowUtils::KEY_FLAG_LOCATION_LEFT |
8639 0 : nsIDOMWindowUtils::KEY_FLAG_LOCATION_RIGHT | nsIDOMWindowUtils::KEY_FLAG_LOCATION_NUMPAD));
8640 0 : switch (locationFlag) {
8641 : case nsIDOMWindowUtils::KEY_FLAG_LOCATION_STANDARD:
8642 0 : event.mLocation = eKeyLocationStandard;
8643 0 : break;
8644 : case nsIDOMWindowUtils::KEY_FLAG_LOCATION_LEFT:
8645 0 : event.mLocation = eKeyLocationLeft;
8646 0 : break;
8647 : case nsIDOMWindowUtils::KEY_FLAG_LOCATION_RIGHT:
8648 0 : event.mLocation = eKeyLocationRight;
8649 0 : break;
8650 : case nsIDOMWindowUtils::KEY_FLAG_LOCATION_NUMPAD:
8651 0 : event.mLocation = eKeyLocationNumpad;
8652 0 : break;
8653 : default:
8654 0 : if (locationFlag != 0) {
8655 0 : return NS_ERROR_INVALID_ARG;
8656 : }
8657 : // If location flag isn't set, choose the location from keycode.
8658 0 : switch (aKeyCode) {
8659 : case nsIDOMKeyEvent::DOM_VK_NUMPAD0:
8660 : case nsIDOMKeyEvent::DOM_VK_NUMPAD1:
8661 : case nsIDOMKeyEvent::DOM_VK_NUMPAD2:
8662 : case nsIDOMKeyEvent::DOM_VK_NUMPAD3:
8663 : case nsIDOMKeyEvent::DOM_VK_NUMPAD4:
8664 : case nsIDOMKeyEvent::DOM_VK_NUMPAD5:
8665 : case nsIDOMKeyEvent::DOM_VK_NUMPAD6:
8666 : case nsIDOMKeyEvent::DOM_VK_NUMPAD7:
8667 : case nsIDOMKeyEvent::DOM_VK_NUMPAD8:
8668 : case nsIDOMKeyEvent::DOM_VK_NUMPAD9:
8669 : case nsIDOMKeyEvent::DOM_VK_MULTIPLY:
8670 : case nsIDOMKeyEvent::DOM_VK_ADD:
8671 : case nsIDOMKeyEvent::DOM_VK_SEPARATOR:
8672 : case nsIDOMKeyEvent::DOM_VK_SUBTRACT:
8673 : case nsIDOMKeyEvent::DOM_VK_DECIMAL:
8674 : case nsIDOMKeyEvent::DOM_VK_DIVIDE:
8675 0 : event.mLocation = eKeyLocationNumpad;
8676 0 : break;
8677 : case nsIDOMKeyEvent::DOM_VK_SHIFT:
8678 : case nsIDOMKeyEvent::DOM_VK_CONTROL:
8679 : case nsIDOMKeyEvent::DOM_VK_ALT:
8680 : case nsIDOMKeyEvent::DOM_VK_META:
8681 0 : event.mLocation = eKeyLocationLeft;
8682 0 : break;
8683 : default:
8684 0 : event.mLocation = eKeyLocationStandard;
8685 0 : break;
8686 : }
8687 0 : break;
8688 : }
8689 :
8690 0 : event.mRefPoint = LayoutDeviceIntPoint(0, 0);
8691 0 : event.mTime = PR_IntervalNow();
8692 0 : if (!(aAdditionalFlags & nsIDOMWindowUtils::KEY_FLAG_NOT_SYNTHESIZED_FOR_TESTS)) {
8693 0 : event.mFlags.mIsSynthesizedForTests = true;
8694 : }
8695 :
8696 0 : if (aAdditionalFlags & nsIDOMWindowUtils::KEY_FLAG_PREVENT_DEFAULT) {
8697 0 : event.PreventDefaultBeforeDispatch();
8698 : }
8699 :
8700 : nsEventStatus status;
8701 0 : nsresult rv = aWidget->DispatchEvent(&event, status);
8702 0 : NS_ENSURE_SUCCESS(rv, rv);
8703 :
8704 0 : *aDefaultActionTaken = (status != nsEventStatus_eConsumeNoDefault);
8705 :
8706 0 : return NS_OK;
8707 : }
8708 :
8709 : nsresult
8710 0 : nsContentUtils::SendMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell,
8711 : const nsAString& aType,
8712 : float aX,
8713 : float aY,
8714 : int32_t aButton,
8715 : int32_t aButtons,
8716 : int32_t aClickCount,
8717 : int32_t aModifiers,
8718 : bool aIgnoreRootScrollFrame,
8719 : float aPressure,
8720 : unsigned short aInputSourceArg,
8721 : uint32_t aIdentifier,
8722 : bool aToWindow,
8723 : bool *aPreventDefault,
8724 : bool aIsDOMEventSynthesized,
8725 : bool aIsWidgetEventSynthesized)
8726 : {
8727 0 : nsPoint offset;
8728 0 : nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
8729 0 : if (!widget)
8730 0 : return NS_ERROR_FAILURE;
8731 :
8732 : EventMessage msg;
8733 0 : WidgetMouseEvent::ExitFrom exitFrom = WidgetMouseEvent::eChild;
8734 0 : bool contextMenuKey = false;
8735 0 : if (aType.EqualsLiteral("mousedown")) {
8736 0 : msg = eMouseDown;
8737 0 : } else if (aType.EqualsLiteral("mouseup")) {
8738 0 : msg = eMouseUp;
8739 0 : } else if (aType.EqualsLiteral("mousemove")) {
8740 0 : msg = eMouseMove;
8741 0 : } else if (aType.EqualsLiteral("mouseover")) {
8742 0 : msg = eMouseEnterIntoWidget;
8743 0 : } else if (aType.EqualsLiteral("mouseout")) {
8744 0 : msg = eMouseExitFromWidget;
8745 0 : } else if (aType.EqualsLiteral("mousecancel")) {
8746 0 : msg = eMouseExitFromWidget;
8747 0 : exitFrom = WidgetMouseEvent::eTopLevel;
8748 0 : } else if (aType.EqualsLiteral("mouselongtap")) {
8749 0 : msg = eMouseLongTap;
8750 0 : } else if (aType.EqualsLiteral("contextmenu")) {
8751 0 : msg = eContextMenu;
8752 0 : contextMenuKey = (aButton == 0);
8753 0 : } else if (aType.EqualsLiteral("MozMouseHittest")) {
8754 0 : msg = eMouseHitTest;
8755 : } else {
8756 0 : return NS_ERROR_FAILURE;
8757 : }
8758 :
8759 0 : if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
8760 0 : aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
8761 : }
8762 :
8763 : WidgetMouseEvent event(true, msg, widget,
8764 : aIsWidgetEventSynthesized ?
8765 : WidgetMouseEvent::eSynthesized :
8766 : WidgetMouseEvent::eReal,
8767 : contextMenuKey ? WidgetMouseEvent::eContextMenuKey :
8768 0 : WidgetMouseEvent::eNormal);
8769 0 : event.pointerId = aIdentifier;
8770 0 : event.mModifiers = GetWidgetModifiers(aModifiers);
8771 0 : event.button = aButton;
8772 0 : event.buttons = aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ?
8773 : aButtons :
8774 0 : msg == eMouseUp ? 0 : GetButtonsFlagForButton(aButton);
8775 0 : event.pressure = aPressure;
8776 0 : event.inputSource = aInputSourceArg;
8777 0 : event.mClickCount = aClickCount;
8778 0 : event.mTime = PR_IntervalNow();
8779 0 : event.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
8780 0 : event.mExitFrom = exitFrom;
8781 :
8782 0 : nsPresContext* presContext = aPresShell->GetPresContext();
8783 0 : if (!presContext)
8784 0 : return NS_ERROR_FAILURE;
8785 :
8786 0 : event.mRefPoint = ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
8787 0 : event.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
8788 :
8789 0 : nsEventStatus status = nsEventStatus_eIgnore;
8790 0 : if (aToWindow) {
8791 0 : nsCOMPtr<nsIPresShell> presShell;
8792 0 : nsView* view = GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
8793 0 : if (!presShell || !view) {
8794 0 : return NS_ERROR_FAILURE;
8795 : }
8796 0 : return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
8797 : }
8798 0 : if (gfxPrefs::TestEventsAsyncEnabled()) {
8799 0 : status = widget->DispatchInputEvent(&event);
8800 : } else {
8801 0 : nsresult rv = widget->DispatchEvent(&event, status);
8802 0 : NS_ENSURE_SUCCESS(rv, rv);
8803 : }
8804 0 : if (aPreventDefault) {
8805 0 : *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
8806 : }
8807 :
8808 0 : return NS_OK;
8809 : }
8810 :
8811 : /* static */
8812 : void
8813 0 : nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
8814 : EventTarget* aChromeEventHandler)
8815 : {
8816 0 : nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
8817 0 : NS_ASSERTION(doc, "What happened here?");
8818 0 : doc->OnPageHide(true, aChromeEventHandler);
8819 :
8820 0 : int32_t childCount = 0;
8821 0 : aItem->GetChildCount(&childCount);
8822 0 : AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8823 0 : kids.AppendElements(childCount);
8824 0 : for (int32_t i = 0; i < childCount; ++i) {
8825 0 : aItem->GetChildAt(i, getter_AddRefs(kids[i]));
8826 : }
8827 :
8828 0 : for (uint32_t i = 0; i < kids.Length(); ++i) {
8829 0 : if (kids[i]) {
8830 0 : FirePageHideEvent(kids[i], aChromeEventHandler);
8831 : }
8832 : }
8833 0 : }
8834 :
8835 : // The pageshow event is fired for a given document only if IsShowing() returns
8836 : // the same thing as aFireIfShowing. This gives us a way to fire pageshow only
8837 : // on documents that are still loading or only on documents that are already
8838 : // loaded.
8839 : /* static */
8840 : void
8841 0 : nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
8842 : EventTarget* aChromeEventHandler,
8843 : bool aFireIfShowing)
8844 : {
8845 0 : int32_t childCount = 0;
8846 0 : aItem->GetChildCount(&childCount);
8847 0 : AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
8848 0 : kids.AppendElements(childCount);
8849 0 : for (int32_t i = 0; i < childCount; ++i) {
8850 0 : aItem->GetChildAt(i, getter_AddRefs(kids[i]));
8851 : }
8852 :
8853 0 : for (uint32_t i = 0; i < kids.Length(); ++i) {
8854 0 : if (kids[i]) {
8855 0 : FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
8856 : }
8857 : }
8858 :
8859 0 : nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
8860 0 : NS_ASSERTION(doc, "What happened here?");
8861 0 : if (doc->IsShowing() == aFireIfShowing) {
8862 0 : doc->OnPageShow(true, aChromeEventHandler);
8863 : }
8864 0 : }
8865 :
8866 : /* static */
8867 : already_AddRefed<nsPIWindowRoot>
8868 5 : nsContentUtils::GetWindowRoot(nsIDocument* aDoc)
8869 : {
8870 5 : if (aDoc) {
8871 5 : if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
8872 5 : return win->GetTopWindowRoot();
8873 : }
8874 : }
8875 0 : return nullptr;
8876 : }
8877 :
8878 : /* static */
8879 : bool
8880 1268 : nsContentUtils::IsPreloadType(nsContentPolicyType aType)
8881 : {
8882 1268 : if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
8883 1254 : aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
8884 : aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
8885 14 : return true;
8886 : }
8887 1254 : return false;
8888 : }
8889 :
8890 : nsresult
8891 0 : nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
8892 : nsIDocument* aDoc,
8893 : nsIHttpChannel* aChannel,
8894 : mozilla::net::ReferrerPolicy aReferrerPolicy)
8895 : {
8896 0 : NS_ENSURE_ARG_POINTER(aPrincipal);
8897 0 : NS_ENSURE_ARG_POINTER(aChannel);
8898 :
8899 0 : nsCOMPtr<nsIURI> principalURI;
8900 :
8901 0 : if (IsSystemPrincipal(aPrincipal)) {
8902 0 : return NS_OK;
8903 : }
8904 :
8905 0 : aPrincipal->GetURI(getter_AddRefs(principalURI));
8906 :
8907 0 : if (!aDoc) {
8908 0 : return aChannel->SetReferrerWithPolicy(principalURI, aReferrerPolicy);
8909 : }
8910 :
8911 : // If it weren't for history.push/replaceState, we could just use the
8912 : // principal's URI here. But since we want changes to the URI effected
8913 : // by push/replaceState to be reflected in the XHR referrer, we have to
8914 : // be more clever.
8915 : //
8916 : // If the document's original URI (before any push/replaceStates) matches
8917 : // our principal, then we use the document's current URI (after
8918 : // push/replaceStates). Otherwise (if the document is, say, a data:
8919 : // URI), we just use the principal's URI.
8920 0 : nsCOMPtr<nsIURI> docCurURI = aDoc->GetDocumentURI();
8921 0 : nsCOMPtr<nsIURI> docOrigURI = aDoc->GetOriginalURI();
8922 :
8923 0 : nsCOMPtr<nsIURI> referrerURI;
8924 :
8925 0 : if (principalURI && docCurURI && docOrigURI) {
8926 0 : bool equal = false;
8927 0 : principalURI->Equals(docOrigURI, &equal);
8928 0 : if (equal) {
8929 0 : referrerURI = docCurURI;
8930 : }
8931 : }
8932 :
8933 0 : if (!referrerURI) {
8934 0 : referrerURI = principalURI;
8935 : }
8936 :
8937 0 : return aChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
8938 : }
8939 :
8940 : // static
8941 : net::ReferrerPolicy
8942 0 : nsContentUtils::GetReferrerPolicyFromHeader(const nsAString& aHeader)
8943 : {
8944 : // Multiple headers could be concatenated into one comma-separated
8945 : // list of policies. Need to tokenize the multiple headers.
8946 0 : nsCharSeparatedTokenizer tokenizer(aHeader, ',');
8947 0 : nsAutoString token;
8948 0 : net::ReferrerPolicy referrerPolicy = mozilla::net::RP_Unset;
8949 0 : while (tokenizer.hasMoreTokens()) {
8950 0 : token = tokenizer.nextToken();
8951 0 : if (token.IsEmpty()) {
8952 0 : continue;
8953 : }
8954 0 : net::ReferrerPolicy policy = net::ReferrerPolicyFromString(token);
8955 0 : if (policy != net::RP_Unset) {
8956 0 : referrerPolicy = policy;
8957 : }
8958 : }
8959 0 : return referrerPolicy;
8960 : }
8961 :
8962 : // static
8963 : bool
8964 1 : nsContentUtils::PromiseRejectionEventsEnabled(JSContext* aCx, JSObject* aObj)
8965 : {
8966 1 : if (NS_IsMainThread()) {
8967 0 : return Preferences::GetBool("dom.promise_rejection_events.enabled", false);
8968 : }
8969 :
8970 : using namespace workers;
8971 :
8972 : // Otherwise, check the pref via the WorkerPrivate
8973 1 : WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
8974 1 : if (!workerPrivate) {
8975 0 : return false;
8976 : }
8977 :
8978 1 : return workerPrivate->PromiseRejectionEventsEnabled();
8979 : }
8980 :
8981 : // static
8982 : bool
8983 4 : nsContentUtils::PushEnabled(JSContext* aCx, JSObject* aObj)
8984 : {
8985 4 : if (NS_IsMainThread()) {
8986 0 : return Preferences::GetBool("dom.push.enabled", false);
8987 : }
8988 :
8989 : using namespace workers;
8990 :
8991 : // Otherwise, check the pref via the WorkerPrivate
8992 4 : WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
8993 4 : if (!workerPrivate) {
8994 0 : return false;
8995 : }
8996 :
8997 4 : return workerPrivate->PushEnabled();
8998 : }
8999 :
9000 : // static
9001 : bool
9002 10 : nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel)
9003 : {
9004 10 : nsLoadFlags loadFlags = 0;
9005 10 : aChannel->GetLoadFlags(&loadFlags);
9006 10 : if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
9007 2 : return true;
9008 : }
9009 :
9010 16 : nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
9011 8 : if (!loadInfo) {
9012 0 : return false;
9013 : }
9014 8 : nsContentPolicyType type = loadInfo->InternalContentPolicyType();
9015 8 : return type == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
9016 8 : type == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
9017 : }
9018 :
9019 : // static, public
9020 : nsContentUtils::StorageAccess
9021 0 : nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
9022 : {
9023 0 : MOZ_ASSERT(aWindow->IsInnerWindow());
9024 :
9025 0 : if (nsIDocument* document = aWindow->GetExtantDoc()) {
9026 0 : nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
9027 0 : return InternalStorageAllowedForPrincipal(principal, aWindow);
9028 : }
9029 :
9030 0 : return StorageAccess::eDeny;
9031 : }
9032 :
9033 : // static, public
9034 : nsContentUtils::StorageAccess
9035 0 : nsContentUtils::StorageAllowedForPrincipal(nsIPrincipal* aPrincipal)
9036 : {
9037 0 : return InternalStorageAllowedForPrincipal(aPrincipal, nullptr);
9038 : }
9039 :
9040 : // static, private
9041 : void
9042 0 : nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
9043 : uint32_t* aLifetimePolicy,
9044 : uint32_t* aBehavior)
9045 : {
9046 0 : *aLifetimePolicy = sCookiesLifetimePolicy;
9047 0 : *aBehavior = sCookiesBehavior;
9048 :
9049 : // Any permissions set for the given principal will override our default
9050 : // settings from preferences.
9051 : nsCOMPtr<nsIPermissionManager> permissionManager =
9052 0 : services::GetPermissionManager();
9053 0 : if (!permissionManager) {
9054 0 : return;
9055 : }
9056 :
9057 : uint32_t perm;
9058 0 : permissionManager->TestPermissionFromPrincipal(aPrincipal, "cookie", &perm);
9059 0 : switch (perm) {
9060 : case nsICookiePermission::ACCESS_ALLOW:
9061 0 : *aBehavior = nsICookieService::BEHAVIOR_ACCEPT;
9062 0 : *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
9063 0 : break;
9064 : case nsICookiePermission::ACCESS_DENY:
9065 0 : *aBehavior = nsICookieService::BEHAVIOR_REJECT;
9066 0 : *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
9067 0 : break;
9068 : case nsICookiePermission::ACCESS_SESSION:
9069 0 : *aBehavior = nsICookieService::BEHAVIOR_ACCEPT;
9070 0 : *aLifetimePolicy = nsICookieService::ACCEPT_SESSION;
9071 0 : break;
9072 : case nsICookiePermission::ACCESS_ALLOW_FIRST_PARTY_ONLY:
9073 0 : *aBehavior = nsICookieService::BEHAVIOR_REJECT_FOREIGN;
9074 : // NOTE: The decision was made here to override the lifetime policy to be
9075 : // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
9076 : // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
9077 : // specific domain. As BEHAVIOR_REJECT_FOREIGN isn't visible in our UI,
9078 : // this is probably not an issue.
9079 0 : *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
9080 0 : break;
9081 : case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
9082 0 : *aBehavior = nsICookieService::BEHAVIOR_LIMIT_FOREIGN;
9083 : // NOTE: The decision was made here to override the lifetime policy to be
9084 : // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
9085 : // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
9086 : // specific domain. As BEHAVIOR_LIMIT_FOREIGN isn't visible in our UI,
9087 : // this is probably not an issue.
9088 0 : *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
9089 0 : break;
9090 : }
9091 : }
9092 :
9093 : // static, private
9094 : nsContentUtils::StorageAccess
9095 0 : nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
9096 : nsPIDOMWindowInner* aWindow)
9097 : {
9098 0 : MOZ_ASSERT(aPrincipal);
9099 0 : MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
9100 :
9101 0 : StorageAccess access = StorageAccess::eAllow;
9102 :
9103 : // We don't allow storage on the null principal, in general. Even if the
9104 : // calling context is chrome.
9105 0 : if (aPrincipal->GetIsNullPrincipal()) {
9106 0 : return StorageAccess::eDeny;
9107 : }
9108 :
9109 0 : if (aWindow) {
9110 : // If the document is sandboxed, then it is not permitted to use storage
9111 0 : nsIDocument* document = aWindow->GetExtantDoc();
9112 0 : if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) {
9113 0 : return StorageAccess::eDeny;
9114 : }
9115 :
9116 : // Check if we are in private browsing, and record that fact
9117 0 : if (IsInPrivateBrowsing(document)) {
9118 0 : access = StorageAccess::ePrivateBrowsing;
9119 : }
9120 : }
9121 :
9122 : uint32_t lifetimePolicy;
9123 : uint32_t behavior;
9124 0 : GetCookieBehaviorForPrincipal(aPrincipal, &lifetimePolicy, &behavior);
9125 :
9126 : // Check if we should only allow storage for the session, and record that fact
9127 0 : if (lifetimePolicy == nsICookieService::ACCEPT_SESSION) {
9128 : // Storage could be StorageAccess::ePrivateBrowsing or StorageAccess::eAllow
9129 : // so perform a std::min comparison to make sure we preserve ePrivateBrowsing
9130 : // if it has been set.
9131 0 : access = std::min(StorageAccess::eSessionScoped, access);
9132 : }
9133 :
9134 : // About URIs are allowed to access storage, even if they don't have chrome
9135 : // privileges. If this is not desired, than the consumer will have to
9136 : // implement their own restriction functionality.
9137 : //
9138 : // This is due to backwards-compatibility and the state of storage access before
9139 : // the introducton of nsContentUtils::InternalStorageAllowedForPrincipal:
9140 : //
9141 : // BEFORE:
9142 : // localStorage, caches: allowed in 3rd-party iframes always
9143 : // IndexedDB: allowed in 3rd-party iframes only if 3rd party URI is an about:
9144 : // URI within a specific whitelist
9145 : //
9146 : // AFTER:
9147 : // localStorage, caches: allowed in 3rd-party iframes by default. Preference
9148 : // can be set to disable in 3rd-party, which will not disallow in about: URIs.
9149 : // IndexedDB: allowed in 3rd-party iframes by default. Preference can be set to
9150 : // disable in 3rd-party, which will disallow in about: URIs, unless they are
9151 : // within a specific whitelist.
9152 : //
9153 : // This means that behavior for storage with internal about: URIs should not be
9154 : // affected, which is desireable due to the lack of automated testing for about:
9155 : // URIs with these preferences set, and the importance of the correct functioning
9156 : // of these URIs even with custom preferences.
9157 0 : nsCOMPtr<nsIURI> uri;
9158 0 : nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
9159 0 : if (NS_SUCCEEDED(rv) && uri) {
9160 0 : bool isAbout = false;
9161 0 : MOZ_ALWAYS_SUCCEEDS(uri->SchemeIs("about", &isAbout));
9162 0 : if (isAbout) {
9163 0 : return access;
9164 : }
9165 : }
9166 :
9167 : // We don't want to prompt for every attempt to access permissions.
9168 0 : if (behavior == nsICookieService::BEHAVIOR_REJECT) {
9169 0 : return StorageAccess::eDeny;
9170 : }
9171 :
9172 : // In the absense of a window, we assume that we are first-party.
9173 0 : if (aWindow && (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
9174 0 : behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN)) {
9175 : nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
9176 0 : do_GetService(THIRDPARTYUTIL_CONTRACTID);
9177 0 : MOZ_ASSERT(thirdPartyUtil);
9178 :
9179 0 : bool thirdPartyWindow = false;
9180 0 : if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow(
9181 0 : aWindow->GetOuterWindow(), nullptr, &thirdPartyWindow)) && thirdPartyWindow) {
9182 : // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
9183 : // simply rejecting the request to use the storage. In the future, if we
9184 : // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
9185 : // for non-cookie storage types, this may change.
9186 :
9187 0 : return StorageAccess::eDeny;
9188 : }
9189 : }
9190 :
9191 0 : return access;
9192 : }
9193 :
9194 : namespace {
9195 :
9196 : // We put StringBuilder in the anonymous namespace to prevent anything outside
9197 : // this file from accidentally being linked against it.
9198 :
9199 : class StringBuilder
9200 : {
9201 : private:
9202 : // Try to keep the size of StringBuilder close to a jemalloc bucket size.
9203 : static const uint32_t STRING_BUFFER_UNITS = 1020;
9204 : class Unit
9205 : {
9206 : public:
9207 0 : Unit() : mAtom(nullptr), mType(eUnknown), mLength(0)
9208 : {
9209 0 : MOZ_COUNT_CTOR(StringBuilder::Unit);
9210 0 : }
9211 0 : ~Unit()
9212 0 : {
9213 0 : if (mType == eString || mType == eStringWithEncode) {
9214 0 : delete mString;
9215 : }
9216 0 : MOZ_COUNT_DTOR(StringBuilder::Unit);
9217 0 : }
9218 :
9219 : enum Type
9220 : {
9221 : eUnknown,
9222 : eAtom,
9223 : eString,
9224 : eStringWithEncode,
9225 : eLiteral,
9226 : eTextFragment,
9227 : eTextFragmentWithEncode,
9228 : };
9229 :
9230 : union
9231 : {
9232 : nsIAtom* mAtom;
9233 : const char* mLiteral;
9234 : nsAutoString* mString;
9235 : const nsTextFragment* mTextFragment;
9236 : };
9237 : Type mType;
9238 : uint32_t mLength;
9239 : };
9240 : public:
9241 0 : StringBuilder() : mLast(this), mLength(0)
9242 : {
9243 0 : MOZ_COUNT_CTOR(StringBuilder);
9244 0 : }
9245 :
9246 0 : ~StringBuilder()
9247 0 : {
9248 0 : MOZ_COUNT_DTOR(StringBuilder);
9249 0 : }
9250 :
9251 0 : void Append(nsIAtom* aAtom)
9252 : {
9253 0 : Unit* u = AddUnit();
9254 0 : u->mAtom = aAtom;
9255 0 : u->mType = Unit::eAtom;
9256 0 : uint32_t len = aAtom->GetLength();
9257 0 : u->mLength = len;
9258 0 : mLength += len;
9259 0 : }
9260 :
9261 : template<int N>
9262 0 : void Append(const char (&aLiteral)[N])
9263 : {
9264 0 : Unit* u = AddUnit();
9265 0 : u->mLiteral = aLiteral;
9266 0 : u->mType = Unit::eLiteral;
9267 0 : uint32_t len = N - 1;
9268 0 : u->mLength = len;
9269 0 : mLength += len;
9270 0 : }
9271 :
9272 : template<int N>
9273 : void Append(char (&aLiteral)[N])
9274 : {
9275 : Unit* u = AddUnit();
9276 : u->mLiteral = aLiteral;
9277 : u->mType = Unit::eLiteral;
9278 : uint32_t len = N - 1;
9279 : u->mLength = len;
9280 : mLength += len;
9281 : }
9282 :
9283 0 : void Append(const nsAString& aString)
9284 : {
9285 0 : Unit* u = AddUnit();
9286 0 : u->mString = new nsAutoString(aString);
9287 0 : u->mType = Unit::eString;
9288 0 : uint32_t len = aString.Length();
9289 0 : u->mLength = len;
9290 0 : mLength += len;
9291 0 : }
9292 :
9293 0 : void Append(nsAutoString* aString)
9294 : {
9295 0 : Unit* u = AddUnit();
9296 0 : u->mString = aString;
9297 0 : u->mType = Unit::eString;
9298 0 : uint32_t len = aString->Length();
9299 0 : u->mLength = len;
9300 0 : mLength += len;
9301 0 : }
9302 :
9303 0 : void AppendWithAttrEncode(nsAutoString* aString, uint32_t aLen)
9304 : {
9305 0 : Unit* u = AddUnit();
9306 0 : u->mString = aString;
9307 0 : u->mType = Unit::eStringWithEncode;
9308 0 : u->mLength = aLen;
9309 0 : mLength += aLen;
9310 0 : }
9311 :
9312 0 : void Append(const nsTextFragment* aTextFragment)
9313 : {
9314 0 : Unit* u = AddUnit();
9315 0 : u->mTextFragment = aTextFragment;
9316 0 : u->mType = Unit::eTextFragment;
9317 0 : uint32_t len = aTextFragment->GetLength();
9318 0 : u->mLength = len;
9319 0 : mLength += len;
9320 0 : }
9321 :
9322 0 : void AppendWithEncode(const nsTextFragment* aTextFragment, uint32_t aLen)
9323 : {
9324 0 : Unit* u = AddUnit();
9325 0 : u->mTextFragment = aTextFragment;
9326 0 : u->mType = Unit::eTextFragmentWithEncode;
9327 0 : u->mLength = aLen;
9328 0 : mLength += aLen;
9329 0 : }
9330 :
9331 0 : bool ToString(nsAString& aOut)
9332 : {
9333 0 : if (!aOut.SetCapacity(mLength, fallible)) {
9334 0 : return false;
9335 : }
9336 :
9337 0 : for (StringBuilder* current = this; current; current = current->mNext) {
9338 0 : uint32_t len = current->mUnits.Length();
9339 0 : for (uint32_t i = 0; i < len; ++i) {
9340 0 : Unit& u = current->mUnits[i];
9341 0 : switch (u.mType) {
9342 : case Unit::eAtom:
9343 0 : aOut.Append(nsDependentAtomString(u.mAtom));
9344 0 : break;
9345 : case Unit::eString:
9346 0 : aOut.Append(*(u.mString));
9347 0 : break;
9348 : case Unit::eStringWithEncode:
9349 0 : EncodeAttrString(*(u.mString), aOut);
9350 0 : break;
9351 : case Unit::eLiteral:
9352 0 : aOut.AppendASCII(u.mLiteral, u.mLength);
9353 0 : break;
9354 : case Unit::eTextFragment:
9355 0 : u.mTextFragment->AppendTo(aOut);
9356 0 : break;
9357 : case Unit::eTextFragmentWithEncode:
9358 0 : EncodeTextFragment(u.mTextFragment, aOut);
9359 0 : break;
9360 : default:
9361 0 : MOZ_CRASH("Unknown unit type?");
9362 : }
9363 : }
9364 : }
9365 0 : return true;
9366 : }
9367 : private:
9368 0 : Unit* AddUnit()
9369 : {
9370 0 : if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
9371 0 : new StringBuilder(this);
9372 : }
9373 0 : return mLast->mUnits.AppendElement();
9374 : }
9375 :
9376 0 : explicit StringBuilder(StringBuilder* aFirst)
9377 0 : : mLast(nullptr), mLength(0)
9378 : {
9379 0 : MOZ_COUNT_CTOR(StringBuilder);
9380 0 : aFirst->mLast->mNext = this;
9381 0 : aFirst->mLast = this;
9382 0 : }
9383 :
9384 0 : void EncodeAttrString(const nsAutoString& aValue, nsAString& aOut)
9385 : {
9386 0 : const char16_t* c = aValue.BeginReading();
9387 0 : const char16_t* end = aValue.EndReading();
9388 0 : while (c < end) {
9389 0 : switch (*c) {
9390 : case '"':
9391 0 : aOut.AppendLiteral(""");
9392 0 : break;
9393 : case '&':
9394 0 : aOut.AppendLiteral("&");
9395 0 : break;
9396 : case 0x00A0:
9397 0 : aOut.AppendLiteral(" ");
9398 0 : break;
9399 : default:
9400 0 : aOut.Append(*c);
9401 0 : break;
9402 : }
9403 0 : ++c;
9404 : }
9405 0 : }
9406 :
9407 0 : void EncodeTextFragment(const nsTextFragment* aValue, nsAString& aOut)
9408 : {
9409 0 : uint32_t len = aValue->GetLength();
9410 0 : if (aValue->Is2b()) {
9411 0 : const char16_t* data = aValue->Get2b();
9412 0 : for (uint32_t i = 0; i < len; ++i) {
9413 0 : const char16_t c = data[i];
9414 0 : switch (c) {
9415 : case '<':
9416 0 : aOut.AppendLiteral("<");
9417 0 : break;
9418 : case '>':
9419 0 : aOut.AppendLiteral(">");
9420 0 : break;
9421 : case '&':
9422 0 : aOut.AppendLiteral("&");
9423 0 : break;
9424 : case 0x00A0:
9425 0 : aOut.AppendLiteral(" ");
9426 0 : break;
9427 : default:
9428 0 : aOut.Append(c);
9429 0 : break;
9430 : }
9431 : }
9432 : } else {
9433 0 : const char* data = aValue->Get1b();
9434 0 : for (uint32_t i = 0; i < len; ++i) {
9435 0 : const unsigned char c = data[i];
9436 0 : switch (c) {
9437 : case '<':
9438 0 : aOut.AppendLiteral("<");
9439 0 : break;
9440 : case '>':
9441 0 : aOut.AppendLiteral(">");
9442 0 : break;
9443 : case '&':
9444 0 : aOut.AppendLiteral("&");
9445 0 : break;
9446 : case 0x00A0:
9447 0 : aOut.AppendLiteral(" ");
9448 0 : break;
9449 : default:
9450 0 : aOut.Append(c);
9451 0 : break;
9452 : }
9453 : }
9454 : }
9455 0 : }
9456 :
9457 : AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
9458 : nsAutoPtr<StringBuilder> mNext;
9459 : StringBuilder* mLast;
9460 : // mLength is used only in the first StringBuilder object in the linked list.
9461 : uint32_t mLength;
9462 : };
9463 :
9464 : } // namespace
9465 :
9466 : static void
9467 0 : AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)
9468 : {
9469 0 : uint32_t extraSpaceNeeded = 0;
9470 0 : uint32_t len = aText->GetLength();
9471 0 : if (aText->Is2b()) {
9472 0 : const char16_t* data = aText->Get2b();
9473 0 : for (uint32_t i = 0; i < len; ++i) {
9474 0 : const char16_t c = data[i];
9475 0 : switch (c) {
9476 : case '<':
9477 0 : extraSpaceNeeded += ArrayLength("<") - 2;
9478 0 : break;
9479 : case '>':
9480 0 : extraSpaceNeeded += ArrayLength(">") - 2;
9481 0 : break;
9482 : case '&':
9483 0 : extraSpaceNeeded += ArrayLength("&") - 2;
9484 0 : break;
9485 : case 0x00A0:
9486 0 : extraSpaceNeeded += ArrayLength(" ") - 2;
9487 0 : break;
9488 : default:
9489 0 : break;
9490 : }
9491 : }
9492 : } else {
9493 0 : const char* data = aText->Get1b();
9494 0 : for (uint32_t i = 0; i < len; ++i) {
9495 0 : const unsigned char c = data[i];
9496 0 : switch (c) {
9497 : case '<':
9498 0 : extraSpaceNeeded += ArrayLength("<") - 2;
9499 0 : break;
9500 : case '>':
9501 0 : extraSpaceNeeded += ArrayLength(">") - 2;
9502 0 : break;
9503 : case '&':
9504 0 : extraSpaceNeeded += ArrayLength("&") - 2;
9505 0 : break;
9506 : case 0x00A0:
9507 0 : extraSpaceNeeded += ArrayLength(" ") - 2;
9508 0 : break;
9509 : default:
9510 0 : break;
9511 : }
9512 : }
9513 : }
9514 :
9515 0 : if (extraSpaceNeeded) {
9516 0 : aBuilder.AppendWithEncode(aText, len + extraSpaceNeeded);
9517 : } else {
9518 0 : aBuilder.Append(aText);
9519 : }
9520 0 : }
9521 :
9522 : static void
9523 0 : AppendEncodedAttributeValue(nsAutoString* aValue, StringBuilder& aBuilder)
9524 : {
9525 0 : const char16_t* c = aValue->BeginReading();
9526 0 : const char16_t* end = aValue->EndReading();
9527 :
9528 0 : uint32_t extraSpaceNeeded = 0;
9529 0 : while (c < end) {
9530 0 : switch (*c) {
9531 : case '"':
9532 0 : extraSpaceNeeded += ArrayLength(""") - 2;
9533 0 : break;
9534 : case '&':
9535 0 : extraSpaceNeeded += ArrayLength("&") - 2;
9536 0 : break;
9537 : case 0x00A0:
9538 0 : extraSpaceNeeded += ArrayLength(" ") - 2;
9539 0 : break;
9540 : default:
9541 0 : break;
9542 : }
9543 0 : ++c;
9544 : }
9545 :
9546 0 : if (extraSpaceNeeded) {
9547 0 : aBuilder.AppendWithAttrEncode(aValue, aValue->Length() + extraSpaceNeeded);
9548 : } else {
9549 0 : aBuilder.Append(aValue);
9550 : }
9551 0 : }
9552 :
9553 : static void
9554 0 : StartElement(Element* aContent, StringBuilder& aBuilder)
9555 : {
9556 0 : nsIAtom* localName = aContent->NodeInfo()->NameAtom();
9557 0 : int32_t tagNS = aContent->GetNameSpaceID();
9558 :
9559 0 : aBuilder.Append("<");
9560 0 : if (aContent->IsHTMLElement() || aContent->IsSVGElement() ||
9561 0 : aContent->IsMathMLElement()) {
9562 0 : aBuilder.Append(localName);
9563 : } else {
9564 0 : aBuilder.Append(aContent->NodeName());
9565 : }
9566 :
9567 0 : int32_t count = aContent->GetAttrCount();
9568 0 : for (int32_t i = 0; i < count; i++) {
9569 0 : const nsAttrName* name = aContent->GetAttrNameAt(i);
9570 0 : int32_t attNs = name->NamespaceID();
9571 0 : nsIAtom* attName = name->LocalName();
9572 :
9573 : // Filter out any attribute starting with [-|_]moz
9574 0 : nsDependentAtomString attrNameStr(attName);
9575 0 : if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
9576 0 : StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
9577 0 : continue;
9578 : }
9579 :
9580 0 : auto* attValue = new nsAutoString();
9581 0 : aContent->GetAttr(attNs, attName, *attValue);
9582 :
9583 : // Filter out special case of <br type="_moz*"> used by the editor.
9584 : // Bug 16988. Yuck.
9585 0 : if (localName == nsGkAtoms::br && tagNS == kNameSpaceID_XHTML &&
9586 0 : attName == nsGkAtoms::type && attNs == kNameSpaceID_None &&
9587 0 : StringBeginsWith(*attValue, NS_LITERAL_STRING("_moz"))) {
9588 0 : delete attValue;
9589 0 : continue;
9590 : }
9591 :
9592 0 : aBuilder.Append(" ");
9593 :
9594 0 : if (MOZ_LIKELY(attNs == kNameSpaceID_None) ||
9595 0 : (attNs == kNameSpaceID_XMLNS &&
9596 0 : attName == nsGkAtoms::xmlns)) {
9597 : // Nothing else required
9598 0 : } else if (attNs == kNameSpaceID_XML) {
9599 0 : aBuilder.Append("xml:");
9600 0 : } else if (attNs == kNameSpaceID_XMLNS) {
9601 0 : aBuilder.Append("xmlns:");
9602 0 : } else if (attNs == kNameSpaceID_XLink) {
9603 0 : aBuilder.Append("xlink:");
9604 : } else {
9605 0 : nsIAtom* prefix = name->GetPrefix();
9606 0 : if (prefix) {
9607 0 : aBuilder.Append(prefix);
9608 0 : aBuilder.Append(":");
9609 : }
9610 : }
9611 :
9612 0 : aBuilder.Append(attName);
9613 0 : aBuilder.Append(R"(=")");
9614 0 : AppendEncodedAttributeValue(attValue, aBuilder);
9615 0 : aBuilder.Append(R"(")");
9616 : }
9617 :
9618 0 : aBuilder.Append(">");
9619 :
9620 : /*
9621 : // Per HTML spec we should append one \n if the first child of
9622 : // pre/textarea/listing is a textnode and starts with a \n.
9623 : // But because browsers haven't traditionally had that behavior,
9624 : // we're not changing our behavior either - yet.
9625 : if (aContent->IsHTMLElement()) {
9626 : if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
9627 : localName == nsGkAtoms::listing) {
9628 : nsIContent* fc = aContent->GetFirstChild();
9629 : if (fc &&
9630 : (fc->NodeType() == nsIDOMNode::TEXT_NODE ||
9631 : fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
9632 : const nsTextFragment* text = fc->GetText();
9633 : if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
9634 : aBuilder.Append("\n");
9635 : }
9636 : }
9637 : }
9638 : }*/
9639 0 : }
9640 :
9641 : static inline bool
9642 0 : ShouldEscape(nsIContent* aParent)
9643 : {
9644 0 : if (!aParent || !aParent->IsHTMLElement()) {
9645 0 : return true;
9646 : }
9647 :
9648 : static const nsIAtom* nonEscapingElements[] = {
9649 : nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
9650 : nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
9651 : nsGkAtoms::plaintext,
9652 : // Per the current spec noscript should be escaped in case
9653 : // scripts are disabled or if document doesn't have
9654 : // browsing context. However the latter seems to be a spec bug
9655 : // and Gecko hasn't traditionally done the former.
9656 : nsGkAtoms::noscript
9657 0 : };
9658 0 : static mozilla::BloomFilter<12, nsIAtom> sFilter;
9659 : static bool sInitialized = false;
9660 0 : if (!sInitialized) {
9661 0 : sInitialized = true;
9662 0 : for (auto& nonEscapingElement : nonEscapingElements) {
9663 0 : sFilter.add(nonEscapingElement);
9664 : }
9665 : }
9666 :
9667 0 : nsIAtom* tag = aParent->NodeInfo()->NameAtom();
9668 0 : if (sFilter.mightContain(tag)) {
9669 0 : for (auto& nonEscapingElement : nonEscapingElements) {
9670 0 : if (tag == nonEscapingElement) {
9671 0 : return false;
9672 : }
9673 : }
9674 : }
9675 0 : return true;
9676 : }
9677 :
9678 : static inline bool
9679 0 : IsVoidTag(Element* aElement)
9680 : {
9681 0 : if (!aElement->IsHTMLElement()) {
9682 0 : return false;
9683 : }
9684 0 : return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
9685 : }
9686 :
9687 : bool
9688 0 : nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
9689 : bool aDescendentsOnly,
9690 : nsAString& aOut)
9691 : {
9692 : // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
9693 0 : MOZ_ASSERT(aDescendentsOnly ||
9694 : aRoot->NodeType() != nsIDOMNode::DOCUMENT_NODE);
9695 :
9696 0 : nsINode* current = aDescendentsOnly ?
9697 0 : nsNodeUtils::GetFirstChildOfTemplateOrNode(aRoot) : aRoot;
9698 :
9699 0 : if (!current) {
9700 0 : return true;
9701 : }
9702 :
9703 0 : StringBuilder builder;
9704 : nsIContent* next;
9705 : while (true) {
9706 0 : bool isVoid = false;
9707 0 : switch (current->NodeType()) {
9708 : case nsIDOMNode::ELEMENT_NODE: {
9709 0 : Element* elem = current->AsElement();
9710 0 : StartElement(elem, builder);
9711 0 : isVoid = IsVoidTag(elem);
9712 0 : if (!isVoid &&
9713 : (next = nsNodeUtils::GetFirstChildOfTemplateOrNode(current))) {
9714 0 : current = next;
9715 0 : continue;
9716 : }
9717 0 : break;
9718 : }
9719 :
9720 : case nsIDOMNode::TEXT_NODE:
9721 : case nsIDOMNode::CDATA_SECTION_NODE: {
9722 0 : const nsTextFragment* text = static_cast<nsIContent*>(current)->GetText();
9723 0 : nsIContent* parent = current->GetParent();
9724 0 : if (ShouldEscape(parent)) {
9725 0 : AppendEncodedCharacters(text, builder);
9726 : } else {
9727 0 : builder.Append(text);
9728 : }
9729 0 : break;
9730 : }
9731 :
9732 : case nsIDOMNode::COMMENT_NODE: {
9733 0 : builder.Append("<!--");
9734 0 : builder.Append(static_cast<nsIContent*>(current)->GetText());
9735 0 : builder.Append("-->");
9736 0 : break;
9737 : }
9738 :
9739 : case nsIDOMNode::DOCUMENT_TYPE_NODE: {
9740 0 : builder.Append("<!DOCTYPE ");
9741 0 : builder.Append(current->NodeName());
9742 0 : builder.Append(">");
9743 0 : break;
9744 : }
9745 :
9746 : case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: {
9747 0 : builder.Append("<?");
9748 0 : builder.Append(current->NodeName());
9749 0 : builder.Append(" ");
9750 0 : builder.Append(static_cast<nsIContent*>(current)->GetText());
9751 0 : builder.Append(">");
9752 0 : break;
9753 : }
9754 : }
9755 :
9756 : while (true) {
9757 0 : if (!isVoid && current->NodeType() == nsIDOMNode::ELEMENT_NODE) {
9758 0 : builder.Append("</");
9759 0 : nsIContent* elem = static_cast<nsIContent*>(current);
9760 0 : if (elem->IsHTMLElement() || elem->IsSVGElement() ||
9761 0 : elem->IsMathMLElement()) {
9762 0 : builder.Append(elem->NodeInfo()->NameAtom());
9763 : } else {
9764 0 : builder.Append(current->NodeName());
9765 : }
9766 0 : builder.Append(">");
9767 : }
9768 0 : isVoid = false;
9769 :
9770 0 : if (current == aRoot) {
9771 0 : return builder.ToString(aOut);
9772 : }
9773 :
9774 0 : if ((next = current->GetNextSibling())) {
9775 0 : current = next;
9776 0 : break;
9777 : }
9778 :
9779 0 : current = current->GetParentNode();
9780 :
9781 : // Handle template element. If the parent is a template's content,
9782 : // then adjust the parent to be the template element.
9783 0 : if (current != aRoot &&
9784 0 : current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
9785 0 : DocumentFragment* frag = static_cast<DocumentFragment*>(current);
9786 0 : nsIContent* fragHost = frag->GetHost();
9787 0 : if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
9788 0 : current = fragHost;
9789 : }
9790 : }
9791 :
9792 0 : if (aDescendentsOnly && current == aRoot) {
9793 0 : return builder.ToString(aOut);
9794 : }
9795 0 : }
9796 0 : }
9797 : }
9798 :
9799 : bool
9800 0 : nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri)
9801 : {
9802 : // aUri must start with about: or this isn't the right function to be using.
9803 0 : MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
9804 :
9805 : // Make sure the global is a window
9806 0 : nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
9807 0 : if (!win) {
9808 0 : return false;
9809 : }
9810 :
9811 0 : nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
9812 0 : NS_ENSURE_TRUE(principal, false);
9813 0 : nsCOMPtr<nsIURI> uri;
9814 0 : principal->GetURI(getter_AddRefs(uri));
9815 0 : if (!uri) {
9816 0 : return false;
9817 : }
9818 :
9819 : // First check the scheme to avoid getting long specs in the common case.
9820 0 : bool isAbout = false;
9821 0 : uri->SchemeIs("about", &isAbout);
9822 0 : if (!isAbout) {
9823 0 : return false;
9824 : }
9825 :
9826 : // Now check the spec itself
9827 0 : nsAutoCString spec;
9828 0 : uri->GetSpecIgnoringRef(spec);
9829 0 : return spec.EqualsASCII(aUri);
9830 : }
9831 :
9832 : /* static */ void
9833 1 : nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell, bool aVisible)
9834 : {
9835 2 : nsCOMPtr<nsIScrollable> scroller = do_QueryInterface(aDocShell);
9836 :
9837 1 : if (scroller) {
9838 : int32_t prefValue;
9839 :
9840 1 : if (aVisible) {
9841 1 : prefValue = nsIScrollable::Scrollbar_Auto;
9842 : } else {
9843 0 : prefValue = nsIScrollable::Scrollbar_Never;
9844 : }
9845 :
9846 1 : scroller->SetDefaultScrollbarPreferences(
9847 1 : nsIScrollable::ScrollOrientation_Y, prefValue);
9848 1 : scroller->SetDefaultScrollbarPreferences(
9849 1 : nsIScrollable::ScrollOrientation_X, prefValue);
9850 : }
9851 1 : }
9852 :
9853 : /* static */ void
9854 2 : nsContentUtils::GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl)
9855 : {
9856 2 : MOZ_ASSERT(aDocShell);
9857 :
9858 : // Simulate receiver context for web platform test
9859 2 : if (Preferences::GetBool("dom.presentation.testing.simulate-receiver")) {
9860 0 : nsCOMPtr<nsIDocument> doc;
9861 :
9862 : nsCOMPtr<nsPIDOMWindowOuter> docShellWin =
9863 0 : do_QueryInterface(aDocShell->GetScriptGlobalObject());
9864 0 : if (docShellWin) {
9865 0 : doc = docShellWin->GetExtantDoc();
9866 : }
9867 :
9868 0 : if (NS_WARN_IF(!doc)) {
9869 0 : return;
9870 : }
9871 :
9872 0 : nsCOMPtr<nsIURI> uri = doc->GetDocumentURI();
9873 0 : if (NS_WARN_IF(!uri)) {
9874 0 : return;
9875 : }
9876 :
9877 0 : nsAutoCString uriStr;
9878 0 : uri->GetSpec(uriStr);
9879 0 : aPresentationUrl = NS_ConvertUTF8toUTF16(uriStr);
9880 0 : return;
9881 : }
9882 :
9883 2 : if (XRE_IsContentProcess()) {
9884 0 : nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
9885 0 : aDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
9886 0 : nsCOMPtr<nsIDocShellTreeItem> root;
9887 0 : aDocShell->GetRootTreeItem(getter_AddRefs(root));
9888 0 : if (sameTypeRoot.get() == root.get()) {
9889 : // presentation URL is stored in TabChild for the top most
9890 : // <iframe mozbrowser> in content process.
9891 0 : TabChild* tabChild = TabChild::GetFrom(aDocShell);
9892 0 : if (tabChild) {
9893 0 : aPresentationUrl = tabChild->PresentationURL();
9894 : }
9895 0 : return;
9896 : }
9897 : }
9898 :
9899 3 : nsCOMPtr<nsILoadContext> loadContext(do_QueryInterface(aDocShell));
9900 3 : nsCOMPtr<nsIDOMElement> topFrameElement;
9901 2 : loadContext->GetTopFrameElement(getter_AddRefs(topFrameElement));
9902 2 : if (!topFrameElement) {
9903 1 : return;
9904 : }
9905 :
9906 1 : topFrameElement->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
9907 : }
9908 :
9909 : /* static */ nsIDocShell*
9910 87 : nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget)
9911 : {
9912 174 : nsCOMPtr<nsPIDOMWindowInner> innerWindow;
9913 :
9914 174 : if (nsCOMPtr<nsINode> node = do_QueryInterface(aTarget)) {
9915 : bool ignore;
9916 : innerWindow =
9917 29 : do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
9918 58 : } else if ((innerWindow = do_QueryInterface(aTarget))) {
9919 : // Nothing else to do
9920 : } else {
9921 80 : nsCOMPtr<DOMEventTargetHelper> helper = do_QueryInterface(aTarget);
9922 40 : if (helper) {
9923 40 : innerWindow = helper->GetOwner();
9924 : }
9925 : }
9926 :
9927 87 : if (innerWindow) {
9928 47 : return innerWindow->GetDocShell();
9929 : }
9930 :
9931 40 : return nullptr;
9932 : }
9933 :
9934 : /*
9935 : * Note: this function only relates to figuring out HTTPS state, which is an
9936 : * input to the Secure Context algorithm. We are not actually implementing any
9937 : * part of the Secure Context algorithm itself here.
9938 : *
9939 : * This is a bit of a hack. Ideally we'd propagate HTTPS state through
9940 : * nsIChannel as described in the Fetch and HTML specs, but making channels
9941 : * know about whether they should inherit HTTPS state, propagating information
9942 : * about who the channel's "client" is, exposing GetHttpsState API on channels
9943 : * and modifying the various cache implementations to store and retrieve HTTPS
9944 : * state involves a huge amount of code (see bug 1220687). We avoid that for
9945 : * now using this function.
9946 : *
9947 : * This function takes advantage of the observation that we can return true if
9948 : * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
9949 : * the document's origin (e.g. the origin has a scheme of 'https' or host
9950 : * 'localhost' etc.). Since we generally propagate a creator document's origin
9951 : * onto data:, blob:, etc. documents, this works for them too.
9952 : *
9953 : * The scenario where this observation breaks down is sandboxing without the
9954 : * 'allow-same-origin' flag, since in this case a document is given a unique
9955 : * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
9956 : * by using the origin that the document would have had had it not been
9957 : * sandboxed.
9958 : *
9959 : * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
9960 : * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
9961 : * sandboxing is limited to the immediate sandbox. In the case that aDocument
9962 : * should inherit its origin (e.g. data: URI) but its parent has ended up
9963 : * with a unique origin due to sandboxing further up the parent chain we may
9964 : * end up returning false when we would ideally return true (since we will
9965 : * examine the parent's origin for 'https' and not finding it.) This means
9966 : * that we may restrict the privileges of some pages unnecessarily in this
9967 : * edge case.
9968 : */
9969 : /* static */ bool
9970 8 : nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
9971 : {
9972 8 : if (!aDocument) {
9973 0 : return false;
9974 : }
9975 :
9976 16 : nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
9977 :
9978 8 : if (principal->GetIsSystemPrincipal()) {
9979 0 : return true;
9980 : }
9981 :
9982 : // If aDocument is sandboxed, try and get the principal that it would have
9983 : // been given had it not been sandboxed:
9984 12 : if (principal->GetIsNullPrincipal() &&
9985 4 : (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
9986 0 : nsIChannel* channel = aDocument->GetChannel();
9987 0 : if (channel) {
9988 : nsCOMPtr<nsIScriptSecurityManager> ssm =
9989 0 : nsContentUtils::GetSecurityManager();
9990 : nsresult rv =
9991 0 : ssm->GetChannelResultPrincipalIfNotSandboxed(channel,
9992 0 : getter_AddRefs(principal));
9993 0 : if (NS_FAILED(rv)) {
9994 0 : return false;
9995 : }
9996 0 : if (principal->GetIsSystemPrincipal()) {
9997 : // If a document with the system principal is sandboxing a subdocument
9998 : // that would normally inherit the embedding element's principal (e.g.
9999 : // a srcdoc document) then the embedding document does not trust the
10000 : // content that is written to the embedded document. Unlike when the
10001 : // embedding document is https, in this case we have no indication as
10002 : // to whether the embedded document's contents are delivered securely
10003 : // or not, and the sandboxing would possibly indicate that they were
10004 : // not. To play it safe we return false here. (See bug 1162772
10005 : // comment 73-80.)
10006 0 : return false;
10007 : }
10008 : }
10009 : }
10010 :
10011 8 : if (principal->GetIsNullPrincipal()) {
10012 4 : return false;
10013 : }
10014 :
10015 4 : MOZ_ASSERT(principal->GetIsCodebasePrincipal());
10016 :
10017 : nsCOMPtr<nsIContentSecurityManager> csm =
10018 8 : do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
10019 4 : NS_WARNING_ASSERTION(csm, "csm is null");
10020 4 : if (csm) {
10021 4 : bool isTrustworthyOrigin = false;
10022 4 : csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
10023 4 : if (isTrustworthyOrigin) {
10024 4 : return true;
10025 : }
10026 : }
10027 :
10028 0 : return false;
10029 : }
10030 :
10031 : /* static */ CustomElementDefinition*
10032 0 : nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
10033 : const nsAString& aLocalName,
10034 : uint32_t aNameSpaceID,
10035 : const nsAString* aIs)
10036 : {
10037 0 : MOZ_ASSERT(aDoc);
10038 :
10039 0 : if (aNameSpaceID != kNameSpaceID_XHTML ||
10040 0 : !aDoc->GetDocShell()) {
10041 0 : return nullptr;
10042 : }
10043 :
10044 0 : nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
10045 0 : if (!window) {
10046 0 : return nullptr;
10047 : }
10048 :
10049 0 : RefPtr<CustomElementRegistry> registry(window->CustomElements());
10050 0 : if (!registry) {
10051 0 : return nullptr;
10052 : }
10053 :
10054 0 : return registry->LookupCustomElementDefinition(aLocalName, aIs);
10055 : }
10056 :
10057 : /* static */ void
10058 0 : nsContentUtils::SetupCustomElement(Element* aElement,
10059 : const nsAString* aTypeExtension)
10060 : {
10061 0 : MOZ_ASSERT(aElement);
10062 :
10063 0 : nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
10064 :
10065 0 : if (!doc) {
10066 0 : return;
10067 : }
10068 :
10069 0 : if (aElement->GetNameSpaceID() != kNameSpaceID_XHTML ||
10070 0 : !doc->GetDocShell()) {
10071 0 : return;
10072 : }
10073 :
10074 0 : nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
10075 0 : if (!window) {
10076 0 : return;
10077 : }
10078 :
10079 0 : RefPtr<CustomElementRegistry> registry(window->CustomElements());
10080 0 : if (!registry) {
10081 0 : return;
10082 : }
10083 :
10084 0 : return registry->SetupCustomElement(aElement, aTypeExtension);
10085 : }
10086 :
10087 : /* static */ void
10088 0 : nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
10089 : nsIDocument::ElementCallbackType aType,
10090 : Element* aCustomElement,
10091 : LifecycleCallbackArgs* aArgs,
10092 : CustomElementDefinition* aDefinition)
10093 : {
10094 0 : MOZ_ASSERT(aDoc);
10095 :
10096 0 : if (!aDoc->GetDocShell()) {
10097 0 : return;
10098 : }
10099 :
10100 0 : nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
10101 0 : if (!window) {
10102 0 : return;
10103 : }
10104 :
10105 0 : RefPtr<CustomElementRegistry> registry(window->CustomElements());
10106 0 : if (!registry) {
10107 0 : return;
10108 : }
10109 :
10110 0 : registry->EnqueueLifecycleCallback(aType, aCustomElement, aArgs, aDefinition);
10111 : }
10112 :
10113 : /* static */ void
10114 0 : nsContentUtils::GetCustomPrototype(nsIDocument* aDoc,
10115 : int32_t aNamespaceID,
10116 : nsIAtom* aAtom,
10117 : JS::MutableHandle<JSObject*> aPrototype)
10118 : {
10119 0 : MOZ_ASSERT(aDoc);
10120 :
10121 0 : if (aNamespaceID != kNameSpaceID_XHTML ||
10122 0 : !aDoc->GetDocShell()) {
10123 0 : return;
10124 : }
10125 :
10126 0 : nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
10127 0 : if (!window) {
10128 0 : return;
10129 : }
10130 :
10131 0 : RefPtr<CustomElementRegistry> registry(window->CustomElements());
10132 0 : if (!registry) {
10133 0 : return;
10134 : }
10135 :
10136 0 : return registry->GetCustomPrototype(aAtom, aPrototype);
10137 : }
10138 :
10139 : /* static */ bool
10140 0 : nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
10141 : {
10142 0 : MOZ_ASSERT(aChannel);
10143 :
10144 0 : nsCOMPtr<nsILoadGroup> loadGroup;
10145 0 : nsresult rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
10146 0 : if (NS_WARN_IF(NS_FAILED(rv) || !loadGroup)) {
10147 0 : return false;
10148 : }
10149 :
10150 0 : nsCOMPtr<nsIInterfaceRequestor> callbacks;
10151 0 : rv = loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
10152 0 : if (NS_WARN_IF(NS_FAILED(rv) || !callbacks)) {
10153 0 : return false;
10154 : }
10155 :
10156 0 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
10157 0 : if (NS_WARN_IF(!loadContext)) {
10158 0 : return false;
10159 : }
10160 :
10161 0 : nsCOMPtr<mozIDOMWindowProxy> window;
10162 0 : rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
10163 0 : if (NS_WARN_IF(NS_FAILED(rv) || !window)) {
10164 0 : return false;
10165 : }
10166 :
10167 0 : nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(window);
10168 0 : if (NS_WARN_IF(!outer)) {
10169 0 : return false;
10170 : }
10171 :
10172 0 : if (!XRE_IsContentProcess()) {
10173 0 : outer->SetLargeAllocStatus(LargeAllocStatus::NON_E10S);
10174 0 : return false;
10175 : }
10176 :
10177 0 : nsIDocShell* docShell = outer->GetDocShell();
10178 0 : if (!docShell->GetIsOnlyToplevelInTabGroup()) {
10179 0 : outer->SetLargeAllocStatus(LargeAllocStatus::NOT_ONLY_TOPLEVEL_IN_TABGROUP);
10180 0 : return false;
10181 : }
10182 :
10183 : // Get the request method, and check if it is a GET request. If it is not GET,
10184 : // then we cannot perform a large allocation load.
10185 0 : nsAutoCString requestMethod;
10186 0 : rv = aChannel->GetRequestMethod(requestMethod);
10187 0 : NS_ENSURE_SUCCESS(rv, false);
10188 :
10189 0 : if (NS_WARN_IF(!requestMethod.LowerCaseEqualsLiteral("get"))) {
10190 0 : outer->SetLargeAllocStatus(LargeAllocStatus::NON_GET);
10191 0 : return false;
10192 : }
10193 :
10194 0 : TabChild* tabChild = TabChild::GetFrom(outer->AsOuter());
10195 0 : NS_ENSURE_TRUE(tabChild, false);
10196 :
10197 0 : if (tabChild->IsAwaitingLargeAlloc()) {
10198 0 : NS_WARNING("In a Large-Allocation TabChild, ignoring Large-Allocation header!");
10199 0 : tabChild->StopAwaitingLargeAlloc();
10200 0 : outer->SetLargeAllocStatus(LargeAllocStatus::SUCCESS);
10201 0 : return false;
10202 : }
10203 :
10204 : // On Win32 systems, we want to behave differently, so set the isWin32 bool to
10205 : // be true iff we are on win32.
10206 : #if defined(XP_WIN) && defined(_X86_)
10207 : const bool isWin32 = true;
10208 : #else
10209 0 : const bool isWin32 = false;
10210 : #endif
10211 :
10212 : static bool sLargeAllocForceEnable = false;
10213 : static bool sCachedLargeAllocForceEnable = false;
10214 0 : if (!sCachedLargeAllocForceEnable) {
10215 0 : sCachedLargeAllocForceEnable = true;
10216 : mozilla::Preferences::AddBoolVarCache(&sLargeAllocForceEnable,
10217 0 : "dom.largeAllocation.forceEnable");
10218 : }
10219 :
10220 : // We want to enable the large allocation header on 32-bit windows machines,
10221 : // and disable it on other machines, while still printing diagnostic messages.
10222 : // dom.largeAllocation.forceEnable can allow you to enable the process
10223 : // switching behavior of the Large-Allocation header on non 32-bit windows
10224 : // machines.
10225 0 : bool largeAllocEnabled = isWin32 || sLargeAllocForceEnable;
10226 0 : if (!largeAllocEnabled) {
10227 : NS_WARNING("dom.largeAllocation.forceEnable not set - "
10228 0 : "ignoring otherwise successful Large-Allocation header.");
10229 : // On platforms which aren't WIN32, we don't activate the largeAllocation
10230 : // header, instead we simply emit diagnostics into the console.
10231 0 : outer->SetLargeAllocStatus(LargeAllocStatus::NON_WIN32);
10232 0 : return false;
10233 : }
10234 :
10235 : // At this point the fress process load should succeed! We just need to get
10236 : // ourselves a nsIWebBrowserChrome3 to ask to perform the reload. We should
10237 : // have one, as we have already confirmed that we are running in a content
10238 : // process.
10239 0 : nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
10240 0 : docShell->GetTreeOwner(getter_AddRefs(treeOwner));
10241 0 : NS_ENSURE_TRUE(treeOwner, false);
10242 :
10243 0 : nsCOMPtr<nsIWebBrowserChrome3> wbc3 = do_GetInterface(treeOwner);
10244 0 : NS_ENSURE_TRUE(wbc3, false);
10245 :
10246 0 : nsCOMPtr<nsIURI> uri;
10247 0 : rv = aChannel->GetURI(getter_AddRefs(uri));
10248 0 : NS_ENSURE_SUCCESS(rv, false);
10249 0 : NS_ENSURE_TRUE(uri, false);
10250 :
10251 0 : nsCOMPtr<nsIURI> referrer;
10252 0 : rv = aChannel->GetReferrer(getter_AddRefs(referrer));
10253 0 : NS_ENSURE_SUCCESS(rv, false);
10254 :
10255 0 : nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
10256 0 : if (!loadInfo) {
10257 0 : return false;
10258 : }
10259 0 : nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
10260 :
10261 : // Get the channel's load flags, and use them to generate nsIWebNavigation
10262 : // load flags. We want to make sure to propagate the refresh and cache busting
10263 : // flags.
10264 : nsLoadFlags channelLoadFlags;
10265 0 : aChannel->GetLoadFlags(&channelLoadFlags);
10266 :
10267 0 : uint32_t webnavLoadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
10268 0 : if (channelLoadFlags & nsIRequest::LOAD_BYPASS_CACHE) {
10269 0 : webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE;
10270 0 : webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
10271 0 : } else if (channelLoadFlags & nsIRequest::VALIDATE_ALWAYS) {
10272 0 : webnavLoadFlags |= nsIWebNavigation::LOAD_FLAGS_IS_REFRESH;
10273 : }
10274 :
10275 : // Actually perform the cross process load
10276 0 : bool reloadSucceeded = false;
10277 0 : rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer,
10278 : triggeringPrincipal, webnavLoadFlags,
10279 0 : &reloadSucceeded);
10280 0 : NS_ENSURE_SUCCESS(rv, false);
10281 :
10282 0 : return reloadSucceeded;
10283 : }
10284 :
10285 : /* static */ void
10286 0 : nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
10287 : nsIDocument* aDocument,
10288 : nsTArray<nsIContent*>& aElements)
10289 : {
10290 0 : MOZ_ASSERT(aDocument);
10291 :
10292 0 : if (nsIPresShell* presShell = aDocument->GetShell()) {
10293 0 : if (nsIFrame* scrollFrame = presShell->GetRootScrollFrame()) {
10294 0 : nsIAnonymousContentCreator* creator = do_QueryFrame(scrollFrame);
10295 0 : MOZ_ASSERT(creator,
10296 : "scroll frame should always implement nsIAnonymousContentCreator");
10297 0 : creator->AppendAnonymousContentTo(aElements, 0);
10298 : }
10299 :
10300 0 : if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
10301 0 : if (Element* container = canvasFrame->GetCustomContentContainer()) {
10302 0 : aElements.AppendElement(container);
10303 : }
10304 : }
10305 : }
10306 0 : }
10307 :
10308 : static void
10309 0 : AppendNativeAnonymousChildrenFromFrame(
10310 : nsIFrame* aFrame,
10311 : nsTArray<nsIContent*>& aKids,
10312 : uint32_t aFlags)
10313 : {
10314 0 : if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
10315 0 : ac->AppendAnonymousContentTo(aKids, aFlags);
10316 : }
10317 0 : }
10318 :
10319 : /* static */ void
10320 0 : nsContentUtils::AppendNativeAnonymousChildren(
10321 : const nsIContent* aContent,
10322 : nsTArray<nsIContent*>& aKids,
10323 : uint32_t aFlags)
10324 : {
10325 0 : if (aContent->MayHaveAnonymousChildren()) {
10326 0 : if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
10327 : // NAC created by the element's primary frame.
10328 0 : AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
10329 :
10330 : // NAC created by any other non-primary frames for the element.
10331 0 : AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
10332 0 : primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
10333 0 : for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
10334 0 : MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == aContent);
10335 0 : AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids, aFlags);
10336 : }
10337 : }
10338 :
10339 : // Get manually created NAC (editor resize handles, etc.).
10340 0 : if (auto nac = static_cast<ManualNAC*>(
10341 0 : aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
10342 0 : aKids.AppendElements(*nac);
10343 : }
10344 : }
10345 :
10346 : // The root scroll frame is not the primary frame of the root element.
10347 : // Detect and handle this case.
10348 0 : if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
10349 0 : aContent == aContent->OwnerDoc()->GetRootElement()) {
10350 0 : AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
10351 : }
10352 0 : }
10353 :
10354 :
10355 : /* static */ void
10356 1 : nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode,
10357 : nsIPrincipal** aLoadingPrincipal,
10358 : nsContentPolicyType& aContentPolicyType)
10359 : {
10360 : // Use the serialized loadingPrincipal from the image element. Fall back
10361 : // to mContent's principal (SystemPrincipal) if not available.
10362 1 : aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
10363 2 : nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingNode->NodePrincipal();
10364 2 : nsAutoString imageLoadingPrincipal;
10365 : aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
10366 1 : imageLoadingPrincipal);
10367 1 : if (!imageLoadingPrincipal.IsEmpty()) {
10368 2 : nsCOMPtr<nsISupports> serializedPrincipal;
10369 2 : NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal),
10370 3 : getter_AddRefs(serializedPrincipal));
10371 1 : loadingPrincipal = do_QueryInterface(serializedPrincipal);
10372 :
10373 1 : if (loadingPrincipal) {
10374 : // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
10375 : // indicating it's a favicon loading.
10376 1 : aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
10377 : } else {
10378 : // Fallback if the deserialization is failed.
10379 0 : loadingPrincipal = aLoadingNode->NodePrincipal();
10380 : }
10381 : }
10382 1 : loadingPrincipal.forget(aLoadingPrincipal);
10383 1 : }
10384 :
10385 : /* static */ nsresult
10386 1 : nsContentUtils::CreateJSValueFromSequenceOfObject(JSContext* aCx,
10387 : const Sequence<JSObject*>& aTransfer,
10388 : JS::MutableHandle<JS::Value> aValue)
10389 : {
10390 1 : if (aTransfer.IsEmpty()) {
10391 1 : return NS_OK;
10392 : }
10393 :
10394 0 : JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aTransfer.Length()));
10395 0 : if (!array) {
10396 0 : return NS_ERROR_OUT_OF_MEMORY;
10397 : }
10398 :
10399 0 : for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
10400 0 : JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
10401 0 : if (!object) {
10402 0 : continue;
10403 : }
10404 :
10405 0 : if (NS_WARN_IF(!JS_DefineElement(aCx, array, i, object,
10406 : JSPROP_ENUMERATE))) {
10407 0 : return NS_ERROR_OUT_OF_MEMORY;
10408 : }
10409 : }
10410 :
10411 0 : aValue.setObject(*array);
10412 0 : return NS_OK;
10413 : }
10414 :
10415 : /* static */ Element*
10416 33 : nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement)
10417 : {
10418 33 : MOZ_ASSERT(aElement);
10419 33 : MOZ_ASSERT(aElement->IsNativeAnonymous());
10420 :
10421 33 : Element* e = aElement;
10422 99 : while (e && e->IsNativeAnonymous()) {
10423 33 : e = e->GetParentElement();
10424 : }
10425 33 : return e;
10426 : }
10427 :
10428 : /**
10429 : * Checks whether the given type is a supported document type for
10430 : * loading within the nsObjectLoadingContent specified by aContent.
10431 : *
10432 : * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
10433 : * NOTE Does not take content policy or capabilities into account
10434 : */
10435 : static bool
10436 0 : HtmlObjectContentSupportsDocument(const nsCString& aMimeType,
10437 : nsIContent* aContent)
10438 : {
10439 : nsCOMPtr<nsIWebNavigationInfo> info(
10440 0 : do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
10441 0 : if (!info) {
10442 0 : return false;
10443 : }
10444 :
10445 0 : nsCOMPtr<nsIWebNavigation> webNav;
10446 0 : if (aContent) {
10447 0 : nsIDocument* currentDoc = aContent->GetComposedDoc();
10448 0 : if (currentDoc) {
10449 0 : webNav = do_GetInterface(currentDoc->GetWindow());
10450 : }
10451 : }
10452 :
10453 : uint32_t supported;
10454 0 : nsresult rv = info->IsTypeSupported(aMimeType, webNav, &supported);
10455 :
10456 0 : if (NS_FAILED(rv)) {
10457 0 : return false;
10458 : }
10459 :
10460 0 : if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
10461 : // Don't want to support plugins as documents
10462 0 : return supported != nsIWebNavigationInfo::PLUGIN;
10463 : }
10464 :
10465 : // Try a stream converter
10466 : // NOTE: We treat any type we can convert from as a supported type. If a
10467 : // type is not actually supported, the URI loader will detect that and
10468 : // return an error, and we'll fallback.
10469 : nsCOMPtr<nsIStreamConverterService> convServ =
10470 0 : do_GetService("@mozilla.org/streamConverters;1");
10471 0 : bool canConvert = false;
10472 0 : if (convServ) {
10473 0 : rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
10474 : }
10475 0 : return NS_SUCCEEDED(rv) && canConvert;
10476 : }
10477 :
10478 : /* static */
10479 : already_AddRefed<nsIPluginTag>
10480 0 : nsContentUtils::PluginTagForType(const nsCString& aMIMEType, bool aNoFakePlugin)
10481 : {
10482 0 : RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
10483 0 : nsCOMPtr<nsIPluginTag> tag;
10484 0 : NS_ENSURE_TRUE(pluginHost, nullptr);
10485 :
10486 : // ShouldPlay will handle the case where the plugin is disabled
10487 0 : pluginHost->GetPluginTagForType(aMIMEType,
10488 : aNoFakePlugin ? nsPluginHost::eExcludeFake
10489 : : nsPluginHost::eExcludeNone,
10490 0 : getter_AddRefs(tag));
10491 :
10492 0 : return tag.forget();
10493 : }
10494 :
10495 : /* static */ uint32_t
10496 0 : nsContentUtils::HtmlObjectContentTypeForMIMEType(const nsCString& aMIMEType,
10497 : bool aNoFakePlugin,
10498 : nsIContent* aContent)
10499 : {
10500 0 : if (aMIMEType.IsEmpty()) {
10501 0 : return nsIObjectLoadingContent::TYPE_NULL;
10502 : }
10503 :
10504 0 : if (imgLoader::SupportImageWithMimeType(aMIMEType.get())) {
10505 0 : return nsIObjectLoadingContent::TYPE_IMAGE;
10506 : }
10507 :
10508 : // Faking support of the PDF content as a document for EMBED tags
10509 : // when internal PDF viewer is enabled.
10510 0 : if (aMIMEType.LowerCaseEqualsLiteral("application/pdf") &&
10511 0 : IsPDFJSEnabled()) {
10512 0 : return nsIObjectLoadingContent::TYPE_DOCUMENT;
10513 : }
10514 :
10515 0 : if (HtmlObjectContentSupportsDocument(aMIMEType, aContent)) {
10516 0 : return nsIObjectLoadingContent::TYPE_DOCUMENT;
10517 : }
10518 :
10519 0 : RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
10520 0 : if (pluginHost) {
10521 0 : nsCOMPtr<nsIPluginTag> tag = PluginTagForType(aMIMEType, aNoFakePlugin);
10522 0 : if (tag) {
10523 0 : if (!aNoFakePlugin &&
10524 0 : nsCOMPtr<nsIFakePluginTag>(do_QueryInterface(tag))) {
10525 0 : return nsIObjectLoadingContent::TYPE_FAKE_PLUGIN;
10526 : }
10527 :
10528 : // ShouldPlay will handle checking for disabled plugins
10529 0 : return nsIObjectLoadingContent::TYPE_PLUGIN;
10530 : }
10531 : }
10532 :
10533 0 : return nsIObjectLoadingContent::TYPE_NULL;
10534 : }
10535 :
10536 : /* static */ already_AddRefed<nsIEventTarget>
10537 1252 : nsContentUtils::GetEventTargetByLoadInfo(nsILoadInfo* aLoadInfo, TaskCategory aCategory)
10538 : {
10539 1252 : if (NS_WARN_IF(!aLoadInfo)) {
10540 0 : return nullptr;
10541 : }
10542 :
10543 2504 : nsCOMPtr<nsIDOMDocument> domDoc;
10544 1252 : aLoadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
10545 2504 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
10546 2504 : nsCOMPtr<nsIEventTarget> target;
10547 1252 : if (doc) {
10548 105 : if (DocGroup* group = doc->GetDocGroup()) {
10549 105 : target = group->EventTargetFor(aCategory);
10550 : }
10551 : } else {
10552 : // There's no document yet, but this might be a top-level load where we can
10553 : // find a TabGroup.
10554 : uint64_t outerWindowId;
10555 1147 : if (NS_FAILED(aLoadInfo->GetOuterWindowID(&outerWindowId))) {
10556 : // No window. This might be an add-on XHR, a service worker request, or
10557 : // something else.
10558 1138 : return nullptr;
10559 : }
10560 1156 : RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(outerWindowId);
10561 1147 : if (!window) {
10562 1138 : return nullptr;
10563 : }
10564 :
10565 9 : target = window->TabGroup()->EventTargetFor(aCategory);
10566 : }
10567 :
10568 114 : return target.forget();
10569 : }
10570 :
10571 : /* static */ bool
10572 26 : nsContentUtils::IsLocalRefURL(const nsString& aString)
10573 : {
10574 : // Find the first non-"C0 controls + space" character.
10575 26 : const char16_t* current = aString.get();
10576 26 : for (; *current != '\0'; current++) {
10577 26 : if (*current > 0x20) {
10578 : // if the first non-"C0 controls + space" character is '#', this is a
10579 : // local-ref URL.
10580 26 : return *current == '#';
10581 : }
10582 : }
10583 :
10584 0 : return false;
10585 : }
10586 :
10587 : // Tab ID is composed in a similar manner of Window ID.
10588 : static uint64_t gNextTabId = 0;
10589 : static const uint64_t kTabIdProcessBits = 32;
10590 : static const uint64_t kTabIdTabBits = 64 - kTabIdProcessBits;
10591 :
10592 : /* static */ uint64_t
10593 1 : nsContentUtils::GenerateTabId()
10594 : {
10595 1 : uint64_t processId = 0;
10596 1 : if (XRE_IsContentProcess()) {
10597 0 : ContentChild* cc = ContentChild::GetSingleton();
10598 0 : processId = cc->GetID();
10599 : }
10600 :
10601 1 : MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kTabIdProcessBits));
10602 1 : uint64_t processBits = processId & ((uint64_t(1) << kTabIdProcessBits) - 1);
10603 :
10604 1 : uint64_t tabId = ++gNextTabId;
10605 1 : MOZ_RELEASE_ASSERT(tabId < (uint64_t(1) << kTabIdTabBits));
10606 1 : uint64_t tabBits = tabId & ((uint64_t(1) << kTabIdTabBits) - 1);
10607 :
10608 1 : return (processBits << kTabIdTabBits) | tabBits;
10609 : }
10610 :
10611 : /* static */ bool
10612 0 : nsContentUtils::GetUserIsInteracting()
10613 : {
10614 0 : return UserInteractionObserver::sUserActive;
10615 : }
10616 :
10617 : /* static */ bool
10618 2 : nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult)
10619 : {
10620 2 : nsresult rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), aResult);
10621 2 : if (NS_FAILED(rv)) {
10622 2 : rv = aChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), aResult);
10623 : }
10624 2 : return NS_SUCCEEDED(rv);
10625 : }
10626 :
10627 : static const char* kUserInteractionInactive = "user-interaction-inactive";
10628 : static const char* kUserInteractionActive = "user-interaction-active";
10629 :
10630 : void
10631 3 : nsContentUtils::UserInteractionObserver::Init()
10632 : {
10633 : // Listen for the observer messages from EventStateManager which are telling
10634 : // us whether or not the user is interacting.
10635 6 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10636 3 : obs->AddObserver(this, kUserInteractionInactive, false);
10637 3 : obs->AddObserver(this, kUserInteractionActive, false);
10638 :
10639 : // We can't register ourselves as an annotator yet, as the HangMonitor hasn't
10640 : // started yet. It will have started by the time we have the chance to spin
10641 : // the event loop.
10642 6 : RefPtr<UserInteractionObserver> self = this;
10643 6 : NS_DispatchToMainThread(
10644 6 : NS_NewRunnableFunction("nsContentUtils::UserInteractionObserver::Init",
10645 15 : [=]() { HangMonitor::RegisterAnnotator(*self); }));
10646 3 : }
10647 :
10648 : void
10649 0 : nsContentUtils::UserInteractionObserver::Shutdown()
10650 : {
10651 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
10652 0 : if (obs) {
10653 0 : obs->RemoveObserver(this, kUserInteractionInactive);
10654 0 : obs->RemoveObserver(this, kUserInteractionActive);
10655 : }
10656 :
10657 0 : HangMonitor::UnregisterAnnotator(*this);
10658 0 : }
10659 :
10660 : /**
10661 : * NB: This function is always called by the HangMonitor thread.
10662 : * Plan accordingly
10663 : */
10664 : void
10665 0 : nsContentUtils::UserInteractionObserver::AnnotateHang(HangMonitor::HangAnnotations& aAnnotations)
10666 : {
10667 : // NOTE: Only annotate the hang report if the user is known to be interacting.
10668 0 : if (sUserActive) {
10669 0 : aAnnotations.AddAnnotation(NS_LITERAL_STRING("UserInteracting"), true);
10670 : }
10671 0 : }
10672 :
10673 : NS_IMETHODIMP
10674 3 : nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
10675 : const char* aTopic,
10676 : const char16_t* aData)
10677 : {
10678 3 : if (!strcmp(aTopic, kUserInteractionInactive)) {
10679 2 : sUserActive = false;
10680 1 : } else if (!strcmp(aTopic, kUserInteractionActive)) {
10681 1 : sUserActive = true;
10682 : } else {
10683 0 : NS_WARNING("Unexpected observer notification");
10684 : }
10685 3 : return NS_OK;
10686 : }
10687 :
10688 : Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
10689 33 : NS_IMPL_ISUPPORTS(nsContentUtils::UserInteractionObserver, nsIObserver)
10690 :
10691 : /* static */ bool
10692 1 : nsContentUtils::IsOverridingWindowName(const nsAString& aName)
10693 : {
10694 1 : return !aName.IsEmpty() &&
10695 0 : !aName.LowerCaseEqualsLiteral("_blank") &&
10696 0 : !aName.LowerCaseEqualsLiteral("_top") &&
10697 1 : !aName.LowerCaseEqualsLiteral("_parent") &&
10698 1 : !aName.LowerCaseEqualsLiteral("_self");
10699 : }
|