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/. */
7 #include "ChromeUtils.h"
9 #include "JSOracleParent.h"
10 #include "js/CallAndConstruct.h" // JS::Call
11 #include "js/ColumnNumber.h" // JS::TaggedColumnNumberOneOrigin, JS::ColumnNumberOneOrigin
12 #include "js/CharacterEncoding.h"
13 #include "js/Date.h" // JS::IsISOStyleDate
14 #include "js/Object.h" // JS::GetClass
15 #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_DefinePropertyById, JS_Enumerate, JS_GetProperty, JS_GetPropertyById, JS_SetProperty, JS_SetPropertyById, JS::IdVector
16 #include "js/PropertyDescriptor.h" // JS::PropertyDescriptor, JS_GetOwnPropertyDescriptorById
17 #include "js/SavedFrameAPI.h"
18 #include "js/Value.h" // JS::Value, JS::StringValue
19 #include "jsfriendapi.h"
20 #include "WrapperFactory.h"
22 #include "mozilla/Base64.h"
23 #include "mozilla/CycleCollectedJSRuntime.h"
24 #include "mozilla/ErrorNames.h"
25 #include "mozilla/EventStateManager.h"
26 #include "mozilla/FormAutofillNative.h"
27 #include "mozilla/IntentionalCrash.h"
28 #include "mozilla/PerfStats.h"
29 #include "mozilla/Preferences.h"
30 #include "mozilla/ProcInfo.h"
31 #include "mozilla/ResultExtensions.h"
32 #include "mozilla/ScopeExit.h"
33 #include "mozilla/ScrollingMetrics.h"
34 #include "mozilla/SharedStyleSheetCache.h"
35 #include "mozilla/SpinEventLoopUntil.h"
36 #include "mozilla/TimeStamp.h"
37 #include "mozilla/dom/ContentParent.h"
38 #include "mozilla/dom/IdleDeadline.h"
39 #include "mozilla/dom/InProcessParent.h"
40 #include "mozilla/dom/JSActorService.h"
41 #include "mozilla/dom/MediaSessionBinding.h"
42 #include "mozilla/dom/PBrowserParent.h"
43 #include "mozilla/dom/Performance.h"
44 #include "mozilla/dom/PopupBlocker.h"
45 #include "mozilla/dom/Promise.h"
46 #include "mozilla/dom/Record.h"
47 #include "mozilla/dom/ReportingHeader.h"
48 #include "mozilla/dom/UnionTypes.h"
49 #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
50 #include "mozilla/dom/WindowGlobalParent.h"
51 #include "mozilla/dom/WorkerScope.h"
52 #include "mozilla/ipc/GeckoChildProcessHost.h"
53 #include "mozilla/ipc/UtilityProcessSandboxing.h"
54 #include "mozilla/ipc/UtilityProcessManager.h"
55 #include "mozilla/ipc/UtilityProcessHost.h"
56 #include "mozilla/net/UrlClassifierFeatureFactory.h"
57 #include "mozilla/RemoteDecoderManagerChild.h"
58 #include "mozilla/KeySystemConfig.h"
59 #include "mozilla/WheelHandlingHelper.h"
60 #include "IOActivityMonitor.h"
61 #include "nsNativeTheme.h"
62 #include "nsThreadUtils.h"
63 #include "mozJSModuleLoader.h"
64 #include "mozilla/ProfilerLabels.h"
65 #include "mozilla/ProfilerMarkers.h"
66 #include "nsDocShell.h"
67 #include "nsIException.h"
68 #include "VsyncSource.h"
75 # include <sys/wait.h>
78 # include <sys/prctl.h>
83 # include "mozilla/MFCDMParent.h"
86 namespace mozilla::dom
{
89 void ChromeUtils::NondeterministicGetWeakMapKeys(
90 GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aMap
,
91 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aRv
) {
92 if (!aMap
.isObject()) {
93 aRetval
.setUndefined();
95 JSContext
* cx
= aGlobal
.Context();
96 JS::Rooted
<JSObject
*> objRet(cx
);
97 JS::Rooted
<JSObject
*> mapObj(cx
, &aMap
.toObject());
98 if (!JS_NondeterministicGetWeakMapKeys(cx
, mapObj
, &objRet
)) {
99 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
101 aRetval
.set(objRet
? JS::ObjectValue(*objRet
) : JS::UndefinedValue());
107 void ChromeUtils::NondeterministicGetWeakSetKeys(
108 GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aSet
,
109 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aRv
) {
110 if (!aSet
.isObject()) {
111 aRetval
.setUndefined();
113 JSContext
* cx
= aGlobal
.Context();
114 JS::Rooted
<JSObject
*> objRet(cx
);
115 JS::Rooted
<JSObject
*> setObj(cx
, &aSet
.toObject());
116 if (!JS_NondeterministicGetWeakSetKeys(cx
, setObj
, &objRet
)) {
117 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
119 aRetval
.set(objRet
? JS::ObjectValue(*objRet
) : JS::UndefinedValue());
125 void ChromeUtils::Base64URLEncode(GlobalObject
& aGlobal
,
126 const ArrayBufferViewOrArrayBuffer
& aSource
,
127 const Base64URLEncodeOptions
& aOptions
,
128 nsACString
& aResult
, ErrorResult
& aRv
) {
129 auto paddingPolicy
= aOptions
.mPad
? Base64URLEncodePaddingPolicy::Include
130 : Base64URLEncodePaddingPolicy::Omit
;
132 aSource
, [&](const Span
<uint8_t>& aData
, JS::AutoCheckCannotGC
&&) {
133 nsresult rv
= mozilla::Base64URLEncode(aData
.Length(), aData
.Elements(),
134 paddingPolicy
, aResult
);
135 if (NS_WARN_IF(NS_FAILED(rv
))) {
143 void ChromeUtils::Base64URLDecode(GlobalObject
& aGlobal
,
144 const nsACString
& aString
,
145 const Base64URLDecodeOptions
& aOptions
,
146 JS::MutableHandle
<JSObject
*> aRetval
,
148 Base64URLDecodePaddingPolicy paddingPolicy
;
149 switch (aOptions
.mPadding
) {
150 case Base64URLDecodePadding::Require
:
151 paddingPolicy
= Base64URLDecodePaddingPolicy::Require
;
154 case Base64URLDecodePadding::Ignore
:
155 paddingPolicy
= Base64URLDecodePaddingPolicy::Ignore
;
158 case Base64URLDecodePadding::Reject
:
159 paddingPolicy
= Base64URLDecodePaddingPolicy::Reject
;
163 aRv
.Throw(NS_ERROR_INVALID_ARG
);
166 FallibleTArray
<uint8_t> data
;
167 nsresult rv
= mozilla::Base64URLDecode(aString
, paddingPolicy
, data
);
168 if (NS_WARN_IF(NS_FAILED(rv
))) {
173 JS::Rooted
<JSObject
*> buffer(
174 aGlobal
.Context(), ArrayBuffer::Create(aGlobal
.Context(), data
, aRv
));
182 void ChromeUtils::ReleaseAssert(GlobalObject
& aGlobal
, bool aCondition
,
183 const nsAString
& aMessage
) {
184 // If the condition didn't fail, which is the likely case, immediately return.
185 if (MOZ_LIKELY(aCondition
)) {
189 // Extract the current stack from the JS runtime to embed in the crash reason.
190 nsAutoString filename
;
193 if (nsCOMPtr
<nsIStackFrame
> location
= GetCurrentJSStack(1)) {
194 location
->GetFilename(aGlobal
.Context(), filename
);
195 lineNo
= location
->GetLineNumber(aGlobal
.Context());
197 filename
.Assign(u
"<unknown>"_ns
);
200 // Convert to utf-8 for adding as the MozCrashReason.
201 NS_ConvertUTF16toUTF8
filenameUtf8(filename
);
202 NS_ConvertUTF16toUTF8
messageUtf8(aMessage
);
205 MOZ_CRASH_UNSAFE_PRINTF("Failed ChromeUtils.releaseAssert(\"%s\") @ %s:%u",
206 messageUtf8
.get(), filenameUtf8
.get(), lineNo
);
210 void ChromeUtils::AddProfilerMarker(
211 GlobalObject
& aGlobal
, const nsACString
& aName
,
212 const ProfilerMarkerOptionsOrDouble
& aOptions
,
213 const Optional
<nsACString
>& aText
) {
214 if (!profiler_thread_is_being_profiled_for_markers()) {
218 MarkerOptions options
;
220 MarkerCategory category
= ::geckoprofiler::category::JS
;
222 DOMHighResTimeStamp startTime
= 0;
223 uint64_t innerWindowId
= 0;
224 if (aOptions
.IsDouble()) {
225 startTime
= aOptions
.GetAsDouble();
227 const ProfilerMarkerOptions
& opt
= aOptions
.GetAsProfilerMarkerOptions();
228 startTime
= opt
.mStartTime
;
229 innerWindowId
= opt
.mInnerWindowId
;
231 if (opt
.mCaptureStack
) {
232 // If we will be capturing a stack, change the category of the
233 // ChromeUtils.addProfilerMarker label automatically added by the webidl
234 // binding from DOM to PROFILER so that this function doesn't appear in
236 JSContext
* cx
= aGlobal
.Context();
237 ProfilingStack
* stack
= js::GetContextProfilingStackIfEnabled(cx
);
238 if (MOZ_LIKELY(stack
)) {
239 uint32_t sp
= stack
->stackPointer
;
240 if (MOZ_LIKELY(sp
> 0)) {
241 js::ProfilingStackFrame
& frame
= stack
->frames
[sp
- 1];
242 if (frame
.isLabelFrame() && "ChromeUtils"_ns
.Equals(frame
.label()) &&
243 "addProfilerMarker"_ns
.Equals(frame
.dynamicString())) {
244 frame
.setLabelCategory(JS::ProfilingCategoryPair::PROFILER
);
249 options
.Set(MarkerStack::Capture());
251 #define BEGIN_CATEGORY(name, labelAsString, color) \
252 if (opt.mCategory.Equals(labelAsString)) { \
253 category = ::geckoprofiler::category::name; \
255 #define SUBCATEGORY(supercategory, name, labelAsString)
257 MOZ_PROFILING_CATEGORY_LIST(BEGIN_CATEGORY
, SUBCATEGORY
, END_CATEGORY
)
258 #undef BEGIN_CATEGORY
262 category
= ::geckoprofiler::category::OTHER
;
266 RefPtr
<Performance
> performance
;
268 if (NS_IsMainThread()) {
269 nsCOMPtr
<nsPIDOMWindowInner
> ownerWindow
=
270 do_QueryInterface(aGlobal
.GetAsSupports());
272 performance
= ownerWindow
->GetPerformance();
275 JSContext
* cx
= aGlobal
.Context();
276 WorkerPrivate
* workerPrivate
= GetWorkerPrivateFromContext(cx
);
278 performance
= workerPrivate
->GlobalScope()->GetPerformance();
283 options
.Set(MarkerTiming::IntervalUntilNowFrom(
284 performance
->CreationTimeStamp() +
285 TimeDuration::FromMilliseconds(startTime
)));
287 options
.Set(MarkerTiming::IntervalUntilNowFrom(
288 TimeStamp::ProcessCreation() +
289 TimeDuration::FromMilliseconds(startTime
)));
294 options
.Set(MarkerInnerWindowId(innerWindowId
));
296 options
.Set(MarkerInnerWindowIdFromJSContext(aGlobal
.Context()));
300 AUTO_PROFILER_STATS(ChromeUtils_AddProfilerMarker
);
301 if (aText
.WasPassed()) {
302 profiler_add_marker(aName
, category
, std::move(options
),
303 ::geckoprofiler::markers::TextMarker
{},
306 profiler_add_marker(aName
, category
, std::move(options
));
312 void ChromeUtils::GetXPCOMErrorName(GlobalObject
& aGlobal
, uint32_t aErrorCode
,
313 nsACString
& aRetval
) {
314 GetErrorName((nsresult
)aErrorCode
, aRetval
);
318 void ChromeUtils::WaiveXrays(GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aVal
,
319 JS::MutableHandle
<JS::Value
> aRetval
,
321 JS::Rooted
<JS::Value
> value(aGlobal
.Context(), aVal
);
322 if (!xpc::WrapperFactory::WaiveXrayAndWrap(aGlobal
.Context(), &value
)) {
323 aRv
.NoteJSContextException(aGlobal
.Context());
330 void ChromeUtils::UnwaiveXrays(GlobalObject
& aGlobal
,
331 JS::Handle
<JS::Value
> aVal
,
332 JS::MutableHandle
<JS::Value
> aRetval
,
334 if (!aVal
.isObject()) {
339 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(),
340 js::UncheckedUnwrap(&aVal
.toObject()));
341 if (!JS_WrapObject(aGlobal
.Context(), &obj
)) {
342 aRv
.NoteJSContextException(aGlobal
.Context());
344 aRetval
.setObject(*obj
);
349 void ChromeUtils::GetClassName(GlobalObject
& aGlobal
,
350 JS::Handle
<JSObject
*> aObj
, bool aUnwrap
,
351 nsAString
& aRetval
) {
352 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(), aObj
);
354 obj
= js::UncheckedUnwrap(obj
, /* stopAtWindowProxy = */ false);
357 aRetval
= NS_ConvertUTF8toUTF16(nsDependentCString(JS::GetClass(obj
)->name
));
361 bool ChromeUtils::IsDOMObject(GlobalObject
& aGlobal
, JS::Handle
<JSObject
*> aObj
,
363 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(), aObj
);
365 obj
= js::UncheckedUnwrap(obj
, /* stopAtWindowProxy = */ false);
368 return mozilla::dom::IsDOMObject(obj
);
372 bool ChromeUtils::IsISOStyleDate(GlobalObject
& aGlobal
,
373 const nsACString
& aStr
) {
374 // aStr is a UTF-8 string, however we can cast to JS::Latin1Chars
375 // because JS::IsISOStyleDate handles ASCII only
376 return JS::IsISOStyleDate(aGlobal
.Context(),
377 JS::Latin1Chars(aStr
.Data(), aStr
.Length()));
381 void ChromeUtils::ShallowClone(GlobalObject
& aGlobal
,
382 JS::Handle
<JSObject
*> aObj
,
383 JS::Handle
<JSObject
*> aTarget
,
384 JS::MutableHandle
<JSObject
*> aRetval
,
386 JSContext
* cx
= aGlobal
.Context();
388 auto cleanup
= MakeScopeExit([&]() { aRv
.NoteJSContextException(cx
); });
390 JS::Rooted
<JS::IdVector
> ids(cx
, JS::IdVector(cx
));
391 JS::RootedVector
<JS::Value
> values(cx
);
392 JS::RootedVector
<jsid
> valuesIds(cx
);
395 // cx represents our current Realm, so it makes sense to use it for the
396 // CheckedUnwrapDynamic call. We do want CheckedUnwrapDynamic, in case
397 // someone is shallow-cloning a Window.
398 JS::Rooted
<JSObject
*> obj(cx
, js::CheckedUnwrapDynamic(aObj
, cx
));
400 js::ReportAccessDenied(cx
);
404 if (js::IsScriptedProxy(obj
)) {
405 JS_ReportErrorASCII(cx
, "Shallow cloning a proxy object is not allowed");
409 JSAutoRealm
ar(cx
, obj
);
411 if (!JS_Enumerate(cx
, obj
, &ids
) || !values
.reserve(ids
.length()) ||
412 !valuesIds
.reserve(ids
.length())) {
416 JS::Rooted
<Maybe
<JS::PropertyDescriptor
>> desc(cx
);
417 JS::Rooted
<JS::PropertyKey
> id(cx
);
418 for (jsid idVal
: ids
) {
420 if (!JS_GetOwnPropertyDescriptorById(cx
, obj
, id
, &desc
)) {
423 if (desc
.isNothing() || desc
->isAccessorDescriptor()) {
426 valuesIds
.infallibleAppend(id
);
427 values
.infallibleAppend(desc
->value());
431 JS::Rooted
<JSObject
*> obj(cx
);
433 Maybe
<JSAutoRealm
> ar
;
435 // Our target could be anything, so we want CheckedUnwrapDynamic here.
436 // "cx" represents the current Realm when we were called from bindings, so
437 // we can just use that.
438 JS::Rooted
<JSObject
*> target(cx
, js::CheckedUnwrapDynamic(aTarget
, cx
));
440 js::ReportAccessDenied(cx
);
443 ar
.emplace(cx
, target
);
446 obj
= JS_NewPlainObject(cx
);
451 JS::Rooted
<JS::Value
> value(cx
);
452 JS::Rooted
<JS::PropertyKey
> id(cx
);
453 for (uint32_t i
= 0; i
< valuesIds
.length(); i
++) {
457 JS_MarkCrossZoneId(cx
, id
);
458 if (!JS_WrapValue(cx
, &value
) ||
459 !JS_SetPropertyById(cx
, obj
, id
, value
)) {
465 if (aTarget
&& !JS_WrapObject(cx
, &obj
)) {
474 class IdleDispatchRunnable final
: public IdleRunnable
,
475 public nsITimerCallback
{
477 NS_DECL_ISUPPORTS_INHERITED
479 IdleDispatchRunnable(nsIGlobalObject
* aParent
, IdleRequestCallback
& aCallback
)
480 : IdleRunnable("ChromeUtils::IdleDispatch"),
481 mCallback(&aCallback
),
484 // MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT.
486 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
Run() override
{
490 auto deadline
= mDeadline
- TimeStamp::ProcessCreation();
493 RefPtr
<IdleDeadline
> idleDeadline
=
494 new IdleDeadline(mParent
, mTimedOut
, deadline
.ToMilliseconds());
496 RefPtr
<IdleRequestCallback
> callback(std::move(mCallback
));
497 MOZ_ASSERT(!mCallback
);
498 callback
->Call(*idleDeadline
, "ChromeUtils::IdleDispatch handler");
504 void SetDeadline(TimeStamp aDeadline
) override
{ mDeadline
= aDeadline
; }
506 NS_IMETHOD
Notify(nsITimer
* aTimer
) override
{
508 SetDeadline(TimeStamp::Now());
512 void SetTimer(uint32_t aDelay
, nsIEventTarget
* aTarget
) override
{
515 NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, aDelay
,
516 nsITimer::TYPE_ONE_SHOT
, aTarget
);
520 virtual ~IdleDispatchRunnable() { CancelTimer(); }
530 RefPtr
<IdleRequestCallback
> mCallback
;
531 nsCOMPtr
<nsIGlobalObject
> mParent
;
533 nsCOMPtr
<nsITimer
> mTimer
;
535 TimeStamp mDeadline
{};
536 bool mTimedOut
= false;
539 NS_IMPL_ISUPPORTS_INHERITED(IdleDispatchRunnable
, IdleRunnable
,
541 } // anonymous namespace
544 void ChromeUtils::IdleDispatch(const GlobalObject
& aGlobal
,
545 IdleRequestCallback
& aCallback
,
546 const IdleRequestOptions
& aOptions
,
548 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
551 auto runnable
= MakeRefPtr
<IdleDispatchRunnable
>(global
, aCallback
);
553 if (aOptions
.mTimeout
.WasPassed()) {
554 aRv
= NS_DispatchToCurrentThreadQueue(
555 runnable
.forget(), aOptions
.mTimeout
.Value(), EventQueuePriority::Idle
);
557 aRv
= NS_DispatchToCurrentThreadQueue(runnable
.forget(),
558 EventQueuePriority::Idle
);
563 void ChromeUtils::Import(const GlobalObject
& aGlobal
,
564 const nsACString
& aResourceURI
,
565 const Optional
<JS::Handle
<JSObject
*>>& aTargetObj
,
566 JS::MutableHandle
<JSObject
*> aRetval
,
568 RefPtr moduleloader
= mozJSModuleLoader::Get();
569 MOZ_ASSERT(moduleloader
);
571 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE("ChromeUtils::Import",
572 OTHER
, aResourceURI
);
574 JSContext
* cx
= aGlobal
.Context();
576 JS::Rooted
<JSObject
*> global(cx
);
577 JS::Rooted
<JSObject
*> exports(cx
);
578 nsresult rv
= moduleloader
->Import(cx
, aResourceURI
, &global
, &exports
);
584 // Import() on the component loader can return NS_OK while leaving an
585 // exception on the JSContext. Check for that case.
586 if (JS_IsExceptionPending(cx
)) {
587 aRv
.NoteJSContextException(cx
);
591 if (aTargetObj
.WasPassed()) {
592 if (!JS_AssignObject(cx
, aTargetObj
.Value(), exports
)) {
593 aRv
.Throw(NS_ERROR_FAILURE
);
598 if (!JS_WrapObject(cx
, &exports
)) {
599 aRv
.Throw(NS_ERROR_FAILURE
);
602 aRetval
.set(exports
);
605 static mozJSModuleLoader
* GetModuleLoaderForCurrentGlobal(
606 JSContext
* aCx
, const GlobalObject
& aGlobal
,
607 Maybe
<loader::NonSharedGlobalSyncModuleLoaderScope
>&
608 aMaybeSyncLoaderScope
) {
609 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
611 if (mozJSModuleLoader::IsSharedSystemGlobal(global
)) {
612 return mozJSModuleLoader::Get();
614 if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global
)) {
615 return mozJSModuleLoader::GetOrCreateDevToolsLoader(aCx
);
618 if (loader::NonSharedGlobalSyncModuleLoaderScope::IsActive()) {
619 mozJSModuleLoader
* moduleloader
=
620 loader::NonSharedGlobalSyncModuleLoaderScope::ActiveLoader();
622 if (!moduleloader
->IsLoaderGlobal(global
->GetGlobalJSObject())) {
623 JS_ReportErrorASCII(aCx
,
624 "global: \"current\" option cannot be used for "
625 "different global while other importESModule "
626 "with global: \"current\" is on the stack");
633 RefPtr targetModuleLoader
= global
->GetModuleLoader(aCx
);
634 if (!targetModuleLoader
) {
635 // Sandbox without associated window returns nullptr for GetModuleLoader.
636 JS_ReportErrorASCII(aCx
, "No ModuleLoader found for the current context");
640 if (targetModuleLoader
->HasFetchingModules()) {
641 if (!NS_IsMainThread()) {
642 JS_ReportErrorASCII(aCx
,
643 "ChromeUtils.importESModule cannot be used in worker "
644 "when there is ongoing dynamic import");
648 if (!mozilla::SpinEventLoopUntil(
649 "importESModule for current global"_ns
, [&]() -> bool {
650 return !targetModuleLoader
->HasFetchingModules();
652 JS_ReportErrorASCII(aCx
, "Failed to wait for ongoing module requests");
657 aMaybeSyncLoaderScope
.emplace(aCx
, global
);
658 return aMaybeSyncLoaderScope
->ActiveLoader();
661 static mozJSModuleLoader
* GetModuleLoaderForOptions(
662 JSContext
* aCx
, const GlobalObject
& aGlobal
,
663 const ImportESModuleOptionsDictionary
& aOptions
,
664 Maybe
<loader::NonSharedGlobalSyncModuleLoaderScope
>&
665 aMaybeSyncLoaderScope
) {
666 if (!aOptions
.mGlobal
.WasPassed()) {
667 return mozJSModuleLoader::Get();
670 switch (aOptions
.mGlobal
.Value()) {
671 case ImportESModuleTargetGlobal::Shared
:
672 return mozJSModuleLoader::Get();
674 case ImportESModuleTargetGlobal::Devtools
:
675 return mozJSModuleLoader::GetOrCreateDevToolsLoader(aCx
);
677 case ImportESModuleTargetGlobal::Contextual
: {
678 if (!NS_IsMainThread()) {
679 return GetModuleLoaderForCurrentGlobal(aCx
, aGlobal
,
680 aMaybeSyncLoaderScope
);
683 RefPtr devToolsModuleloader
= mozJSModuleLoader::GetDevToolsLoader();
684 if (devToolsModuleloader
&&
685 devToolsModuleloader
->IsLoaderGlobal(aGlobal
.Get())) {
686 return mozJSModuleLoader::GetOrCreateDevToolsLoader(aCx
);
688 return mozJSModuleLoader::Get();
691 case ImportESModuleTargetGlobal::Current
:
692 return GetModuleLoaderForCurrentGlobal(aCx
, aGlobal
,
693 aMaybeSyncLoaderScope
);
696 MOZ_CRASH("Unknown ImportESModuleTargetGlobal");
700 static bool ValidateImportOptions(
701 JSContext
* aCx
, const GlobalObject
& aGlobal
,
702 const ImportESModuleOptionsDictionary
& aOptions
) {
703 if (!NS_IsMainThread() &&
704 (!aOptions
.mGlobal
.WasPassed() ||
705 (aOptions
.mGlobal
.Value() != ImportESModuleTargetGlobal::Current
&&
706 aOptions
.mGlobal
.Value() != ImportESModuleTargetGlobal::Contextual
))) {
707 JS_ReportErrorASCII(aCx
,
708 "ChromeUtils.importESModule: Only { global: "
709 "\"current\" } and { global: \"contextual\" } options "
710 "are supported on worker");
714 if (NS_IsMainThread()) {
715 nsCOMPtr
<nsIGlobalObject
> global
=
716 do_QueryInterface(aGlobal
.GetAsSupports());
718 if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global
) &&
719 !aOptions
.mGlobal
.WasPassed()) {
720 JS_ReportErrorASCII(aCx
,
721 "ChromeUtils.importESModule: global option is "
722 "required in DevTools distinct global");
731 void ChromeUtils::ImportESModule(
732 const GlobalObject
& aGlobal
, const nsAString
& aResourceURI
,
733 const ImportESModuleOptionsDictionary
& aOptions
,
734 JS::MutableHandle
<JSObject
*> aRetval
, ErrorResult
& aRv
) {
735 JSContext
* cx
= aGlobal
.Context();
737 if (!ValidateImportOptions(cx
, aGlobal
, aOptions
)) {
738 aRv
.Throw(NS_ERROR_FAILURE
);
742 Maybe
<loader::NonSharedGlobalSyncModuleLoaderScope
> maybeSyncLoaderScope
;
743 RefPtr
<mozJSModuleLoader
> moduleloader
=
744 GetModuleLoaderForOptions(cx
, aGlobal
, aOptions
, maybeSyncLoaderScope
);
746 aRv
.Throw(NS_ERROR_FAILURE
);
750 NS_ConvertUTF16toUTF8
registryLocation(aResourceURI
);
752 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE(
753 "ChromeUtils::ImportESModule", OTHER
, registryLocation
);
755 JS::Rooted
<JSObject
*> moduleNamespace(cx
);
757 moduleloader
->ImportESModule(cx
, registryLocation
, &moduleNamespace
);
763 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
765 if (!JS_WrapObject(cx
, &moduleNamespace
)) {
766 aRv
.Throw(NS_ERROR_FAILURE
);
769 aRetval
.set(moduleNamespace
);
771 if (maybeSyncLoaderScope
) {
772 maybeSyncLoaderScope
->Finish();
776 // An integer encoding for ImportESModuleOptionsDictionary, to pass the value
777 // to the lazy getters.
778 class EncodedOptions
{
780 explicit EncodedOptions(const ImportESModuleOptionsDictionary
& aOptions
) {
781 if (aOptions
.mGlobal
.WasPassed()) {
782 mValue
= uint32_t(aOptions
.mGlobal
.Value()) + 1;
788 explicit EncodedOptions(uint32_t aValue
) : mValue(aValue
) {}
790 int32_t toInt32() const { return int32_t(mValue
); }
792 void DecodeInto(ImportESModuleOptionsDictionary
& aOptions
) {
794 aOptions
.mGlobal
.Reset();
796 aOptions
.mGlobal
.Construct(ImportESModuleTargetGlobal(mValue
- 1));
804 namespace lazy_getter
{
806 // The property id of the getter.
807 // Used by all lazy getters.
808 static const size_t SLOT_ID
= 0;
810 // The URI of the module to import.
811 // Used by ChromeUtils.defineModuleGetter and ChromeUtils.defineESModuleGetters.
812 static const size_t SLOT_URI
= 1;
814 // An array object that contians values for PARAM_INDEX_TARGET and
815 // PARAM_INDEX_LAMBDA.
816 // Used by ChromeUtils.defineLazyGetter.
817 static const size_t SLOT_PARAMS
= 1;
819 // The EncodedOptions value.
820 // Used by ChromeUtils.defineESModuleGetters.
821 static const size_t SLOT_OPTIONS
= 2;
823 static const size_t PARAM_INDEX_TARGET
= 0;
824 static const size_t PARAM_INDEX_LAMBDA
= 1;
825 static const size_t PARAMS_COUNT
= 2;
827 static bool ExtractArgs(JSContext
* aCx
, JS::CallArgs
& aArgs
,
828 JS::MutableHandle
<JSObject
*> aCallee
,
829 JS::MutableHandle
<JSObject
*> aThisObj
,
830 JS::MutableHandle
<jsid
> aId
) {
831 aCallee
.set(&aArgs
.callee());
833 JS::Handle
<JS::Value
> thisv
= aArgs
.thisv();
834 if (!thisv
.isObject()) {
835 JS_ReportErrorASCII(aCx
, "Invalid target object");
839 aThisObj
.set(&thisv
.toObject());
841 JS::Rooted
<JS::Value
> id(aCx
,
842 js::GetFunctionNativeReserved(aCallee
, SLOT_ID
));
843 MOZ_ALWAYS_TRUE(JS_ValueToId(aCx
, id
, aId
));
847 static bool JSLazyGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
848 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
850 JS::Rooted
<JSObject
*> callee(aCx
);
851 JS::Rooted
<JSObject
*> unused(aCx
);
852 JS::Rooted
<jsid
> id(aCx
);
853 if (!ExtractArgs(aCx
, args
, &callee
, &unused
, &id
)) {
857 JS::Rooted
<JS::Value
> paramsVal(
858 aCx
, js::GetFunctionNativeReserved(callee
, SLOT_PARAMS
));
859 if (paramsVal
.isUndefined()) {
860 args
.rval().setUndefined();
863 // Avoid calling the lambda multiple times, in case of:
864 // * the getter function is retrieved from property descriptor and called
865 // * the lambda gets the property again
866 // * the getter function throws and accessed again
867 js::SetFunctionNativeReserved(callee
, SLOT_PARAMS
, JS::UndefinedHandleValue
);
869 JS::Rooted
<JSObject
*> paramsObj(aCx
, ¶msVal
.toObject());
871 JS::Rooted
<JS::Value
> targetVal(aCx
);
872 JS::Rooted
<JS::Value
> lambdaVal(aCx
);
873 if (!JS_GetElement(aCx
, paramsObj
, PARAM_INDEX_TARGET
, &targetVal
)) {
876 if (!JS_GetElement(aCx
, paramsObj
, PARAM_INDEX_LAMBDA
, &lambdaVal
)) {
880 JS::Rooted
<JSObject
*> targetObj(aCx
, &targetVal
.toObject());
882 JS::Rooted
<JS::Value
> value(aCx
);
883 if (!JS::Call(aCx
, targetObj
, lambdaVal
, JS::HandleValueArray::empty(),
888 if (!JS_DefinePropertyById(aCx
, targetObj
, id
, value
, JSPROP_ENUMERATE
)) {
892 args
.rval().set(value
);
896 static bool DefineLazyGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
897 JS::Handle
<JS::Value
> aName
,
898 JS::Handle
<JSObject
*> aLambda
) {
899 JS::Rooted
<jsid
> id(aCx
);
900 if (!JS_ValueToId(aCx
, aName
, &id
)) {
904 JS::Rooted
<JSObject
*> getter(
905 aCx
, JS_GetFunctionObject(
906 js::NewFunctionByIdWithReserved(aCx
, JSLazyGetter
, 0, 0, id
)));
908 JS_ReportOutOfMemory(aCx
);
912 JS::RootedVector
<JS::Value
> params(aCx
);
913 if (!params
.resize(PARAMS_COUNT
)) {
916 params
[PARAM_INDEX_TARGET
].setObject(*aTarget
);
917 params
[PARAM_INDEX_LAMBDA
].setObject(*aLambda
);
918 JS::Rooted
<JSObject
*> paramsObj(aCx
, JS::NewArrayObject(aCx
, params
));
923 js::SetFunctionNativeReserved(getter
, SLOT_ID
, aName
);
924 js::SetFunctionNativeReserved(getter
, SLOT_PARAMS
,
925 JS::ObjectValue(*paramsObj
));
927 return JS_DefinePropertyById(aCx
, aTarget
, id
, getter
, nullptr,
931 enum class ModuleType
{ JSM
, ESM
};
933 static bool ModuleGetterImpl(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
,
935 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
937 JS::Rooted
<JSObject
*> callee(aCx
);
938 JS::Rooted
<JSObject
*> thisObj(aCx
);
939 JS::Rooted
<jsid
> id(aCx
);
940 if (!ExtractArgs(aCx
, args
, &callee
, &thisObj
, &id
)) {
944 JS::Rooted
<JSString
*> moduleURI(
945 aCx
, js::GetFunctionNativeReserved(callee
, SLOT_URI
).toString());
946 JS::UniqueChars bytes
= JS_EncodeStringToUTF8(aCx
, moduleURI
);
950 nsDependentCString
uri(bytes
.get());
952 JS::Rooted
<JS::Value
> value(aCx
);
953 if (aType
== ModuleType::JSM
) {
954 RefPtr moduleloader
= mozJSModuleLoader::Get();
955 MOZ_ASSERT(moduleloader
);
957 JS::Rooted
<JSObject
*> moduleGlobal(aCx
);
958 JS::Rooted
<JSObject
*> moduleExports(aCx
);
959 nsresult rv
= moduleloader
->Import(aCx
, uri
, &moduleGlobal
, &moduleExports
);
965 // JSM's exports is from the same realm.
966 if (!JS_GetPropertyById(aCx
, moduleExports
, id
, &value
)) {
970 EncodedOptions
encodedOptions(
971 js::GetFunctionNativeReserved(callee
, SLOT_OPTIONS
).toInt32());
973 ImportESModuleOptionsDictionary options
;
974 encodedOptions
.DecodeInto(options
);
976 GlobalObject
global(aCx
, callee
);
978 Maybe
<loader::NonSharedGlobalSyncModuleLoaderScope
> maybeSyncLoaderScope
;
979 RefPtr
<mozJSModuleLoader
> moduleloader
=
980 GetModuleLoaderForOptions(aCx
, global
, options
, maybeSyncLoaderScope
);
985 JS::Rooted
<JSObject
*> moduleNamespace(aCx
);
986 nsresult rv
= moduleloader
->ImportESModule(aCx
, uri
, &moduleNamespace
);
992 // ESM's namespace is from the module's realm.
994 JSAutoRealm
ar(aCx
, moduleNamespace
);
995 if (!JS_GetPropertyById(aCx
, moduleNamespace
, id
, &value
)) {
999 if (!JS_WrapValue(aCx
, &value
)) {
1003 if (maybeSyncLoaderScope
) {
1004 maybeSyncLoaderScope
->Finish();
1008 if (!JS_DefinePropertyById(aCx
, thisObj
, id
, value
, JSPROP_ENUMERATE
)) {
1012 args
.rval().set(value
);
1016 static bool JSModuleGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
1017 return ModuleGetterImpl(aCx
, aArgc
, aVp
, ModuleType::JSM
);
1020 static bool ESModuleGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
1021 return ModuleGetterImpl(aCx
, aArgc
, aVp
, ModuleType::ESM
);
1024 static bool ModuleSetterImpl(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
1025 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
1027 JS::Rooted
<JSObject
*> callee(aCx
);
1028 JS::Rooted
<JSObject
*> thisObj(aCx
);
1029 JS::Rooted
<jsid
> id(aCx
);
1030 if (!ExtractArgs(aCx
, args
, &callee
, &thisObj
, &id
)) {
1034 return JS_DefinePropertyById(aCx
, thisObj
, id
, args
.get(0), JSPROP_ENUMERATE
);
1037 static bool JSModuleSetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
1038 return ModuleSetterImpl(aCx
, aArgc
, aVp
);
1041 static bool ESModuleSetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
1042 return ModuleSetterImpl(aCx
, aArgc
, aVp
);
1045 static bool DefineJSModuleGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
1046 const nsAString
& aId
,
1047 const nsAString
& aResourceURI
) {
1048 JS::Rooted
<JS::Value
> uri(aCx
);
1049 JS::Rooted
<JS::Value
> idValue(aCx
);
1050 JS::Rooted
<jsid
> id(aCx
);
1051 if (!xpc::NonVoidStringToJsval(aCx
, aResourceURI
, &uri
) ||
1052 !xpc::NonVoidStringToJsval(aCx
, aId
, &idValue
) ||
1053 !JS_ValueToId(aCx
, idValue
, &id
)) {
1056 idValue
= js::IdToValue(id
);
1058 JS::Rooted
<JSObject
*> getter(
1059 aCx
, JS_GetFunctionObject(
1060 js::NewFunctionByIdWithReserved(aCx
, JSModuleGetter
, 0, 0, id
)));
1062 JS::Rooted
<JSObject
*> setter(
1063 aCx
, JS_GetFunctionObject(
1064 js::NewFunctionByIdWithReserved(aCx
, JSModuleSetter
, 0, 0, id
)));
1066 if (!getter
|| !setter
) {
1067 JS_ReportOutOfMemory(aCx
);
1071 js::SetFunctionNativeReserved(getter
, SLOT_ID
, idValue
);
1072 js::SetFunctionNativeReserved(setter
, SLOT_ID
, idValue
);
1074 js::SetFunctionNativeReserved(getter
, SLOT_URI
, uri
);
1076 return JS_DefinePropertyById(aCx
, aTarget
, id
, getter
, setter
,
1080 static bool DefineESModuleGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
1081 JS::Handle
<JS::PropertyKey
> aId
,
1082 JS::Handle
<JS::Value
> aResourceURI
,
1083 const EncodedOptions
& encodedOptions
) {
1084 JS::Rooted
<JS::Value
> idVal(aCx
, JS::StringValue(aId
.toString()));
1086 JS::Rooted
<JS::Value
> optionsVal(aCx
,
1087 JS::Int32Value(encodedOptions
.toInt32()));
1089 JS::Rooted
<JSObject
*> getter(
1090 aCx
, JS_GetFunctionObject(js::NewFunctionByIdWithReserved(
1091 aCx
, ESModuleGetter
, 0, 0, aId
)));
1093 JS::Rooted
<JSObject
*> setter(
1094 aCx
, JS_GetFunctionObject(js::NewFunctionByIdWithReserved(
1095 aCx
, ESModuleSetter
, 0, 0, aId
)));
1097 if (!getter
|| !setter
) {
1098 JS_ReportOutOfMemory(aCx
);
1102 js::SetFunctionNativeReserved(getter
, SLOT_ID
, idVal
);
1103 js::SetFunctionNativeReserved(setter
, SLOT_ID
, idVal
);
1105 js::SetFunctionNativeReserved(getter
, SLOT_URI
, aResourceURI
);
1107 js::SetFunctionNativeReserved(getter
, SLOT_OPTIONS
, optionsVal
);
1109 return JS_DefinePropertyById(aCx
, aTarget
, aId
, getter
, setter
,
1113 } // namespace lazy_getter
1116 void ChromeUtils::DefineLazyGetter(const GlobalObject
& aGlobal
,
1117 JS::Handle
<JSObject
*> aTarget
,
1118 JS::Handle
<JS::Value
> aName
,
1119 JS::Handle
<JSObject
*> aLambda
,
1121 JSContext
* cx
= aGlobal
.Context();
1122 if (!lazy_getter::DefineLazyGetter(cx
, aTarget
, aName
, aLambda
)) {
1123 aRv
.NoteJSContextException(cx
);
1129 void ChromeUtils::DefineModuleGetter(const GlobalObject
& global
,
1130 JS::Handle
<JSObject
*> target
,
1131 const nsAString
& id
,
1132 const nsAString
& resourceURI
,
1134 if (!lazy_getter::DefineJSModuleGetter(global
.Context(), target
, id
,
1136 aRv
.NoteJSContextException(global
.Context());
1141 void ChromeUtils::DefineESModuleGetters(
1142 const GlobalObject
& global
, JS::Handle
<JSObject
*> target
,
1143 JS::Handle
<JSObject
*> modules
,
1144 const ImportESModuleOptionsDictionary
& aOptions
, ErrorResult
& aRv
) {
1145 JSContext
* cx
= global
.Context();
1147 JS::Rooted
<JS::IdVector
> props(cx
, JS::IdVector(cx
));
1148 if (!JS_Enumerate(cx
, modules
, &props
)) {
1149 aRv
.NoteJSContextException(cx
);
1153 if (!ValidateImportOptions(cx
, global
, aOptions
)) {
1154 aRv
.Throw(NS_ERROR_FAILURE
);
1158 EncodedOptions
encodedOptions(aOptions
);
1160 JS::Rooted
<JS::PropertyKey
> prop(cx
);
1161 JS::Rooted
<JS::Value
> resourceURIVal(cx
);
1162 for (JS::PropertyKey tmp
: props
) {
1165 if (!prop
.isString()) {
1166 aRv
.Throw(NS_ERROR_FAILURE
);
1170 if (!JS_GetPropertyById(cx
, modules
, prop
, &resourceURIVal
)) {
1171 aRv
.NoteJSContextException(cx
);
1175 if (!lazy_getter::DefineESModuleGetter(cx
, target
, prop
, resourceURIVal
,
1177 aRv
.NoteJSContextException(cx
);
1185 void ChromeUtils::GetLibcConstants(const GlobalObject
&,
1186 LibcConstants
& aConsts
) {
1187 aConsts
.mEINTR
.Construct(EINTR
);
1188 aConsts
.mEACCES
.Construct(EACCES
);
1189 aConsts
.mEAGAIN
.Construct(EAGAIN
);
1190 aConsts
.mEINVAL
.Construct(EINVAL
);
1191 aConsts
.mENOSYS
.Construct(ENOSYS
);
1193 aConsts
.mF_SETFD
.Construct(F_SETFD
);
1194 aConsts
.mF_SETFL
.Construct(F_SETFL
);
1196 aConsts
.mFD_CLOEXEC
.Construct(FD_CLOEXEC
);
1198 aConsts
.mAT_EACCESS
.Construct(AT_EACCESS
);
1200 aConsts
.mO_CREAT
.Construct(O_CREAT
);
1201 aConsts
.mO_NONBLOCK
.Construct(O_NONBLOCK
);
1202 aConsts
.mO_WRONLY
.Construct(O_WRONLY
);
1204 aConsts
.mPOLLERR
.Construct(POLLERR
);
1205 aConsts
.mPOLLHUP
.Construct(POLLHUP
);
1206 aConsts
.mPOLLIN
.Construct(POLLIN
);
1207 aConsts
.mPOLLNVAL
.Construct(POLLNVAL
);
1208 aConsts
.mPOLLOUT
.Construct(POLLOUT
);
1210 aConsts
.mWNOHANG
.Construct(WNOHANG
);
1213 aConsts
.mPR_CAPBSET_READ
.Construct(PR_CAPBSET_READ
);
1219 void ChromeUtils::OriginAttributesToSuffix(
1220 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1224 OriginAttributes
attrs(aAttrs
);
1225 attrs
.CreateSuffix(aSuffix
);
1229 bool ChromeUtils::OriginAttributesMatchPattern(
1230 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1231 const dom::OriginAttributesPatternDictionary
& aPattern
) {
1232 OriginAttributes
attrs(aAttrs
);
1233 OriginAttributesPattern
pattern(aPattern
);
1234 return pattern
.Matches(attrs
);
1238 void ChromeUtils::CreateOriginAttributesFromOrigin(
1239 dom::GlobalObject
& aGlobal
, const nsAString
& aOrigin
,
1240 dom::OriginAttributesDictionary
& aAttrs
, ErrorResult
& aRv
) {
1241 OriginAttributes attrs
;
1242 nsAutoCString suffix
;
1243 if (!attrs
.PopulateFromOrigin(NS_ConvertUTF16toUTF8(aOrigin
), suffix
)) {
1244 aRv
.Throw(NS_ERROR_FAILURE
);
1251 void ChromeUtils::CreateOriginAttributesFromOriginSuffix(
1252 dom::GlobalObject
& aGlobal
, const nsAString
& aSuffix
,
1253 dom::OriginAttributesDictionary
& aAttrs
, ErrorResult
& aRv
) {
1254 OriginAttributes attrs
;
1255 nsAutoCString suffix
;
1256 if (!attrs
.PopulateFromSuffix(NS_ConvertUTF16toUTF8(aSuffix
))) {
1257 aRv
.Throw(NS_ERROR_FAILURE
);
1264 void ChromeUtils::FillNonDefaultOriginAttributes(
1265 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1266 dom::OriginAttributesDictionary
& aNewAttrs
) {
1271 bool ChromeUtils::IsOriginAttributesEqual(
1272 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aA
,
1273 const dom::OriginAttributesDictionary
& aB
) {
1274 return IsOriginAttributesEqual(aA
, aB
);
1278 bool ChromeUtils::IsOriginAttributesEqual(
1279 const dom::OriginAttributesDictionary
& aA
,
1280 const dom::OriginAttributesDictionary
& aB
) {
1285 void ChromeUtils::GetBaseDomainFromPartitionKey(dom::GlobalObject
& aGlobal
,
1286 const nsAString
& aPartitionKey
,
1287 nsAString
& aBaseDomain
,
1290 nsString pkBaseDomain
;
1294 if (!mozilla::OriginAttributes::ParsePartitionKey(
1295 aPartitionKey
, scheme
, pkBaseDomain
, port
, ancestor
)) {
1296 aRv
.Throw(NS_ERROR_FAILURE
);
1300 aBaseDomain
= pkBaseDomain
;
1304 void ChromeUtils::GetPartitionKeyFromURL(dom::GlobalObject
& aGlobal
,
1305 const nsAString
& aURL
,
1306 nsAString
& aPartitionKey
,
1308 nsCOMPtr
<nsIURI
> uri
;
1309 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURL
);
1310 if (NS_SUCCEEDED(rv
) && uri
->SchemeIs("chrome")) {
1311 rv
= NS_ERROR_FAILURE
;
1314 if (NS_WARN_IF(NS_FAILED(rv
))) {
1315 aPartitionKey
.Truncate();
1320 mozilla::OriginAttributes attrs
;
1321 // For now, uses assume the partition key is cross-site.
1322 // We will need to not make this assumption to allow access
1323 // to same-site partitioned cookies in the cookie extension API.
1324 attrs
.SetPartitionKey(uri
, false);
1326 aPartitionKey
= attrs
.mPartitionKey
;
1329 #ifdef NIGHTLY_BUILD
1331 void ChromeUtils::GetRecentJSDevError(GlobalObject
& aGlobal
,
1332 JS::MutableHandle
<JS::Value
> aRetval
,
1334 aRetval
.setUndefined();
1335 auto runtime
= CycleCollectedJSRuntime::Get();
1336 MOZ_ASSERT(runtime
);
1338 auto cx
= aGlobal
.Context();
1339 if (!runtime
->GetRecentDevError(cx
, aRetval
)) {
1340 aRv
.NoteJSContextException(cx
);
1346 void ChromeUtils::ClearRecentJSDevError(GlobalObject
&) {
1347 auto runtime
= CycleCollectedJSRuntime::Get();
1348 MOZ_ASSERT(runtime
);
1350 runtime
->ClearRecentDevError();
1352 #endif // NIGHTLY_BUILD
1354 void ChromeUtils::ClearStyleSheetCacheByPrincipal(GlobalObject
&,
1355 nsIPrincipal
* aForPrincipal
) {
1356 SharedStyleSheetCache::Clear(aForPrincipal
);
1359 void ChromeUtils::ClearStyleSheetCacheByBaseDomain(
1360 GlobalObject
&, const nsACString
& aBaseDomain
) {
1361 SharedStyleSheetCache::Clear(nullptr, &aBaseDomain
);
1364 void ChromeUtils::ClearStyleSheetCache(GlobalObject
&) {
1365 SharedStyleSheetCache::Clear();
1368 #define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \
1369 case mozilla::ProcType::_procType: \
1370 return WebIDLProcType::_webidl
1372 static WebIDLProcType
ProcTypeToWebIDL(mozilla::ProcType aType
) {
1373 // Max is the value of the last enum, not the length, so add one.
1375 static_cast<size_t>(MaxContiguousEnumValue
<WebIDLProcType
>::value
) ==
1376 static_cast<size_t>(ProcType::Max
),
1377 "In order for this static cast to be okay, "
1378 "WebIDLProcType must match ProcType exactly");
1380 // These must match the similar ones in E10SUtils.sys.mjs, RemoteTypes.h,
1381 // ProcInfo.h and ChromeUtils.webidl
1383 PROCTYPE_TO_WEBIDL_CASE(Web
, Web
);
1384 PROCTYPE_TO_WEBIDL_CASE(WebIsolated
, WebIsolated
);
1385 PROCTYPE_TO_WEBIDL_CASE(File
, File
);
1386 PROCTYPE_TO_WEBIDL_CASE(Extension
, Extension
);
1387 PROCTYPE_TO_WEBIDL_CASE(PrivilegedAbout
, Privilegedabout
);
1388 PROCTYPE_TO_WEBIDL_CASE(PrivilegedMozilla
, Privilegedmozilla
);
1389 PROCTYPE_TO_WEBIDL_CASE(WebCOOPCOEP
, WithCoopCoep
);
1390 PROCTYPE_TO_WEBIDL_CASE(WebServiceWorker
, WebServiceWorker
);
1392 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1393 process_bin_type, procinfo_typename, \
1394 webidl_typename, allcaps_name) \
1395 PROCTYPE_TO_WEBIDL_CASE(procinfo_typename, webidl_typename);
1396 #define SKIP_PROCESS_TYPE_CONTENT
1397 #ifndef MOZ_ENABLE_FORKSERVER
1398 # define SKIP_PROCESS_TYPE_FORKSERVER
1399 #endif // MOZ_ENABLE_FORKSERVER
1400 #include "mozilla/GeckoProcessTypes.h"
1401 #undef SKIP_PROCESS_TYPE_CONTENT
1402 #ifndef MOZ_ENABLE_FORKSERVER
1403 # undef SKIP_PROCESS_TYPE_FORKSERVER
1404 #endif // MOZ_ENABLE_FORKSERVER
1405 #undef GECKO_PROCESS_TYPE
1407 PROCTYPE_TO_WEBIDL_CASE(Preallocated
, Preallocated
);
1408 PROCTYPE_TO_WEBIDL_CASE(Unknown
, Unknown
);
1411 MOZ_ASSERT(false, "Unhandled case in ProcTypeToWebIDL");
1412 return WebIDLProcType::Unknown
;
1415 #undef PROCTYPE_TO_WEBIDL_CASE
1418 already_AddRefed
<Promise
> ChromeUtils::RequestProcInfo(GlobalObject
& aGlobal
,
1420 // This function will use IPDL to enable threads info on macOS
1421 // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023
1422 if (!XRE_IsParentProcess()) {
1423 aRv
.Throw(NS_ERROR_FAILURE
);
1426 // Prepare the JS promise that will hold our response.
1427 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1429 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
1430 if (NS_WARN_IF(aRv
.Failed())) {
1433 MOZ_ASSERT(domPromise
);
1435 // Get a list of processes to examine and pre-fill them with available info.
1436 // Note that this is subject to race conditions: just because we have a
1437 // process in the list doesn't mean that the process will still be alive when
1438 // we attempt to get its information. Followup code MUST be able to fail
1439 // gracefully on some processes and still return whichever information is
1442 // Get all the content parents.
1443 // Note that this array includes even the long dead content parents, so we
1444 // might have some garbage, especially with Fission.
1445 // SAFETY NOTE: `contentParents` is only valid if used synchronously.
1446 // Anything else and you may end up dealing with dangling pointers.
1447 nsTArray
<ContentParent
*> contentParents
;
1448 ContentParent::GetAll(contentParents
);
1450 // Prepare our background request.
1451 // We reserve one more slot for the browser process itself.
1452 nsTArray
<ProcInfoRequest
> requests(contentParents
.Length() + 1);
1453 // Requesting process info for the browser process itself.
1454 requests
.EmplaceBack(
1455 /* aPid = */ base::GetCurrentProcId(),
1456 /* aProcessType = */ ProcType::Browser
,
1457 /* aOrigin = */ ""_ns
,
1458 /* aWindowInfo = */ nsTArray
<WindowInfo
>(),
1459 /* aUtilityInfo = */ nsTArray
<UtilityInfo
>());
1461 // First handle non-ContentParent processes.
1462 mozilla::ipc::GeckoChildProcessHost::GetAll(
1463 [&requests
](mozilla::ipc::GeckoChildProcessHost
* aGeckoProcess
) {
1464 base::ProcessId childPid
= aGeckoProcess
->GetChildProcessId();
1465 if (childPid
== 0) {
1466 // Something went wrong with this process, it may be dead already,
1470 mozilla::ProcType type
= mozilla::ProcType::Unknown
;
1472 switch (aGeckoProcess
->GetProcessType()) {
1473 case GeckoProcessType::GeckoProcessType_Content
: {
1474 // These processes are handled separately.
1478 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1479 process_bin_type, procinfo_typename, \
1480 webidl_typename, allcaps_name) \
1481 case GeckoProcessType::GeckoProcessType_##enum_name: { \
1482 type = mozilla::ProcType::procinfo_typename; \
1485 #define SKIP_PROCESS_TYPE_CONTENT
1486 #ifndef MOZ_ENABLE_FORKSERVER
1487 # define SKIP_PROCESS_TYPE_FORKSERVER
1488 #endif // MOZ_ENABLE_FORKSERVER
1489 #include "mozilla/GeckoProcessTypes.h"
1490 #ifndef MOZ_ENABLE_FORKSERVER
1491 # undef SKIP_PROCESS_TYPE_FORKSERVER
1492 #endif // MOZ_ENABLE_FORKSERVER
1493 #undef SKIP_PROCESS_TYPE_CONTENT
1494 #undef GECKO_PROCESS_TYPE
1496 // Leave the default Unknown value in |type|.
1500 // Attach utility actor information to the process.
1501 nsTArray
<UtilityInfo
> utilityActors
;
1502 if (aGeckoProcess
->GetProcessType() ==
1503 GeckoProcessType::GeckoProcessType_Utility
) {
1504 RefPtr
<mozilla::ipc::UtilityProcessManager
> upm
=
1505 mozilla::ipc::UtilityProcessManager::GetSingleton();
1506 if (!utilityActors
.AppendElements(upm
->GetActors(aGeckoProcess
),
1508 NS_WARNING("Error adding actors");
1513 requests
.EmplaceBack(
1514 /* aPid = */ childPid
,
1515 /* aProcessType = */ type
,
1516 /* aOrigin = */ ""_ns
,
1517 /* aWindowInfo = */ nsTArray
<WindowInfo
>(), // Without a
1518 // ContentProcess, no
1520 /* aUtilityInfo = */ std::move(utilityActors
),
1521 /* aChild = */ 0 // Without a ContentProcess, no ChildId.
1524 /* aChildTask = */ aGeckoProcess
->GetChildTask()
1529 // Now handle ContentParents.
1530 for (const auto* contentParent
: contentParents
) {
1531 if (!contentParent
|| !contentParent
->Process()) {
1532 // Presumably, the process is dead or dying.
1535 base::ProcessId pid
= contentParent
->Process()->GetChildProcessId();
1537 // Presumably, the process is dead or dying.
1540 if (contentParent
->Process()->GetProcessType() !=
1541 GeckoProcessType::GeckoProcessType_Content
) {
1542 // We're probably racing against a process changing type.
1543 // We'll get it in the next call, skip it for the moment.
1547 // Since this code is executed synchronously on the main thread,
1548 // processes cannot die while we're in this loop.
1549 mozilla::ProcType type
= mozilla::ProcType::Unknown
;
1551 // Convert the remoteType into a ProcType.
1552 // Ideally, the remoteType should be strongly typed
1553 // upstream, this would make the conversion less brittle.
1554 const nsAutoCString
remoteType(contentParent
->GetRemoteType());
1555 if (StringBeginsWith(remoteType
, FISSION_WEB_REMOTE_TYPE
)) {
1556 // WARNING: Do not change the order, as
1557 // `DEFAULT_REMOTE_TYPE` is a prefix of
1558 // `FISSION_WEB_REMOTE_TYPE`.
1559 type
= mozilla::ProcType::WebIsolated
;
1560 } else if (StringBeginsWith(remoteType
, SERVICEWORKER_REMOTE_TYPE
)) {
1561 type
= mozilla::ProcType::WebServiceWorker
;
1562 } else if (StringBeginsWith(remoteType
,
1563 WITH_COOP_COEP_REMOTE_TYPE_PREFIX
)) {
1564 type
= mozilla::ProcType::WebCOOPCOEP
;
1565 } else if (remoteType
== FILE_REMOTE_TYPE
) {
1566 type
= mozilla::ProcType::File
;
1567 } else if (remoteType
== EXTENSION_REMOTE_TYPE
) {
1568 type
= mozilla::ProcType::Extension
;
1569 } else if (remoteType
== PRIVILEGEDABOUT_REMOTE_TYPE
) {
1570 type
= mozilla::ProcType::PrivilegedAbout
;
1571 } else if (remoteType
== PRIVILEGEDMOZILLA_REMOTE_TYPE
) {
1572 type
= mozilla::ProcType::PrivilegedMozilla
;
1573 } else if (remoteType
== PREALLOC_REMOTE_TYPE
) {
1574 type
= mozilla::ProcType::Preallocated
;
1575 } else if (StringBeginsWith(remoteType
, DEFAULT_REMOTE_TYPE
)) {
1576 type
= mozilla::ProcType::Web
;
1578 MOZ_CRASH_UNSAFE_PRINTF("Unknown remoteType '%s'", remoteType
.get());
1581 // By convention, everything after '=' is the origin.
1582 nsAutoCString origin
;
1583 nsACString::const_iterator cursor
;
1584 nsACString::const_iterator end
;
1585 remoteType
.BeginReading(cursor
);
1586 remoteType
.EndReading(end
);
1587 if (FindCharInReadable('=', cursor
, end
)) {
1588 origin
= Substring(++cursor
, end
);
1591 // Attach DOM window information to the process.
1592 nsTArray
<WindowInfo
> windows
;
1593 for (const auto& browserParentWrapperKey
:
1594 contentParent
->ManagedPBrowserParent()) {
1595 for (const auto& windowGlobalParentWrapperKey
:
1596 browserParentWrapperKey
->ManagedPWindowGlobalParent()) {
1597 // WindowGlobalParent is the only immediate subclass of
1598 // PWindowGlobalParent.
1599 auto* windowGlobalParent
=
1600 static_cast<WindowGlobalParent
*>(windowGlobalParentWrapperKey
);
1602 nsString documentTitle
;
1603 windowGlobalParent
->GetDocumentTitle(documentTitle
);
1604 WindowInfo
* window
= windows
.EmplaceBack(
1606 /* aOuterWindowId = */ windowGlobalParent
->OuterWindowId(),
1607 /* aDocumentURI = */ windowGlobalParent
->GetDocumentURI(),
1608 /* aDocumentTitle = */ std::move(documentTitle
),
1609 /* aIsProcessRoot = */ windowGlobalParent
->IsProcessRoot(),
1610 /* aIsInProcess = */ windowGlobalParent
->IsInProcess());
1612 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
1617 requests
.EmplaceBack(
1619 /* aProcessType = */ type
,
1620 /* aOrigin = */ origin
,
1621 /* aWindowInfo = */ std::move(windows
),
1622 /* aUtilityInfo = */ nsTArray
<UtilityInfo
>(),
1623 /* aChild = */ contentParent
->ChildID()
1626 /* aChildTask = */ contentParent
->Process()->GetChildTask()
1631 // Now place background request.
1632 RefPtr
<nsISerialEventTarget
> target
= global
->SerialEventTarget();
1633 mozilla::GetProcInfo(std::move(requests
))
1637 domPromise
](const HashMap
<base::ProcessId
, ProcInfo
>& aSysProcInfo
) {
1638 ParentProcInfoDictionary parentInfo
;
1639 if (aSysProcInfo
.count() == 0) {
1640 // For some reason, we couldn't get *any* info.
1641 // Maybe a sandboxing issue?
1642 domPromise
->MaybeReject(NS_ERROR_UNEXPECTED
);
1645 nsTArray
<ChildProcInfoDictionary
> childrenInfo(
1646 aSysProcInfo
.count() - 1);
1647 for (auto iter
= aSysProcInfo
.iter(); !iter
.done(); iter
.next()) {
1648 const auto& sysProcInfo
= iter
.get().value();
1650 if (sysProcInfo
.type
== ProcType::Browser
) {
1651 rv
= mozilla::CopySysProcInfoToDOM(sysProcInfo
, &parentInfo
);
1652 if (NS_FAILED(rv
)) {
1653 // Failing to copy? That's probably not something from we can
1654 // (or should) try to recover gracefully.
1655 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1658 MOZ_ASSERT(sysProcInfo
.childId
== 0);
1659 MOZ_ASSERT(sysProcInfo
.origin
.IsEmpty());
1661 mozilla::dom::ChildProcInfoDictionary
* childInfo
=
1662 childrenInfo
.AppendElement(fallible
);
1664 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1667 rv
= mozilla::CopySysProcInfoToDOM(sysProcInfo
, childInfo
);
1668 if (NS_FAILED(rv
)) {
1669 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1672 // Copy Firefox info.
1673 childInfo
->mChildID
= sysProcInfo
.childId
;
1674 childInfo
->mOrigin
= sysProcInfo
.origin
;
1675 childInfo
->mType
= ProcTypeToWebIDL(sysProcInfo
.type
);
1677 for (const auto& source
: sysProcInfo
.windows
) {
1678 auto* dest
= childInfo
->mWindows
.AppendElement(fallible
);
1680 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1683 dest
->mOuterWindowId
= source
.outerWindowId
;
1684 dest
->mDocumentURI
= source
.documentURI
;
1685 dest
->mDocumentTitle
= source
.documentTitle
;
1686 dest
->mIsProcessRoot
= source
.isProcessRoot
;
1687 dest
->mIsInProcess
= source
.isInProcess
;
1690 if (sysProcInfo
.type
== ProcType::Utility
) {
1691 for (const auto& source
: sysProcInfo
.utilityActors
) {
1693 childInfo
->mUtilityActors
.AppendElement(fallible
);
1695 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1699 dest
->mActorName
= source
.actorName
;
1705 // Attach the children to the parent.
1706 mozilla::dom::Sequence
<mozilla::dom::ChildProcInfoDictionary
>
1707 children(std::move(childrenInfo
));
1708 parentInfo
.mChildren
= std::move(children
);
1709 domPromise
->MaybeResolve(parentInfo
);
1711 [domPromise
](nsresult aRv
) { domPromise
->MaybeReject(aRv
); });
1712 MOZ_ASSERT(domPromise
);
1714 // sending back the promise instance
1715 return domPromise
.forget();
1719 bool ChromeUtils::VsyncEnabled(GlobalObject
& aGlobal
) {
1720 return mozilla::gfx::VsyncSource::GetFastestVsyncRate().isSome();
1723 void ChromeUtils::SetPerfStatsCollectionMask(GlobalObject
& aGlobal
,
1725 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask
>(aMask
));
1728 already_AddRefed
<Promise
> ChromeUtils::CollectPerfStats(GlobalObject
& aGlobal
,
1730 // Creating a JS promise
1731 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1734 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
1739 RefPtr
<PerfStats::PerfStatsPromise
> extPromise
=
1740 PerfStats::CollectPerfStatsJSON();
1743 GetCurrentSerialEventTarget(), __func__
,
1744 [promise
](const nsCString
& aResult
) {
1745 promise
->MaybeResolve(NS_ConvertUTF8toUTF16(aResult
));
1747 [promise
](bool aValue
) { promise
->MaybeReject(NS_ERROR_FAILURE
); });
1749 return promise
.forget();
1752 constexpr auto kSkipSelfHosted
= JS::SavedFrameSelfHosted::Exclude
;
1755 void ChromeUtils::GetCallerLocation(const GlobalObject
& aGlobal
,
1756 nsIPrincipal
* aPrincipal
,
1757 JS::MutableHandle
<JSObject
*> aRetval
) {
1758 JSContext
* cx
= aGlobal
.Context();
1760 auto* principals
= nsJSPrincipals::get(aPrincipal
);
1762 JS::StackCapture
captureMode(JS::FirstSubsumedFrame(cx
, principals
));
1764 JS::Rooted
<JSObject
*> frame(cx
);
1765 if (!JS::CaptureCurrentStack(cx
, &frame
, std::move(captureMode
))) {
1766 JS_ClearPendingException(cx
);
1767 aRetval
.set(nullptr);
1771 // FirstSubsumedFrame gets us a stack which stops at the first principal which
1772 // is subsumed by the given principal. That means that we may have a lot of
1773 // privileged frames that we don't care about at the top of the stack, though.
1774 // We need to filter those out to get the frame we actually want.
1776 js::GetFirstSubsumedSavedFrame(cx
, principals
, frame
, kSkipSelfHosted
));
1780 void ChromeUtils::CreateError(const GlobalObject
& aGlobal
,
1781 const nsAString
& aMessage
,
1782 JS::Handle
<JSObject
*> aStack
,
1783 JS::MutableHandle
<JSObject
*> aRetVal
,
1785 if (aStack
&& !JS::IsMaybeWrappedSavedFrame(aStack
)) {
1786 aRv
.Throw(NS_ERROR_INVALID_ARG
);
1790 JSContext
* cx
= aGlobal
.Context();
1792 auto cleanup
= MakeScopeExit([&]() { aRv
.NoteJSContextException(cx
); });
1794 JS::Rooted
<JSObject
*> retVal(cx
);
1796 JS::Rooted
<JSString
*> fileName(cx
, JS_GetEmptyString(cx
));
1798 JS::TaggedColumnNumberOneOrigin column
;
1800 Maybe
<JSAutoRealm
> ar
;
1801 JS::Rooted
<JSObject
*> stack(cx
);
1803 stack
= UncheckedUnwrap(aStack
);
1804 ar
.emplace(cx
, stack
);
1806 JSPrincipals
* principals
=
1807 JS::GetRealmPrincipals(js::GetContextRealm(cx
));
1808 if (JS::GetSavedFrameLine(cx
, principals
, stack
, &line
) !=
1809 JS::SavedFrameResult::Ok
||
1810 JS::GetSavedFrameColumn(cx
, principals
, stack
, &column
) !=
1811 JS::SavedFrameResult::Ok
||
1812 JS::GetSavedFrameSource(cx
, principals
, stack
, &fileName
) !=
1813 JS::SavedFrameResult::Ok
) {
1818 JS::Rooted
<JSString
*> message(cx
);
1820 JS::Rooted
<JS::Value
> msgVal(cx
);
1821 if (!xpc::NonVoidStringToJsval(cx
, aMessage
, &msgVal
)) {
1824 message
= msgVal
.toString();
1827 JS::Rooted
<JS::Value
> err(cx
);
1828 if (!JS::CreateError(cx
, JSEXN_ERR
, stack
, fileName
, line
,
1829 JS::ColumnNumberOneOrigin(column
.oneOriginValue()),
1830 nullptr, message
, JS::NothingHandleValue
, &err
)) {
1834 MOZ_ASSERT(err
.isObject());
1835 retVal
= &err
.toObject();
1838 if (aStack
&& !JS_WrapObject(cx
, &retVal
)) {
1843 aRetVal
.set(retVal
);
1847 already_AddRefed
<Promise
> ChromeUtils::RequestIOActivity(GlobalObject
& aGlobal
,
1849 MOZ_ASSERT(XRE_IsParentProcess());
1850 MOZ_ASSERT(Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF
, false));
1851 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1853 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
1854 if (NS_WARN_IF(aRv
.Failed())) {
1857 MOZ_ASSERT(domPromise
);
1858 mozilla::net::IOActivityMonitor::RequestActivities(domPromise
);
1859 return domPromise
.forget();
1863 bool ChromeUtils::HasReportingHeaderForOrigin(GlobalObject
& global
,
1864 const nsAString
& aOrigin
,
1866 if (!XRE_IsParentProcess()) {
1867 aRv
.Throw(NS_ERROR_FAILURE
);
1871 return ReportingHeader::HasReportingHeaderForOrigin(
1872 NS_ConvertUTF16toUTF8(aOrigin
));
1876 PopupBlockerState
ChromeUtils::GetPopupControlState(GlobalObject
& aGlobal
) {
1877 switch (PopupBlocker::GetPopupControlState()) {
1878 case PopupBlocker::PopupControlState::openAllowed
:
1879 return PopupBlockerState::OpenAllowed
;
1881 case PopupBlocker::PopupControlState::openControlled
:
1882 return PopupBlockerState::OpenControlled
;
1884 case PopupBlocker::PopupControlState::openBlocked
:
1885 return PopupBlockerState::OpenBlocked
;
1887 case PopupBlocker::PopupControlState::openAbused
:
1888 return PopupBlockerState::OpenAbused
;
1890 case PopupBlocker::PopupControlState::openOverridden
:
1891 return PopupBlockerState::OpenOverridden
;
1895 "PopupBlocker::PopupControlState and PopupBlockerState are out of "
1901 double ChromeUtils::LastExternalProtocolIframeAllowed(GlobalObject
& aGlobal
) {
1902 TimeStamp when
= PopupBlocker::WhenLastExternalProtocolIframeAllowed();
1903 if (when
.IsNull()) {
1907 TimeDuration duration
= TimeStamp::Now() - when
;
1908 return duration
.ToMilliseconds();
1912 void ChromeUtils::ResetLastExternalProtocolIframeAllowed(
1913 GlobalObject
& aGlobal
) {
1914 PopupBlocker::ResetLastExternalProtocolIframeAllowed();
1918 void ChromeUtils::EndWheelTransaction(GlobalObject
& aGlobal
) {
1919 // This allows us to end the current wheel transaction from the browser
1920 // chrome. We do not need to perform any checks before calling
1921 // EndTransaction(), as it should do nothing in the case that there is
1922 // no current wheel transaction.
1923 WheelTransaction::EndTransaction();
1927 void ChromeUtils::RegisterWindowActor(const GlobalObject
& aGlobal
,
1928 const nsACString
& aName
,
1929 const WindowActorOptions
& aOptions
,
1931 MOZ_ASSERT(XRE_IsParentProcess());
1933 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1934 service
->RegisterWindowActor(aName
, aOptions
, aRv
);
1938 void ChromeUtils::UnregisterWindowActor(const GlobalObject
& aGlobal
,
1939 const nsACString
& aName
) {
1940 MOZ_ASSERT(XRE_IsParentProcess());
1942 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1943 service
->UnregisterWindowActor(aName
);
1947 void ChromeUtils::RegisterProcessActor(const GlobalObject
& aGlobal
,
1948 const nsACString
& aName
,
1949 const ProcessActorOptions
& aOptions
,
1951 MOZ_ASSERT(XRE_IsParentProcess());
1953 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1954 service
->RegisterProcessActor(aName
, aOptions
, aRv
);
1958 void ChromeUtils::UnregisterProcessActor(const GlobalObject
& aGlobal
,
1959 const nsACString
& aName
) {
1960 MOZ_ASSERT(XRE_IsParentProcess());
1962 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1963 service
->UnregisterProcessActor(aName
);
1967 bool ChromeUtils::IsClassifierBlockingErrorCode(GlobalObject
& aGlobal
,
1969 return net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
1970 static_cast<nsresult
>(aError
));
1974 void ChromeUtils::PrivateNoteIntentionalCrash(const GlobalObject
& aGlobal
,
1975 ErrorResult
& aError
) {
1976 if (XRE_IsContentProcess()) {
1977 NoteIntentionalCrash("tab");
1980 aError
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
1984 nsIDOMProcessChild
* ChromeUtils::GetDomProcessChild(const GlobalObject
&) {
1985 return nsIDOMProcessChild::GetSingleton();
1989 void ChromeUtils::GetAllDOMProcesses(
1990 GlobalObject
& aGlobal
, nsTArray
<RefPtr
<nsIDOMProcessParent
>>& aParents
,
1992 if (!XRE_IsParentProcess()) {
1993 aRv
.ThrowNotAllowedError(
1994 "getAllDOMProcesses() may only be called in the parent process");
1998 // Always add the parent process nsIDOMProcessParent first
1999 aParents
.AppendElement(InProcessParent::Singleton());
2001 // Before adding nsIDOMProcessParent for all the content processes
2002 for (auto* cp
: ContentParent::AllProcesses(ContentParent::eLive
)) {
2003 aParents
.AppendElement(cp
);
2008 void ChromeUtils::ConsumeInteractionData(
2009 GlobalObject
& aGlobal
, Record
<nsString
, InteractionData
>& aInteractions
,
2011 if (!XRE_IsParentProcess()) {
2012 aRv
.ThrowNotAllowedError(
2013 "consumeInteractionData() may only be called in the parent "
2017 EventStateManager::ConsumeInteractionData(aInteractions
);
2020 already_AddRefed
<Promise
> ChromeUtils::CollectScrollingData(
2021 GlobalObject
& aGlobal
, ErrorResult
& aRv
) {
2022 // Creating a JS promise
2023 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
2026 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
2031 RefPtr
<ScrollingMetrics::ScrollingMetricsPromise
> extPromise
=
2032 ScrollingMetrics::CollectScrollingMetrics();
2035 GetCurrentSerialEventTarget(), __func__
,
2036 [promise
](const std::tuple
<uint32_t, uint32_t>& aResult
) {
2037 InteractionData out
= {};
2038 out
.mInteractionTimeInMilliseconds
= std::get
<0>(aResult
);
2039 out
.mScrollingDistanceInPixels
= std::get
<1>(aResult
);
2040 promise
->MaybeResolve(out
);
2042 [promise
](bool aValue
) { promise
->MaybeReject(NS_ERROR_FAILURE
); });
2044 return promise
.forget();
2048 void ChromeUtils::GetFormAutofillConfidences(
2049 GlobalObject
& aGlobal
, const Sequence
<OwningNonNull
<Element
>>& aElements
,
2050 nsTArray
<FormAutofillConfidences
>& aResults
, ErrorResult
& aRv
) {
2051 FormAutofillNative::GetFormAutofillConfidences(aGlobal
, aElements
, aResults
,
2055 bool ChromeUtils::IsDarkBackground(GlobalObject
&, Element
& aElement
) {
2056 nsIFrame
* f
= aElement
.GetPrimaryFrame(FlushType::Frames
);
2060 return nsNativeTheme::IsDarkBackground(f
);
2063 double ChromeUtils::DateNow(GlobalObject
&) { return JS_Now() / 1000.0; }
2066 void ChromeUtils::EnsureJSOracleStarted(GlobalObject
&) {
2067 if (StaticPrefs::browser_opaqueResponseBlocking_javascriptValidator()) {
2068 JSOracleParent::WithJSOracle([](JSOracleParent
* aParent
) {});
2073 unsigned ChromeUtils::AliveUtilityProcesses(const GlobalObject
&) {
2074 const auto& utilityProcessManager
=
2075 mozilla::ipc::UtilityProcessManager::GetIfExists();
2076 return utilityProcessManager
? utilityProcessManager
->AliveProcesses() : 0;
2080 void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject
& aGlobal
,
2081 nsTArray
<nsCString
>& aNames
) {
2083 for (UtilityActorName idlName
:
2084 MakeWebIDLEnumeratedRange
<WebIDLUtilityActorName
>()) {
2085 aNames
.AppendElement(GetEnumString(idlName
));
2090 bool ChromeUtils::ShouldResistFingerprinting(
2091 GlobalObject
& aGlobal
, JSRFPTarget aTarget
,
2092 const Nullable
<uint64_t>& aOverriddenFingerprintingSettings
) {
2095 case JSRFPTarget::RoundWindowSize
:
2096 target
= RFPTarget::RoundWindowSize
;
2098 case JSRFPTarget::SiteSpecificZoom
:
2099 target
= RFPTarget::SiteSpecificZoom
;
2102 MOZ_CRASH("Unhandled JSRFPTarget enum value");
2106 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
2108 nsPIDOMWindowInner
* win
= global
->GetAsInnerWindow();
2110 nsIDocShell
* docshell
= win
->GetDocShell();
2112 nsDocShell::Cast(docshell
)->GetUsePrivateBrowsing(&isPBM
);
2117 Maybe
<RFPTarget
> overriddenFingerprintingSettings
;
2118 if (!aOverriddenFingerprintingSettings
.IsNull()) {
2119 overriddenFingerprintingSettings
.emplace(
2120 RFPTarget(aOverriddenFingerprintingSettings
.Value()));
2123 // This global object appears to be the global window, not for individual
2124 // sites so to exempt individual sites (instead of just PBM/Not-PBM windows)
2125 // more work would be needed to get the correct context.
2126 return nsRFPService::IsRFPEnabledFor(isPBM
, target
,
2127 overriddenFingerprintingSettings
);
2130 std::atomic
<uint32_t> ChromeUtils::sDevToolsOpenedCount
= 0;
2133 bool ChromeUtils::IsDevToolsOpened() {
2134 return ChromeUtils::sDevToolsOpenedCount
> 0;
2138 bool ChromeUtils::IsDevToolsOpened(GlobalObject
& aGlobal
) {
2139 return ChromeUtils::IsDevToolsOpened();
2143 void ChromeUtils::NotifyDevToolsOpened(GlobalObject
& aGlobal
) {
2144 ChromeUtils::sDevToolsOpenedCount
++;
2148 void ChromeUtils::NotifyDevToolsClosed(GlobalObject
& aGlobal
) {
2149 MOZ_ASSERT(ChromeUtils::sDevToolsOpenedCount
>= 1);
2150 ChromeUtils::sDevToolsOpenedCount
--;
2155 already_AddRefed
<Promise
> ChromeUtils::GetWMFContentDecryptionModuleInformation(
2156 GlobalObject
& aGlobal
, ErrorResult
& aRv
) {
2157 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
2159 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
2160 if (NS_WARN_IF(aRv
.Failed())) {
2163 MOZ_ASSERT(domPromise
);
2164 MFCDMService::GetAllKeySystemsCapabilities(domPromise
);
2165 return domPromise
.forget();
2169 already_AddRefed
<Promise
> ChromeUtils::GetGMPContentDecryptionModuleInformation(
2170 GlobalObject
& aGlobal
, ErrorResult
& aRv
) {
2171 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
2173 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
2174 if (NS_WARN_IF(aRv
.Failed())) {
2177 MOZ_ASSERT(domPromise
);
2178 KeySystemConfig::GetGMPKeySystemConfigs(domPromise
);
2179 return domPromise
.forget();
2182 } // namespace mozilla::dom