nsContentUtils.h 137 KB
Newer Older
1
2
3
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
4
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6

7
/* A namespace class for static content utilities. */
8
9
10
11

#ifndef nsContentUtils_h___
#define nsContentUtils_h___

12
#if defined(XP_WIN)
13
#  include <float.h>
14
15
#endif

16
#if defined(SOLARIS)
17
#  include <ieeefp.h>
18
19
#endif

20
#include "js/TypeDecls.h"
21
#include "js/Value.h"
22
#include "js/RootingAPI.h"
23
#include "mozilla/dom/FromParser.h"
24
#include "mozilla/BasicEvents.h"
25
#include "mozilla/CallState.h"
26
#include "mozilla/CORSMode.h"
27
#include "mozilla/EventForwards.h"
28
#include "mozilla/GuardObjects.h"
29
#include "mozilla/StaticPtr.h"
30
#include "mozilla/TaskCategory.h"
31
#include "mozilla/TimeStamp.h"
32
#include "nsContentListDeclarations.h"
33
#include "nsMathUtils.h"
34
#include "nsTArrayForwardDeclare.h"
35
#include "Units.h"
36
#include "mozilla/dom/AutocompleteInfoBinding.h"
37
#include "mozilla/dom/BindingDeclarations.h"  // For CallerType
38
#include "mozilla/dom/ScriptSettings.h"
39
#include "mozilla/FloatingPoint.h"
40
#include "mozilla/intl/LineBreaker.h"
41
#include "mozilla/intl/WordBreaker.h"
42
#include "mozilla/Logging.h"
43
#include "mozilla/NotNull.h"
44
#include "mozilla/Maybe.h"
45
#include "mozilla/RangeBoundary.h"
46
#include "nsIContentPolicy.h"
47
#include "nsIScriptError.h"
48
#include "mozilla/dom/Document.h"
49
#include "nsPIDOMWindow.h"
50
#include "nsRFPService.h"
51

52
53
#if defined(XP_WIN)
// Undefine LoadImage to prevent naming conflict with Windows.
54
#  undef LoadImage
55
56
#endif

57
58
59
class imgICache;
class imgIContainer;
class imgINotificationObserver;
60
class imgIRequest;
61
62
63
class imgLoader;
class imgRequestProxy;
class nsAutoScriptBlockerSuppressNodeRemoved;
64
class nsCacheableFuncStringHTMLCollection;
65
class nsHtml5StringParser;
66
class nsAtom;
67
68
class nsIChannel;
class nsIConsoleService;
69
class nsIContent;
70
class nsIContentPolicy;
71
class nsIContentSecurityPolicy;
72
class nsIDocShellTreeItem;
73
74
class nsIDocumentLoaderFactory;
class nsIDragSession;
75
class nsIEventTarget;
76
class nsIFragmentContentSink;
77
class nsIFrame;
78
79
80
class nsIImageLoadingContent;
class nsIInterfaceRequestor;
class nsIIOService;
81
class nsILoadInfo;
82
class nsILoadGroup;
83
class nsNameSpaceManager;
84
class nsIObserver;
85
class nsIParser;
86
class nsIPluginTag;
87
class nsIPrincipal;
88
class nsIRequest;
89
class nsIRunnable;
90
91
92
93
class nsIScriptContext;
class nsIScriptSecurityManager;
class nsIStringBundle;
class nsIStringBundleService;
94
class nsISupportsHashKey;
95
class nsIURI;
96
class nsIUUIDGenerator;
97
class nsIWidget;
98
class nsIXPConnect;
99
class nsNodeInfoManager;
100
101
class nsPIDOMWindowInner;
class nsPIDOMWindowOuter;
102
class nsPresContext;
103
class nsStringBuffer;
104
class nsStringHashKey;
105
class nsTextFragment;
106
class nsView;
107
class nsViewportInfo;
108
class nsWrapperCache;
109
class nsAttrValue;
110
class nsITransferable;
111
class nsPIWindowRoot;
112
class nsIReferrerInfo;
113
114

struct JSRuntime;
115

116
117
118
119
120
121
122
123
template <class E>
class nsCOMArray;
template <class K, class V>
class nsDataHashtable;
template <class K, class V>
class nsRefPtrHashtable;
template <class T>
class nsReadingIterator;
124

125
namespace mozilla {
126
class Dispatcher;
127
class ErrorResult;
128
class EventListenerManager;
129
class HTMLEditor;
130
class PresShell;
131
class TextEditor;
132

133
134
struct InputEventOptions;

135
namespace dom {
136
137
class BrowserChild;
class BrowserParent;
138
139
class BrowsingContext;
class BrowsingContextGroup;
140
class ContentChild;
141
class ContentFrameMessageManager;
142
class ContentParent;
143
struct CustomElementDefinition;
144
class DataTransfer;
145
class DocumentFragment;
146
class Element;
147
class Event;
148
class EventTarget;
149
class HTMLInputElement;
150
class IPCDataTransfer;
151
class IPCDataTransferItem;
152
struct LifecycleCallbackArgs;
153
struct LifecycleAdoptedCallbackArgs;
154
class MessageBroadcaster;
155
class NodeInfo;
156
class Selection;
157
class StaticRange;
158
class WorkerPrivate;
159
}  // namespace dom
160

161
162
163
namespace ipc {
class Shmem;
class IShmemAllocator;
164
}  // namespace ipc
165

166
167
namespace gfx {
class DataSourceSurface;
168
}  // namespace gfx
169

170
171
namespace layers {
class LayerManager;
172
}  // namespace layers
173

174
}  // namespace mozilla
175

176
177
class nsIBidiKeyboard;

178
179
extern const char kLoadAsData[];

180
181
// Stolen from nsReadableUtils, but that's OK, since we can declare the same
// name multiple times.
182
183
const nsString& EmptyString();
const nsCString& EmptyCString();
184

185
186
187
188
enum EventNameType {
  EventNameType_None = 0x0000,
  EventNameType_HTML = 0x0001,
  EventNameType_XUL = 0x0002,
189
190
191
  EventNameType_SVGGraphic = 0x0004,  // svg graphic elements
  EventNameType_SVGSVG = 0x0008,      // the svg element
  EventNameType_SMIL = 0x0010,        // smil elements
192
  EventNameType_HTMLBodyOrFramesetOnly = 0x0020,
193
  EventNameType_HTMLMarqueeOnly = 0x0040,
194
195
196
197
198

  EventNameType_HTMLXUL = 0x0003,
  EventNameType_All = 0xFFFF
};

199
struct EventNameMapping {
200
201
  // This holds pointers to nsGkAtoms members, and is therefore safe as a
  // non-owning reference.
202
  nsAtom* MOZ_NON_OWNING_REF mAtom;
203
  int32_t mType;
204
  mozilla::EventMessage mMessage;
205
  mozilla::EventClassID mEventClassID;
206
207
208
  // True if mAtom is possibly used by special SVG/SMIL events, but
  // mMessage is eUnidentifiedEvent. See EventNameList.h
  bool mMaybeSpecialSVGorSMILEvent;
209
210
};

211
class nsContentUtils {
212
  friend class nsAutoScriptBlockerSuppressNodeRemoved;
213
  typedef mozilla::dom::Element Element;
214
  typedef mozilla::dom::Document Document;
215
216
  typedef mozilla::Cancelable Cancelable;
  typedef mozilla::CanBubble CanBubble;
217
  typedef mozilla::Composed Composed;
218
219
  typedef mozilla::ChromeOnlyDispatch ChromeOnlyDispatch;
  typedef mozilla::EventMessage EventMessage;
220
  typedef mozilla::TimeDuration TimeDuration;
221
  typedef mozilla::Trusted Trusted;
222

223
 public:
224
225
  static nsresult Init();

226
227
  static bool IsCallerChrome();
  static bool ThreadsafeIsCallerChrome();
228
  static bool IsCallerUAWidget();
229
230
231
232
233
234
  static bool IsFuzzingEnabled()
#ifndef FUZZING
  {
    return false;
  }
#else
235
      ;
236
#endif
237
  static bool IsErrorPage(nsIURI* aURI);
238

239
  static bool IsCallerChromeOrFuzzingEnabled(JSContext* aCx, JSObject*) {
240
241
    return ThreadsafeIsSystemCaller(aCx) || IsFuzzingEnabled();
  }
242

243
244
245
  static bool IsCallerChromeOrElementTransformGettersEnabled(JSContext* aCx,
                                                             JSObject*);

246
247
248
249
250
251
  // The APIs for checking whether the caller is system (in the sense of system
  // principal) should only be used when the JSContext is known to accurately
  // represent the caller.  In practice, that means you should only use them in
  // two situations at the moment:
  //
  // 1) Functions used in WebIDL Func annotations.
252
  // 2) Bindings code or other code called directly from the JS engine.
253
254
255
256
257
258
259
  //
  // Use pretty much anywhere else is almost certainly wrong and should be
  // replaced with [NeedsCallerType] annotations in bindings.

  // Check whether the caller is system if you know you're on the main thread.
  static bool IsSystemCaller(JSContext* aCx);

260
261
  // Check whether the caller is system if you might be on a worker or worklet
  // thread.
262
263
  static bool ThreadsafeIsSystemCaller(JSContext* aCx);

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  // In the traditional Gecko architecture, both C++ code and untrusted JS code
  // needed to rely on the same XPCOM method/getter/setter to get work done.
  // This required lots of security checks in the various exposed methods, which
  // in turn created difficulty in determining whether the caller was script
  // (whose access needed to be checked) and internal C++ platform code (whose
  // access did not need to be checked). To address this problem, Gecko had a
  // convention whereby the absence of script on the stack was interpretted as
  // "System Caller" and always granted unfettered access.
  //
  // Unfortunately, this created a bunch of footguns. For example, when the
  // implementation of a DOM method wanted to perform a privileged
  // sub-operation, it needed to "hide" the presence of script on the stack in
  // order for that sub-operation to be allowed. Additionally, if script could
  // trigger an API entry point to be invoked in some asynchronous way without
  // script on the stack, it could potentially perform privilege escalation.
  //
  // In the modern world, untrusted script should interact with the platform
  // exclusively over WebIDL APIs, and platform code has a lot more flexibility
  // in deciding whether or not to use XPCOM. This gives us the flexibility to
  // do something better.
  //
  // Going forward, APIs should be designed such that any security checks that
  // ask the question "is my caller allowed to do this?" should live in WebIDL
  // API entry points, with a separate method provided for internal callers
  // that just want to get the job done.
  //
  // To enforce this and catch bugs, nsContentUtils::SubjectPrincipal will crash
  // if it is invoked without script on the stack. To land that transition, it
  // was necessary to go through and whitelist a bunch of callers that were
  // depending on the old behavior. Those callers should be fixed up, and these
  // methods should not be used by new code without review from bholley or bz.
295
296
297
298
299
  static bool LegacyIsCallerNativeCode() { return !GetCurrentJSContext(); }
  static bool LegacyIsCallerChromeOrNativeCode() {
    return LegacyIsCallerNativeCode() || IsCallerChrome();
  }
  static nsIPrincipal* SubjectPrincipalOrSystemIfNativeCaller() {
300
301
302
303
304
305
    if (!GetCurrentJSContext()) {
      return GetSystemPrincipal();
    }
    return SubjectPrincipal();
  }

306
307
308
  static bool LookupBindingMember(
      JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
      JS::MutableHandle<JS::PropertyDescriptor> aDesc);
309

310
  // Check whether we should avoid leaking distinguishing information to JS/CSS.
311
  // This function can be called both in the main thread and worker threads.
312
  static bool ShouldResistFingerprinting();
313
  static bool ShouldResistFingerprinting(nsIDocShell* aDocShell);
314
  static bool ShouldResistFingerprinting(nsIPrincipal* aPrincipal);
315
316
  static bool ShouldResistFingerprinting(
      mozilla::dom::WorkerPrivate* aWorkerPrivate);
317
  static bool ShouldResistFingerprinting(const Document* aDoc);
318

319
320
321
  // Prevent system colors from being exposed to CSS or canvas.
  static bool UseStandinsForNativeColors();

322
323
324
325
326
  // A helper function to calculate the rounded window size for fingerprinting
  // resistance. The rounded size is based on the chrome UI size and available
  // screen size. If the inputWidth/Height is greater than the available content
  // size, this will report the available content size. Otherwise, it will
  // round the size to the nearest upper 200x100.
327
328
329
330
331
  static void CalcRoundedWindowSizeForResistingFingerprinting(
      int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
      int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
      bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
      int32_t* aOutputHeight);
332

333
334
  /**
   * Returns the parent node of aChild crossing document boundaries.
335
   * Uses the parent node in the composed document.
336
337
338
   */
  static nsINode* GetCrossDocParentNode(nsINode* aChild);

339
  /**
340
341
342
343
   * Similar to nsINode::IsInclusiveDescendantOf, except will treat an
   * HTMLTemplateElement or ShadowRoot as an ancestor of things in the
   * corresponding DocumentFragment. See the concept of "host-including
   * inclusive ancestor" in the DOM specification.
344
345
   */
  static bool ContentIsHostIncludingDescendantOf(
346
      const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor);
347

348
  /**
349
350
351
   * Similar to nsINode::IsInclusiveDescendantOf except it crosses document
   * boundaries, this function uses ancestor/descendant relations in the
   * composed document (see shadow DOM spec).
352
   */
353
  static bool ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
354
                                            nsINode* aPossibleAncestor);
355

356
357
358
359
360
361
  /**
   * As with ContentIsCrossDocDescendantOf but crosses shadow boundaries but not
   * cross document boundaries.
   *
   * @see nsINode::GetFlattenedTreeParentNode()
   */
362
363
  static bool ContentIsFlattenedTreeDescendantOf(
      const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor);
364

365
366
367
368
369
370
  /**
   * Same as `ContentIsFlattenedTreeDescendantOf`, but from the flattened tree
   * point of view of the style system
   *
   * @see nsINode::GetFlattenedTreeParentNodeForStyle()
   */
371
372
  static bool ContentIsFlattenedTreeDescendantOfForStyle(
      const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor);
373

374
375
376
377
  /**
   * Retarget an object A against an object B
   * @see https://dom.spec.whatwg.org/#retarget
   */
378
  static nsINode* Retarget(nsINode* aTargetA, nsINode* aTargetB);
379

380
  /*
381
382
   * https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor.
   *
383
384
   * This method fills the |aArray| with all ancestor nodes of |aNode|
   * including |aNode| at the zero index.
385
   *
386
   */
387
388
  static nsresult GetInclusiveAncestors(nsINode* aNode,
                                        nsTArray<nsINode*>& aArray);
389
390

  /*
391
392
   * https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor.
   *
393
394
395
396
397
398
399
   * This method fills |aAncestorNodes| with all ancestor nodes of |aNode|
   * including |aNode| (QI'd to nsIContent) at the zero index.
   * For each ancestor, there is a corresponding element in |aAncestorOffsets|
   * which is the IndexOf the child in relation to its parent.
   *
   * This method just sucks.
   */
400
401
402
  static nsresult GetInclusiveAncestorsAndOffsets(
      nsINode* aNode, int32_t aOffset, nsTArray<nsIContent*>* aAncestorNodes,
      nsTArray<int32_t>* aAncestorOffsets);
403

404
  /**
405
406
407
   * Returns the closest common inclusive ancestor
   * (https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor) , if any,
   * for two nodes.
408
409
   *
   * Returns null if the nodes are disconnected.
410
   */
411
412
  static nsINode* GetClosestCommonInclusiveAncestor(nsINode* aNode1,
                                                    nsINode* aNode2) {
413
414
415
416
417
418
    if (aNode1 == aNode2) {
      return aNode1;
    }

    return GetCommonAncestorHelper(aNode1, aNode2);
  }
419

420
421
422
423
424
  /**
   * Returns the common flattened tree ancestor, if any, for two given content
   * nodes.
   */
  static nsIContent* GetCommonFlattenedTreeAncestor(nsIContent* aContent1,
425
                                                    nsIContent* aContent2) {
426
427
428
429
430
431
    if (aContent1 == aContent2) {
      return aContent1;
    }

    return GetCommonFlattenedTreeAncestorHelper(aContent1, aContent2);
  }
432

433
434
435
436
  /**
   * Returns the common flattened tree ancestor from the point of view of the
   * style system, if any, for two given content nodes.
   */
437
438
  static Element* GetCommonFlattenedTreeAncestorForStyle(Element* aElement1,
                                                         Element* aElement2);
439

440
441
442
443
444
445
446
447
448
  /**
   * Returns the common ancestor under interactive content, if any.
   * If neither one has interactive content as ancestor, common ancestor will be
   * returned. If only one has interactive content as ancestor, null will be
   * returned. If the nodes are the same, that node is returned.
   */
  static nsINode* GetCommonAncestorUnderInteractiveContent(nsINode* aNode1,
                                                           nsINode* aNode2);

449
450
451
  /**
   * Returns true if aNode1 is before aNode2 in the same connected
   * tree.
452
453
454
455
   * aNode1Index and aNode2Index are in/out arguments. If non-null, and value is
   * not -1, that value is used instead of calling slow ComputeIndexOf on the
   * parent node. If value is -1, the value will be set to the return value of
   * ComputeIndexOf.
456
   */
457
458
459
  static bool PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
                               int32_t* aNode1Index = nullptr,
                               int32_t* aNode2Index = nullptr);
460

461
  struct ComparePointsCache {
462
    int32_t ComputeIndexOf(const nsINode* aParent, const nsINode* aChild) {
463
      if (aParent == mParent && aChild == mChild) {
464
465
466
467
468
469
470
471
472
        return mIndex;
      }

      mIndex = aParent->ComputeIndexOf(aChild);
      mParent = aParent;
      mChild = aChild;
      return mIndex;
    }

473
   private:
474
475
    const nsINode* mParent = nullptr;
    const nsINode* mChild = nullptr;
476
477
478
    int32_t mIndex = 0;
  };

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  /**
   *  Utility routine to compare two "points", where a point is a node/offset
   *  pair.
   *  Pass a cache object as aParent1Cache if you expect to repeatedly
   *  call this function with the same value as aParent1.
   *
   *  XXX aOffset1 and aOffset2 should be uint32_t since valid offset value is
   *      between 0 - UINT32_MAX.  However, these methods work even with
   *      negative offset values!  E.g., when aOffset1 is -1 and aOffset is 0,
   *      these methods return -1.  Some root callers depend on this behavior.
   *
   *  @return -1 if point1 < point2,
   *          1 if point1 > point2,
   *          0 if point1 == point2.
   *          `Nothing` if the two nodes aren't in the same connected subtree.
   */
  static Maybe<int32_t> ComparePoints(
      const nsINode* aParent1, int32_t aOffset1, const nsINode* aParent2,
      int32_t aOffset2, ComparePointsCache* aParent1Cache = nullptr);
  template <typename FPT, typename FRT, typename SPT, typename SRT>
  static Maybe<int32_t> ComparePoints(
      const mozilla::RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
      const mozilla::RangeBoundaryBase<SPT, SRT>& aSecondBoundary);

503
504
505
506
507
  /**
   *  Utility routine to compare two "points", where a point is a
   *  node/offset pair
   *  Returns -1 if point1 < point2, 1, if point1 > point2,
   *  0 if error or if point1 == point2.
508
   *  NOTE! If the two nodes aren't in the same connected subtree,
509
   *  the result is 1, and the optional aDisconnected parameter
510
   *  is set to true.
511
   *
512
513
514
   *  Pass a cache object as aParent1Cache if you expect to repeatedly
   *  call this function with the same value as aParent1.
   *
515
516
517
518
519
520
   *  XXX aOffset1 and aOffset2 should be uint32_t since valid offset value is
   *      between 0 - UINT32_MAX.  However, these methods work even with
   *      negative offset values!  E.g., when aOffset1 is -1 and aOffset is 0,
   *      these methods return -1.  Some root callers depend on this behavior.
   *      On the other hand, nsINode can have ATTRCHILD_ARRAY_MAX_CHILD_COUN
   *      (0x3FFFFF) at most.  Therefore, they can be int32_t for now.
521
   */
522
523
524
525
  static int32_t ComparePoints_Deprecated(
      const nsINode* aParent1, int32_t aOffset1, const nsINode* aParent2,
      int32_t aOffset2, bool* aDisconnected = nullptr,
      ComparePointsCache* aParent1Cache = nullptr);
526
  template <typename FPT, typename FRT, typename SPT, typename SRT>
527
  static int32_t ComparePoints_Deprecated(
528
529
530
      const mozilla::RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
      const mozilla::RangeBoundaryBase<SPT, SRT>& aSecondBoundary,
      bool* aDisconnected = nullptr);
531

532
533
  /**
   * Brute-force search of the element subtree rooted at aContent for
534
535
   * an element with the given id.  aId must be nonempty, otherwise
   * this method may return nodes even if they have no id!
536
   */
537
  static Element* MatchElementId(nsIContent* aContent, const nsAString& aId);
538

539
540
541
  /**
   * Similar to above, but to be used if one already has an atom for the ID
   */
542
  static Element* MatchElementId(nsIContent* aContent, const nsAtom* aId);
543

544
545
546
547
548
549
550
  /**
   * Reverses the document position flags passed in.
   *
   * @param   aDocumentPosition   The document position flags to be reversed.
   *
   * @return  The reversed document position flags.
   *
551
   * @see Node
552
   */
553
  static uint16_t ReverseDocumentPosition(uint16_t aDocumentPosition);
554

555
556
557
558
559
560
561
562
  /**
   * Returns a subdocument for aDocument with a particular outer window ID.
   *
   * @param aDocument
   *        The document whose subdocuments will be searched.
   * @param aOuterWindowID
   *        The outer window ID for the subdocument to be found. This must
   *        be a value greater than 0.
563
564
   * @return Document*
   *        A pointer to the found Document. nullptr if the subdocument
565
566
567
568
   *        cannot be found, or if either aDocument or aOuterWindowId were
   *        invalid. If the outer window ID belongs to aDocument itself, this
   *        will return a pointer to aDocument.
   */
569
570
  static Document* GetSubdocumentWithOuterWindowId(Document* aDocument,
                                                   uint64_t aOuterWindowId);
571

572
573
574
  static const nsDependentSubstring TrimCharsInSet(const char* aSet,
                                                   const nsAString& aValue);

575
  template <bool IsWhitespace(char16_t)>
576
  static const nsDependentSubstring TrimWhitespace(const nsAString& aStr,
577
                                                   bool aTrimTrailing = true);
578

579
  /**
580
   * Returns true if aChar is of class Ps, Pi, Po, Pf, or Pe.
581
   */
582
  static bool IsFirstLetterPunctuation(uint32_t aChar);
583

584
585
586
  /**
   * Returns true if aChar is of class Lu, Ll, Lt, Lm, Lo, Nd, Nl or No
   */
587
588
  static bool IsAlphanumeric(uint32_t aChar);
  static bool IsAlphanumericAt(const nsTextFragment* aFrag, uint32_t aOffset);
589

590
591
592
593
594
595
596
597
  /*
   * Is the character an HTML whitespace character?
   *
   * We define whitespace using the list in HTML5 and css3-selectors:
   * U+0009, U+000A, U+000C, U+000D, U+0020
   *
   * HTML 4.01 also lists U+200B (zero-width space).
   */
598
  static bool IsHTMLWhitespace(char16_t aChar);
599

600
601
602
603
  /*
   * Returns whether the character is an HTML whitespace (see IsHTMLWhitespace)
   * or a nbsp character (U+00A0).
   */
604
  static bool IsHTMLWhitespaceOrNBSP(char16_t aChar);
605

606
  /**
607
   * https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
608
   */
609
  static bool IsHTMLBlockLevelElement(nsIContent* aContent);
610

611
  enum ParseHTMLIntegerResultFlags {
612
    eParseHTMLInteger_NoFlags = 0,
613
    // eParseHTMLInteger_NonStandard is set if the string representation of the
614
615
616
617
618
619
    // integer was not the canonical one, but matches at least one of the
    // following:
    //   * had leading whitespaces
    //   * had '+' sign
    //   * had leading '0'
    //   * was '-0'
620
621
    eParseHTMLInteger_NonStandard = 1 << 0,
    eParseHTMLInteger_DidNotConsumeAllInput = 1 << 1,
622
    // Set if one or more error flags were set.
623
624
625
    eParseHTMLInteger_Error = 1 << 2,
    eParseHTMLInteger_ErrorNoValue = 1 << 3,
    eParseHTMLInteger_ErrorOverflow = 1 << 4,
626
    // Use this flag to detect the difference between overflow and underflow
627
    eParseHTMLInteger_Negative = 1 << 5,
628
629
  };
  static int32_t ParseHTMLInteger(const nsAString& aValue,
630
                                  ParseHTMLIntegerResultFlags* aResult);
631
632
633
634
635
636
637
  static int32_t ParseHTMLInteger(const nsACString& aValue,
                                  ParseHTMLIntegerResultFlags* aResult);

 private:
  template <class StringT>
  static int32_t ParseHTMLIntegerImpl(const StringT& aValue,
                                      ParseHTMLIntegerResultFlags* aResult);
638

639
 public:
640
641
642
643
644
645
646
647
  /**
   * Parse a margin string of format 'top, right, bottom, left' into
   * an nsIntMargin.
   *
   * @param aString the string to parse
   * @param aResult the resulting integer
   * @return whether the value could be parsed
   */
648
649
  static bool ParseIntMarginValue(const nsAString& aString,
                                  nsIntMargin& aResult);
650

651
652
653
654
655
656
657
  /**
   * Parse the value of the <font size=""> attribute according to the HTML5
   * spec as of April 16, 2012.
   *
   * @param aValue the value to parse
   * @return 1 to 7, or 0 if the value couldn't be parsed
   */
658
  static int32_t ParseLegacyFontSize(const nsAString& aValue);
659

660
  static void Shutdown();
661

662
  /**
663
   * Checks whether two nodes come from the same origin.
664
   */
665
666
  static nsresult CheckSameOrigin(const nsINode* aTrustedNode,
                                  const nsINode* unTrustedNode);
667

668
  // Check if the (JS) caller can access aNode.
669
  static bool CanCallerAccess(const nsINode* aNode);
670

671
672
  // Check if the (JS) caller can access aWindow.
  // aWindow can be either outer or inner window.
673
  static bool CanCallerAccess(nsPIDOMWindowInner* aWindow);
674

675
  // Check if the principal is chrome or an addon with the permission.
676
  static bool PrincipalHasPermission(nsIPrincipal& aPrincipal,
677
                                     const nsAtom* aPerm);
678

679
  // Check if the JS caller is chrome or an addon with the permission.
680
  static bool CallerHasPermission(JSContext* aCx, const nsAtom* aPerm);
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  /**
   * Returns the triggering principal which should be used for the given URL
   * attribute value with the given subject principal.
   *
   * If the attribute value is not an absolute URL, the subject principal will
   * be ignored, and the node principal of aContent will be used instead.
   * If aContent is non-null, this function will always return a principal.
   * Otherewise, it may return null if aSubjectPrincipal is null or is rejected
   * based on the attribute value.
   *
   * @param aContent The content on which the attribute is being set.
   * @param aAttrValue The URL value of the attribute. For parsed attribute
   *        values, such as `srcset`, this function should be called separately
   *        for each URL value it contains.
   * @param aSubjectPrincipal The subject principal of the scripted caller
   *        responsible for setting the attribute, or null if no scripted caller
   *        can be determined.
   */
700
701
702
  static nsIPrincipal* GetAttrTriggeringPrincipal(
      nsIContent* aContent, const nsAString& aAttrValue,
      nsIPrincipal* aSubjectPrincipal);
703
704
705
706
707
708
709
710
711
712
713
714
715

  /**
   * Returns true if the given string is guaranteed to be treated as an absolute
   * URL, rather than a relative URL. In practice, this means any complete URL
   * as supported by nsStandardURL, or any string beginning with a valid scheme
   * which is known to the IO service, and has the URI_NORELATIVE flag.
   *
   * If the URL may be treated as absolute in some cases, but relative in others
   * (for instance, "http:foo", which can be either an absolute or relative URL,
   * depending on the context), this function returns false.
   */
  static bool IsAbsoluteURL(const nsACString& aURL);

716
717
  // Check if a node is in the document prolog, i.e. before the document
  // element.
718
  static bool InProlog(nsINode* aNode);
719

720
  static nsNameSpaceManager* NameSpaceManager() { return sNameSpaceManager; }
721

722
  static nsIIOService* GetIOService() { return sIOService; }
723

724
  static nsIBidiKeyboard* GetBidiKeyboard();
725

726
727
728
729
  /**
   * Get the cache security manager service. Can return null if the layout
   * module has been shut down.
   */
730
  static nsIScriptSecurityManager* GetSecurityManager() {
731
732
    return sSecurityManager;
  }
733

734
735
736
737
  // Returns the subject principal from the JSContext. May only be called
  // from the main thread and assumes an existing compartment.
  static nsIPrincipal* SubjectPrincipal(JSContext* aCx);

738
739
  // Returns the subject principal. Guaranteed to return non-null. May only
  // be called when nsContentUtils is initialized.
740
741
742
  static nsIPrincipal* SubjectPrincipal();

  // Returns the prinipal of the given JS object. This may only be called on
743
744
745
  // the main thread for objects from the main thread's JSRuntime. The object
  // must not be a cross-compartment wrapper, because CCWs are not associated
  // with a single realm.
746
  static nsIPrincipal* ObjectPrincipal(JSObject* aObj);
747

748
749
  static void GenerateStateKey(nsIContent* aContent, Document* aDocument,
                               nsACString& aKey);
750

751
  /**
752
753
754
   * Create a new nsIURI from aSpec, using aBaseURI as the base.  The
   * origin charset of the new nsIURI will be the document charset of
   * aDocument.
755
756
757
   */
  static nsresult NewURIWithDocumentCharset(nsIURI** aResult,
                                            const nsAString& aSpec,
758
                                            Document* aDocument,
759
                                            nsIURI* aBaseURI);
760

761
762
763
764
765
  /**
   * Returns true if |aName| is a name with dashes.
   */
  static bool IsNameWithDash(nsAtom* aName);

766
767
  /**
   * Returns true if |aName| is a valid name to be registered via
768
   * customElements.define.
769
   */
770
  static bool IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID);
771

772
  static nsresult CheckQName(const nsAString& aQualifiedName,
773
                             bool aNamespaceAware = true,
774
                             const char16_t** aColon = nullptr);
775

776
  static nsresult SplitQName(const nsIContent* aNamespaceResolver,
777
778
                             const nsString& aQName, int32_t* aNamespace,
                             nsAtom** aLocalName);
779

780
781
  static nsresult GetNodeInfoFromQName(const nsAString& aNamespaceURI,
                                       const nsAString& aQualifiedName,
782
                                       nsNodeInfoManager* aNodeInfoManager,
783
                                       uint16_t aNodeType,
784
                                       mozilla::dom::NodeInfo** aNodeInfo);
785

786
787
  static void SplitExpatName(const char16_t* aExpatName, nsAtom** aPrefix,
                             nsAtom** aTagName, int32_t* aNameSpaceID);
788

789
  // Get a permission-manager setting for the given principal and type.
790
  // If the pref doesn't exist or if it isn't ALLOW_ACTION, false is
791
792
  // returned, otherwise true is returned. Always returns true for the
  // system principal, and false for a null principal.
793
794
  static bool IsSitePermAllow(nsIPrincipal* aPrincipal,
                              const nsACString& aType);
795
796
797
798
799

  // Get a permission-manager setting for the given principal and type.
  // If the pref doesn't exist or if it isn't DENY_ACTION, false is
  // returned, otherwise true is returned. Always returns false for the
  // system principal, and true for a null principal.
800
  static bool IsSitePermDeny(nsIPrincipal* aPrincipal, const nsACString& aType);
801
802
803
804
805
806
807

  // Get a permission-manager setting for the given principal and type.
  // If the pref doesn't exist or if it isn't ALLOW_ACTION, false is
  // returned, otherwise true is returned. Always returns true for the
  // system principal, and false for a null principal.
  // This version checks the permission for an exact host match on
  // the principal
808
809
  static bool IsExactSitePermAllow(nsIPrincipal* aPrincipal,
                                   const nsACString& aType);
810
811
812
813
814
815
816

  // Get a permission-manager setting for the given principal and type.
  // If the pref doesn't exist or if it isn't DENY_ACTION, false is
  // returned, otherwise true is returned. Always returns false for the
  // system principal, and true for a null principal.
  // This version checks the permission for an exact host match on
  // the principal
817
818
  static bool IsExactSitePermDeny(nsIPrincipal* aPrincipal,
                                  const nsACString& aType);
819

820
  // Returns true if aDoc1 and aDoc2 have equal NodePrincipal()s.
821
  static bool HaveEqualPrincipals(Document* aDoc1, Document* aDoc2);
822

823
  static mozilla::intl::LineBreaker* LineBreaker() {
824
    return sLineBreaker.get();
825
826
  }

827
  static mozilla::intl::WordBreaker* WordBreaker() {
828
    return sWordBreaker.get();
829
830
  }

831
832
833
834
835
836
837
  /**
   * Regster aObserver as a shutdown observer. A strong reference is held
   * to aObserver until UnregisterShutdownObserver is called.
   */
  static void RegisterShutdownObserver(nsIObserver* aObserver);
  static void UnregisterShutdownObserver(nsIObserver* aObserver);

838
  /**
839
   * @return true if aContent has an attribute aName in namespace aNameSpaceID,
840
841
   * and the attribute value is non-empty.
   */
842
  static bool HasNonEmptyAttr(const nsIContent* aContent, int32_t aNameSpaceID,
843
                              nsAtom* aName);
844

845
846
  /**
   * Method that gets the primary presContext for the node.
847
   *
848
   * @param aContent The content node.
849
   * @return the presContext, or nullptr if the content is not in a document
850
   *         (if GetComposedDoc returns nullptr)
851
   */
852
  static nsPresContext* GetContextForContent(const nsIContent* aContent);
853

854
855
856
857
858
859
860
  /**
   * Method that gets the pres shell for the node.
   *
   * @param aContent The content node.
   * @return the pres shell, or nullptr if the content is not in a document
   *         (if GetComposedDoc returns nullptr)
   */
861
  static mozilla::PresShell* GetPresShellForContent(const nsIContent* aContent);
862