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

/* A namespace class for static layout utilities. */

9
#include "nsContentUtils.h"
10

11
12
13
14
15
16
17
18
19
20
#include <algorithm>
#include <math.h>

#include "DecoderTraits.h"
#include "harfbuzz/hb.h"
#include "imgICache.h"
#include "imgIContainer.h"
#include "imgINotificationObserver.h"
#include "imgLoader.h"
#include "imgRequestProxy.h"
21
#include "jsapi.h"
22
#include "jsfriendapi.h"
23
#include "js/Array.h"  // JS::NewArrayObject
24
#include "js/ArrayBuffer.h"  // JS::{GetArrayBufferData,IsArrayBufferObject,NewArrayBuffer}
25
#include "js/JSON.h"
26
#include "js/RegExp.h"  // JS::ExecuteRegExpNoStatics, JS::NewUCRegExpObject, JS::RegExpFlags
27
#include "js/Value.h"
28
#include "Layers.h"
29
#include "nsAppRunner.h"
30
31
// nsNPAPIPluginInstance must be included before mozilla/dom/Document.h, which
// is included in mozAutoDocUpdate.h.
32
#include "nsNPAPIPluginInstance.h"
33
34
#include "gfxDrawable.h"
#include "ImageOps.h"
35
#include "mozAutoDocUpdate.h"
36
#include "mozilla/net/UrlClassifierCommon.h"
37
#include "mozilla/ArrayUtils.h"
38
#include "mozilla/Attributes.h"
39
#include "mozilla/AutoRestore.h"
40
#include "mozilla/AutoTimelineMarker.h"
41
#include "mozilla/BackgroundHangMonitor.h"
42
#include "mozilla/Base64.h"
43
#include "mozilla/BasePrincipal.h"
44
#include "mozilla/CheckedInt.h"
45
#include "mozilla/Components.h"
46
#include "mozilla/DebugOnly.h"
47
#include "mozilla/LoadInfo.h"
48
#include "mozilla/dom/AncestorIterator.h"
49
#include "mozilla/dom/BlobURLProtocolHandler.h"
50
51
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
52
#include "mozilla/dom/ContentParent.h"
53
#include "mozilla/dom/ContentChild.h"
54
#include "mozilla/dom/CustomElementRegistry.h"
55
#include "mozilla/dom/Document.h"
56
#include "mozilla/dom/DocumentInlines.h"
57
#include "mozilla/dom/MessageBroadcaster.h"
58
#include "mozilla/dom/DocumentFragment.h"
59
60
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
61
#include "mozilla/dom/DOMSecurityMonitor.h"
62
#include "mozilla/dom/DOMTypes.h"
63
#include "mozilla/dom/Element.h"
64
#include "mozilla/dom/ElementInlines.h"
65
#include "mozilla/dom/Event.h"
66
#include "mozilla/dom/FileSystemSecurity.h"
67
#include "mozilla/dom/FileBlobImpl.h"
68
#include "mozilla/dom/FontTableURIProtocolHandler.h"
69
#include "mozilla/dom/HTMLInputElement.h"
70
#include "mozilla/dom/HTMLSlotElement.h"
71
#include "mozilla/dom/HTMLTemplateElement.h"
72
#include "mozilla/dom/HTMLTextAreaElement.h"
73
#include "mozilla/dom/IDTracker.h"
74
#include "mozilla/dom/MouseEventBinding.h"
75
#include "mozilla/dom/KeyboardEventBinding.h"
76
#include "mozilla/dom/IPCBlobUtils.h"
77
#include "mozilla/dom/NodeBinding.h"
78
#include "mozilla/dom/Promise.h"
79
#include "mozilla/dom/BrowserBridgeChild.h"
80
#include "mozilla/dom/ScriptSettings.h"
81
#include "mozilla/dom/BrowserParent.h"
82
#include "mozilla/dom/Text.h"
83
#include "mozilla/dom/TouchEvent.h"
84
#include "mozilla/dom/ShadowRoot.h"
85
#include "mozilla/dom/XULCommandEvent.h"
86
#include "mozilla/dom/UserActivation.h"
87
#include "mozilla/dom/WorkerCommon.h"
88
#include "mozilla/dom/WorkerPrivate.h"
89
#include "mozilla/extensions/WebExtensionPolicy.h"
90
#include "mozilla/net/CookieJarSettings.h"
91
#include "mozilla/EventDispatcher.h"
92
#include "mozilla/EventListenerManager.h"
93
#include "mozilla/EventStateManager.h"
94
#include "mozilla/gfx/DataSurfaceHelpers.h"
95
#include "mozilla/HTMLEditor.h"
96
#include "mozilla/IMEStateManager.h"
97
#include "mozilla/InputEventOptions.h"
98
#include "mozilla/InternalMutationEvent.h"
99
#include "mozilla/Likely.h"
100
#include "mozilla/ManualNAC.h"
101
#include "mozilla/MouseEvents.h"
102
#include "mozilla/Preferences.h"
103
#include "mozilla/PresShell.h"
104
#include "mozilla/ResultExtensions.h"
105
#include "mozilla/dom/Selection.h"
106
#include "mozilla/Services.h"
107
108
109
110
111
112
113
114
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_full_screen_api.h"
#ifdef FUZZING
#  include "mozilla/StaticPrefs_fuzzing.h"
#endif
#include "mozilla/StaticPrefs_privacy.h"
#include "mozilla/StaticPrefs_test.h"
#include "mozilla/StaticPrefs_ui.h"
115
#include "mozilla/StoragePrincipalHelper.h"
116
#include "mozilla/TextControlState.h"
117
#include "mozilla/TextEditor.h"
118
#include "mozilla/TextEvents.h"
119
#include "mozilla/ViewportUtils.h"
120
#include "nsArrayUtils.h"
121
#include "nsAString.h"
122
123
124
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
125
#include "nsCanvasFrame.h"
126
#include "nsCaret.h"
127
128
129
130
131
132
133
#include "nsCCUncollectableMarker.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsCOMPtr.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentDLF.h"
#include "nsContentList.h"
#include "nsContentPolicyUtils.h"
134
#include "nsContentSecurityManager.h"
135
136
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
137
#include "nsCycleCollector.h"
138
#include "nsDataHashtable.h"
139
#include "nsDocShellCID.h"
140
#include "nsDOMCID.h"
141
#include "mozilla/dom/DataTransfer.h"
142
143
144
145
#include "nsDOMJSUtils.h"
#include "nsDOMMutationObserver.h"
#include "nsError.h"
#include "nsFocusManager.h"
146
#include "nsFrameLoaderOwner.h"
147
#include "nsGenericHTMLElement.h"
148
#include "nsGenericHTMLFrameElement.h"
149
150
#include "nsGkAtoms.h"
#include "nsHtml5Module.h"
151
#include "nsHtml5StringParser.h"
152
#include "nsHTMLDocument.h"
153
#include "nsHTMLTags.h"
154
#include "nsIAnonymousContentCreator.h"
155
156
157
158
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsICategoryManager.h"
#include "nsIChannelEventSink.h"
#include "nsIConsoleService.h"
159
#include "nsIContent.h"
160
#include "nsIContentInlines.h"
161
162
163
164
#include "nsIContentSecurityPolicy.h"
#include "nsIContentSink.h"
#include "nsIContentViewer.h"
#include "nsIDocShell.h"
165
#include "nsIDocShellTreeOwner.h"
166
#include "mozilla/dom/Document.h"
167
#include "nsIDocumentEncoder.h"
168
#include "nsIDOMWindowUtils.h"
169
170
171
#include "nsIDragService.h"
#include "nsIFormControl.h"
#include "nsIForm.h"
172
#include "nsIFragmentContentSink.h"
173
#include "nsContainerFrame.h"
174
#include "nsIClassifiedChannel.h"
175
#include "nsIHttpChannelInternal.h"
176
#include "nsIIdleService.h"
177
178
179
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
180
181
#include "nsIIOService.h"
#include "nsILoadContext.h"
182
#include "nsILoadGroup.h"
183
#include "nsIMemoryReporter.h"
184
#include "nsIMIMEService.h"
185
#include "nsINode.h"
186
#include "mozilla/dom/NodeInfo.h"
187
#include "mozilla/NullPrincipal.h"
188
#include "nsIObjectLoadingContent.h"
189
190
#include "nsIObserver.h"
#include "nsIObserverService.h"
191
192
#include "nsIOfflineCacheUpdate.h"
#include "nsIParser.h"
193
#include "nsIParserUtils.h"
194
#include "nsIPermissionManager.h"
195
#include "nsIRequest.h"
196
197
198
199
200
201
#include "nsIRunnable.h"
#include "nsIScriptContext.h"
#include "nsIScriptError.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptSecurityManager.h"
202
#include "nsIStreamConverter.h"
203
#include "nsIStreamConverterService.h"
204
#include "nsIStringBundle.h"
205
#include "nsIURI.h"
206
#include "nsIURIMutator.h"
207
#include "nsIURIWithSpecialOrigin.h"
208
#include "nsIUUIDGenerator.h"
209
#include "nsIWebNavigation.h"
210
#include "nsIWidget.h"
211
#include "nsIWindowMediator.h"
212
213
#include "nsIXPConnect.h"
#include "nsJSUtils.h"
214
#include "nsMappedAttributes.h"
215
216
217
218
219
220
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsNodeInfoManager.h"
#include "nsParserCIID.h"
#include "nsParserConstants.h"
#include "nsPIDOMWindow.h"
221
#include "nsPresContext.h"
222
#include "nsPrintfCString.h"
223
#include "nsQueryObject.h"
224
225
#include "nsSandboxFlags.h"
#include "nsScriptSecurityManager.h"
226
#include "nsSerializationHelper.h"
227
#include "nsStreamUtils.h"
228
#include "nsTextFragment.h"
229
#include "nsTextNode.h"
230
#include "nsThreadUtils.h"
231
#include "nsTreeSanitizer.h"
232
#include "nsUnicodeProperties.h"
233
#include "nsURLHelper.h"
234
235
#include "nsViewManager.h"
#include "nsViewportInfo.h"
236
#include "nsWidgetsCID.h"
237
238
#include "nsWrapperCacheInlines.h"
#include "nsXULPopupManager.h"
239
#include "xpcprivate.h"  // nsXPConnect
240
#include "HTMLSplitOnSpacesTokenizer.h"
241
#include "InProcessBrowserChildMessageManager.h"
242
#include "nsContentTypeParser.h"
243
#include "ThirdPartyUtil.h"
244
#include "mozilla/EnumSet.h"
245
#include "mozilla/BloomFilter.h"
246
#include "BrowserChild.h"
247
#include "mozilla/dom/DocGroup.h"
248
249
#include "nsIWebNavigationInfo.h"
#include "nsPluginHost.h"
250
#include "nsIBrowser.h"
251
#include "mozilla/HangAnnotations.h"
252
#include "mozilla/Encoding.h"
253
#include "nsXULElement.h"
254
#include "nsThreadManager.h"
255
#include "nsIBidiKeyboard.h"
256
#include "ReferrerInfo.h"
257
#include "nsAboutProtocolUtils.h"
258

259
260
#if defined(XP_WIN)
// Undefine LoadImage to prevent naming conflict with Windows.
261
#  undef LoadImage
262
263
#endif

264
extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
265
                                      const char** next, char16_t* result);
266
267
extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
                                 const char** colon);
268

269
class imgLoader;
270
class nsAtom;
271

272
using namespace mozilla::dom;
273
using namespace mozilla::ipc;
274
using namespace mozilla::gfx;
275
using namespace mozilla::layers;
276
using namespace mozilla::widget;
277
using namespace mozilla;
278

279
280
const char kLoadAsData[] = "loadAsData";

281
282
283
284
285
286
287
288
289
290
291
292
nsIXPConnect* nsContentUtils::sXPConnect;
nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
nsIPrincipal* nsContentUtils::sSystemPrincipal;
nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
nsNameSpaceManager* nsContentUtils::sNameSpaceManager;
nsIIOService* nsContentUtils::sIOService;
nsIUUIDGenerator* nsContentUtils::sUUIDGenerator;
nsIConsoleService* nsContentUtils::sConsoleService;
nsDataHashtable<nsRefPtrHashKey<nsAtom>, EventNameMapping>*
    nsContentUtils::sAtomEventTable = nullptr;
nsDataHashtable<nsStringHashKey, EventNameMapping>*
    nsContentUtils::sStringEventTable = nullptr;
293
nsTArray<RefPtr<nsAtom>>* nsContentUtils::sUserDefinedEvents = nullptr;
294
295
296
nsIStringBundleService* nsContentUtils::sStringBundleService;
nsIStringBundle* nsContentUtils::sStringBundles[PropertiesFile_COUNT];
nsIContentPolicy* nsContentUtils::sContentPolicyService;
297
bool nsContentUtils::sTriedToGetContentPolicy = false;
298
RefPtr<mozilla::intl::LineBreaker> nsContentUtils::sLineBreaker;
299
RefPtr<mozilla::intl::WordBreaker> nsContentUtils::sWordBreaker;
300
StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
301
302
uint32_t nsContentUtils::sScriptBlockerCount = 0;
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
303
304
AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
    nullptr;
305
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
306
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
307

308
bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
309

310
311
312
313
314
315
nsString* nsContentUtils::sShiftText = nullptr;
nsString* nsContentUtils::sControlText = nullptr;
nsString* nsContentUtils::sMetaText = nullptr;
nsString* nsContentUtils::sOSText = nullptr;
nsString* nsContentUtils::sAltText = nullptr;
nsString* nsContentUtils::sModifierSeparator = nullptr;
316

317
bool nsContentUtils::sInitialized = false;
318
319
320
#ifndef RELEASE_OR_BETA
bool nsContentUtils::sBypassCSSOMOriginCheck = false;
#endif
321
322

nsCString* nsContentUtils::sJSBytecodeMimeType = nullptr;
323

324
nsContentUtils::UserInteractionObserver*
325
    nsContentUtils::sUserInteractionObserver = nullptr;
326

327
328
329
nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
330
bool nsContentUtils::sFragmentParsingActive = false;
331

332
333
mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");

334
335
336
int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;

337
338
339
340
341
342
343
344
345
346
347
348
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RawRangeBoundary& aFirstBoundary,
    const RangeBoundary& aSecondBoundary);
template Maybe<int32_t> nsContentUtils::ComparePoints(
    const RawRangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary);

349
template int32_t nsContentUtils::ComparePoints_Deprecated(
350
351
    const RangeBoundary& aFirstBoundary, const RangeBoundary& aSecondBoundary,
    bool* aDisconnected);
352
template int32_t nsContentUtils::ComparePoints_Deprecated(
353
354
    const RangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);
355
template int32_t nsContentUtils::ComparePoints_Deprecated(
356
357
    const RawRangeBoundary& aFirstBoundary,
    const RangeBoundary& aSecondBoundary, bool* aDisconnected);
358
template int32_t nsContentUtils::ComparePoints_Deprecated(
359
360
361
    const RawRangeBoundary& aFirstBoundary,
    const RawRangeBoundary& aSecondBoundary, bool* aDisconnected);

362
363
364
365
366
367
368
// Subset of
// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
enum AutocompleteUnsupportedFieldName : uint8_t {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
  eAutocompleteUnsupportedFieldName_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
369
370
};

371
372
373
374
375
376
377
enum AutocompleteNoPersistFieldName : uint8_t {
#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
  eAutocompleteNoPersistFieldName_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
};

378
379
380
381
382
enum AutocompleteUnsupportFieldContactHint : uint8_t {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
  eAutocompleteUnsupportedFieldContactHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
383
384
};

385
386
387
388
389
390
391
enum AutocompleteFieldName : uint8_t {
#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
  AUTOCOMPLETE_FIELD_NAME(name_, value_)
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_NAME
#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
392
393
};

394
395
396
397
enum AutocompleteFieldHint : uint8_t {
#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_HINT
398
399
};

400
401
402
403
404
enum AutocompleteFieldContactHint : uint8_t {
#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
  eAutocompleteFieldContactHint_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
405
406
};

407
408
409
410
enum AutocompleteCategory {
#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CATEGORY
411
412
};

413
static const nsAttrValue::EnumTable kAutocompleteUnsupportedFieldNameTable[] = {
414
415
416
417
418
419
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteUnsupportedFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
    {nullptr, 0}};

420
421
422
423
424
425
426
static const nsAttrValue::EnumTable kAutocompleteNoPersistFieldNameTable[] = {
#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteNoPersistFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
    {nullptr, 0}};

427
428
429
430
431
432
433
static const nsAttrValue::EnumTable
    kAutocompleteUnsupportedContactFieldHintTable[] = {
#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
  {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
        {nullptr, 0}};
434

435
static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
436
437
438
439
440
#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_NAME
    {nullptr, 0}};
441
442

static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
443
444
445
446
447
#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
  {value_, eAutocompleteFieldName_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
    {nullptr, 0}};
448
449

static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
450
451
452
453
454
#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
  {value_, eAutocompleteFieldHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_HINT
    {nullptr, 0}};
455
456

static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
457
458
459
460
461
#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
  {value_, eAutocompleteFieldContactHint_##name_},
#include "AutocompleteFieldList.h"
#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
    {nullptr, 0}};
462

463
464
465
466
namespace {

static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);

467
static PLDHashTable* sEventListenerManagersHash;
468

469
470
471
472
473
// A global hashtable to for keeping the arena alive for cross docGroup node
// adoption.
static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
    sDOMArenaHashtable;

474
class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter {
475
476
  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)

477
  ~DOMEventListenerManagersHashReporter() = default;
478

479
 public:
480
  NS_DECL_ISUPPORTS
481

482
  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
483
                            nsISupports* aData, bool aAnonymize) override {
484
    // We don't measure the |EventListenerManager| objects pointed to by the
485
    // entries because those references are non-owning.
486
487
488
489
490
    int64_t amount =
        sEventListenerManagersHash
            ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
                  MallocSizeOf)
            : 0;
491

492
    MOZ_COLLECT_REPORT(
493
494
        "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
        amount, "Memory used by the event listener manager's hash table.");
495
496

    return NS_OK;
497
498
  }
};
499

500
NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
501

502
503
504
class EventListenerManagerMapEntry : public PLDHashEntryHdr {
 public:
  explicit EventListenerManagerMapEntry(const void* aKey) : mKey(aKey) {}
505

506
  ~EventListenerManagerMapEntry() {
507
    NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
508
509
  }

510
511
 protected:          // declared protected to silence clang warnings
  const void* mKey;  // must be first, to look like PLDHashEntryStub
512

513
 public:
514
  RefPtr<EventListenerManager> mListenerManager;
515
516
};

517
518
static void EventListenerManagerHashInitEntry(PLDHashEntryHdr* entry,
                                              const void* key) {
519
520
521
522
  // Initialize the entry with placement new
  new (entry) EventListenerManagerMapEntry(key);
}

523
524
525
526
static void EventListenerManagerHashClearEntry(PLDHashTable* table,
                                               PLDHashEntryHdr* entry) {
  EventListenerManagerMapEntry* lm =
      static_cast<EventListenerManagerMapEntry*>(entry);
527
528
529
530
531

  // Let the EventListenerManagerMapEntry clean itself up...
  lm->~EventListenerManagerMapEntry();
}

532
class SameOriginCheckerImpl final : public nsIChannelEventSink,
533
                                    public nsIInterfaceRequestor {
534
  ~SameOriginCheckerImpl() = default;
535

536
537
538
539
540
  NS_DECL_ISUPPORTS
  NS_DECL_NSICHANNELEVENTSINK
  NS_DECL_NSIINTERFACEREQUESTOR
};

541
}  // namespace
542

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
AutoSuppressEventHandlingAndSuspend::AutoSuppressEventHandlingAndSuspend(
    BrowsingContextGroup* aGroup) {
  for (const auto& bc : aGroup->Toplevels()) {
    SuppressBrowsingContext(bc);
  }
}

void AutoSuppressEventHandlingAndSuspend::SuppressBrowsingContext(
    BrowsingContext* aBC) {
  if (nsCOMPtr<nsPIDOMWindowOuter> win = aBC->GetDOMWindow()) {
    if (RefPtr<Document> doc = win->GetExtantDoc()) {
      mDocuments.AppendElement(doc);
      mWindows.AppendElement(win->GetCurrentInnerWindow());
      // Note: Document::SuppressEventHandling will also automatically suppress
      // event handling for any in-process sub-documents. However, since we need
      // to deal with cases where remote BrowsingContexts may be interleaved
      // with in-process ones, we still need to walk the entire tree ourselves.
      // This may be slightly redundant in some cases, but since event handling
      // suppressions maintain a count of current blockers, it does not cause
      // any problems.
      doc->SuppressEventHandling();
      win->GetCurrentInnerWindow()->Suspend();
    }
  }

568
  for (const auto& bc : aBC->Children()) {
569
570
571
572
573
574
575
576
577
578
579
580
581
    SuppressBrowsingContext(bc);
  }
}

AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
  for (const auto& win : mWindows) {
    win->Resume();
  }
  for (const auto& doc : mDocuments) {
    doc->UnsuppressEventHandlingAndFireEvents(true);
  }
}

582
583
584
585
586
587
588
589
590
/**
 * This class is used to determine whether or not the user is currently
 * interacting with the browser. It listens to observer events to toggle the
 * value of the sUserActive static.
 *
 * This class is an internal implementation detail.
 * nsContentUtils::GetUserIsInteracting() should be used to access current
 * user interaction status.
 */
591
592
593
594
class nsContentUtils::UserInteractionObserver final
    : public nsIObserver,
      public BackgroundHangAnnotator {
 public:
595
596
597
598
599
  NS_DECL_ISUPPORTS
  NS_DECL_NSIOBSERVER

  void Init();
  void Shutdown();
600
  void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
601
602
603

  static Atomic<bool> sUserActive;

604
 private:
605
  ~UserInteractionObserver() = default;
606
607
};

608
// static
609
nsresult nsContentUtils::Init() {
610
611
612
613
614
  if (sInitialized) {
    NS_WARNING("Init() called twice");

    return NS_OK;
  }
615

616
617
  nsHTMLTags::AddRefTable();

618
619
  sNameSpaceManager = nsNameSpaceManager::GetInstance();
  NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
620

621
  sXPConnect = nsXPConnect::XPConnect();
622
623
624
625
626
627
628
  // We hold a strong ref to sXPConnect to ensure that it does not go away until
  // nsLayoutStatics::Shutdown is happening.  Otherwise ~nsXPConnect can be
  // triggered by xpcModuleDtor late in shutdown and cause crashes due to
  // various stuff already being torn down by then.  Note that this means that
  // we are effectively making sure that if we leak nsLayoutStatics then we also
  // leak nsXPConnect.
  NS_ADDREF(sXPConnect);
629
630

  sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
631
  if (!sSecurityManager) return NS_ERROR_FAILURE;
632
  NS_ADDREF(sSecurityManager);
633

634
635
  sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
  MOZ_ASSERT(sSystemPrincipal);
636

637
638
  RefPtr<NullPrincipal> nullPrincipal =
      NullPrincipal::CreateWithoutOriginAttributes();
639
640
641
642
  if (!nullPrincipal) {
    return NS_ERROR_FAILURE;
  }

643
  nullPrincipal.forget(&sNullSubjectPrincipal);
644

645
  nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
646
  if (NS_FAILED(rv)) {
647
648
    // This makes life easier, but we can live without it.

649
    sIOService = nullptr;
650
  }
651

652
  sLineBreaker = mozilla::intl::LineBreaker::Create();
653

654
  sWordBreaker = mozilla::intl::WordBreaker::Create();
655

656
  if (!InitializeEventTable()) return NS_ERROR_FAILURE;
657

658
  if (!sEventListenerManagersHash) {
659
660
661
662
    static const PLDHashTableOps hash_table_ops = {
        PLDHashTable::HashVoidPtrKeyStub, PLDHashTable::MatchEntryStub,
        PLDHashTable::MoveEntryStub, EventListenerManagerHashClearEntry,
        EventListenerManagerHashInitEntry};
663

664
    sEventListenerManagersHash =
665
        new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
666

667
    RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
668
669
  }

670
  sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
671

672
673
674
675
#ifndef RELEASE_OR_BETA
  sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
#endif

676
  nsDependentCString buildID(mozilla::PlatformBuildID());
677
678
  sJSBytecodeMimeType =
      new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
679

680
  Element::InitCCCallbacks();
681

682
683
  Unused << nsRFPService::GetOrCreate();

684
  nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
685
      do_GetService("@mozilla.org/uuid-generator;1", &rv);
686
687
688
689
690
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }
  uuidGenerator.forget(&sUUIDGenerator);

691
692
693
  if (XRE_IsParentProcess()) {
    AsyncPrecreateStringBundles();
  }
694

695
696
697
698
  RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
  uio->Init();
  uio.forget(&sUserInteractionObserver);

699
  sInitialized = true;
700

701
  return NS_OK;
702
}
703

704
705
void nsContentUtils::GetShiftText(nsAString& text) {
  if (!sShiftText) InitializeModifierStrings();
706
707
708
  text.Assign(*sShiftText);
}

709
710
void nsContentUtils::GetControlText(nsAString& text) {
  if (!sControlText) InitializeModifierStrings();
711
712
713
  text.Assign(*sControlText);
}

714
715
void nsContentUtils::GetMetaText(nsAString& text) {
  if (!sMetaText) InitializeModifierStrings();
716
717
718
  text.Assign(*sMetaText);
}

719
void nsContentUtils::GetOSText(nsAString& text) {
720
721
722
723
724
725
  if (!sOSText) {
    InitializeModifierStrings();
  }
  text.Assign(*sOSText);
}

726
727
void nsContentUtils::GetAltText(nsAString& text) {
  if (!sAltText) InitializeModifierStrings();
728
729
730
  text.Assign(*sAltText);
}

731
732
void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
  if (!sModifierSeparator) InitializeModifierStrings();
733
734
735
  text.Assign(*sModifierSeparator);
}

736
737
void nsContentUtils::InitializeModifierStrings() {
  // load the display strings for the keyboard accelerators
738
  nsCOMPtr<nsIStringBundleService> bundleService =
739
      mozilla::services::GetStringBundleService();
740
  nsCOMPtr<nsIStringBundle> bundle;
741
  DebugOnly<nsresult> rv = NS_OK;
742
  if (bundleService) {
743
744
745
    rv = bundleService->CreateBundle(
        "chrome://global-platform/locale/platformKeys.properties",
        getter_AddRefs(bundle));
746
  }
747

748
749
750
  NS_ASSERTION(
      NS_SUCCEEDED(rv) && bundle,
      "chrome://global/locale/platformKeys.properties could not be loaded");
751
752
753
754
755
756
  nsAutoString shiftModifier;
  nsAutoString metaModifier;
  nsAutoString osModifier;
  nsAutoString altModifier;
  nsAutoString controlModifier;
  nsAutoString modifierSeparator;
757
  if (bundle) {
758
759
    // macs use symbols for each modifier key, so fetch each from the bundle,
    // which also covers i18n
760
761
762
763
764
765
    bundle->GetStringFromName("VK_SHIFT", shiftModifier);
    bundle->GetStringFromName("VK_META", metaModifier);
    bundle->GetStringFromName("VK_WIN", osModifier);
    bundle->GetStringFromName("VK_ALT", altModifier);
    bundle->GetStringFromName("VK_CONTROL", controlModifier);
    bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
766
  }
767
  // if any of these don't exist, we get  an empty string
768
769
  sShiftText = new nsString(shiftModifier);
  sMetaText = new nsString(metaModifier);
770
  sOSText = new nsString(osModifier);
771
772
  sAltText = new nsString(altModifier);
  sControlText = new nsString(controlModifier);
773
  sModifierSeparator = new nsString(modifierSeparator);
774
775
}

776
777
mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
    EventMessage aEventMessage) {
778
  switch (aEventMessage) {
779
#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
780
781
  case message_:                                          \
    return struct_;
782
#include "mozilla/EventNameList.h"
783
#undef MESSAGE_TO_EVENT
784
785
786
    default:
      MOZ_ASSERT_UNREACHABLE("Invalid event message?");
      return eBasicEventClass;
787
  }
788
789
}

790
static nsAtom* GetEventTypeFromMessage(EventMessage aEventMessage) {
791
792
  switch (aEventMessage) {
#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
793
794
  case message_:                                          \
    return nsGkAtoms::on##name_;
795
796
#include "mozilla/EventNameList.h"
#undef MESSAGE_TO_EVENT
797
798
    default:
      return nullptr;
799
800
801
802
803
  }
}

// Because of SVG/SMIL we have several atoms mapped to the same
// id, but we can rely on MESSAGE_TO_EVENT to map id to only one atom.
804
static bool ShouldAddEventToStringEventTable(const EventNameMapping& aMapping) {
805
806
  MOZ_ASSERT(aMapping.mAtom);
  return GetEventTypeFromMessage(aMapping.mMessage) == aMapping.mAtom;
807
808
}

809
bool nsContentUtils::InitializeEventTable() {
810
811
812
813
  NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
  NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");

  static const EventNameMapping eventArray[] = {
814
815
#define EVENT(name_, _message, _type, _class) \
  {nsGkAtoms::on##name_, _type, _message, _class, false},
816
#define WINDOW_ONLY_EVENT EVENT
817
#define DOCUMENT_ONLY_EVENT EVENT
818
#define NON_IDL_EVENT EVENT
819
#include "mozilla/EventNameList.h"
820
#undef WINDOW_ONLY_EVENT
821
#undef NON_IDL_EVENT
822
#undef EVENT
Sylvestre Ledru's avatar