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/Object.h" // JS::GetClass
14 #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_DefinePropertyById, JS_Enumerate, JS_GetProperty, JS_GetPropertyById, JS_SetProperty, JS_SetPropertyById, JS::IdVector
15 #include "js/PropertyDescriptor.h" // JS::PropertyDescriptor, JS_GetOwnPropertyDescriptorById
16 #include "js/SavedFrameAPI.h"
17 #include "js/Value.h" // JS::Value, JS::StringValue
18 #include "jsfriendapi.h"
19 #include "WrapperFactory.h"
21 #include "mozilla/Base64.h"
22 #include "mozilla/CycleCollectedJSRuntime.h"
23 #include "mozilla/ErrorNames.h"
24 #include "mozilla/EventStateManager.h"
25 #include "mozilla/FormAutofillNative.h"
26 #include "mozilla/IntentionalCrash.h"
27 #include "mozilla/PerfStats.h"
28 #include "mozilla/Preferences.h"
29 #include "mozilla/ProcInfo.h"
30 #include "mozilla/ResultExtensions.h"
31 #include "mozilla/ScopeExit.h"
32 #include "mozilla/ScrollingMetrics.h"
33 #include "mozilla/SharedStyleSheetCache.h"
34 #include "mozilla/TimeStamp.h"
35 #include "mozilla/dom/ContentParent.h"
36 #include "mozilla/dom/IdleDeadline.h"
37 #include "mozilla/dom/InProcessParent.h"
38 #include "mozilla/dom/JSActorService.h"
39 #include "mozilla/dom/MediaSessionBinding.h"
40 #include "mozilla/dom/PBrowserParent.h"
41 #include "mozilla/dom/Performance.h"
42 #include "mozilla/dom/PopupBlocker.h"
43 #include "mozilla/dom/Promise.h"
44 #include "mozilla/dom/Record.h"
45 #include "mozilla/dom/ReportingHeader.h"
46 #include "mozilla/dom/UnionTypes.h"
47 #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
48 #include "mozilla/dom/WindowGlobalParent.h"
49 #include "mozilla/dom/WorkerScope.h"
50 #include "mozilla/ipc/GeckoChildProcessHost.h"
51 #include "mozilla/ipc/UtilityProcessSandboxing.h"
52 #include "mozilla/ipc/UtilityProcessManager.h"
53 #include "mozilla/ipc/UtilityProcessHost.h"
54 #include "mozilla/net/UrlClassifierFeatureFactory.h"
55 #include "mozilla/WheelHandlingHelper.h"
56 #include "IOActivityMonitor.h"
57 #include "nsNativeTheme.h"
58 #include "nsThreadUtils.h"
59 #include "mozJSModuleLoader.h"
60 #include "mozilla/ProfilerLabels.h"
61 #include "mozilla/ProfilerMarkers.h"
62 #include "nsIException.h"
63 #include "VsyncSource.h"
70 # include <sys/wait.h>
73 # include <sys/prctl.h>
77 namespace mozilla::dom
{
80 void ChromeUtils::NondeterministicGetWeakMapKeys(
81 GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aMap
,
82 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aRv
) {
83 if (!aMap
.isObject()) {
84 aRetval
.setUndefined();
86 JSContext
* cx
= aGlobal
.Context();
87 JS::Rooted
<JSObject
*> objRet(cx
);
88 JS::Rooted
<JSObject
*> mapObj(cx
, &aMap
.toObject());
89 if (!JS_NondeterministicGetWeakMapKeys(cx
, mapObj
, &objRet
)) {
90 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
92 aRetval
.set(objRet
? JS::ObjectValue(*objRet
) : JS::UndefinedValue());
98 void ChromeUtils::NondeterministicGetWeakSetKeys(
99 GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aSet
,
100 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aRv
) {
101 if (!aSet
.isObject()) {
102 aRetval
.setUndefined();
104 JSContext
* cx
= aGlobal
.Context();
105 JS::Rooted
<JSObject
*> objRet(cx
);
106 JS::Rooted
<JSObject
*> setObj(cx
, &aSet
.toObject());
107 if (!JS_NondeterministicGetWeakSetKeys(cx
, setObj
, &objRet
)) {
108 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
110 aRetval
.set(objRet
? JS::ObjectValue(*objRet
) : JS::UndefinedValue());
116 void ChromeUtils::Base64URLEncode(GlobalObject
& aGlobal
,
117 const ArrayBufferViewOrArrayBuffer
& aSource
,
118 const Base64URLEncodeOptions
& aOptions
,
119 nsACString
& aResult
, ErrorResult
& aRv
) {
121 uint8_t* data
= nullptr;
122 if (aSource
.IsArrayBuffer()) {
123 const ArrayBuffer
& buffer
= aSource
.GetAsArrayBuffer();
124 buffer
.ComputeState();
125 length
= buffer
.Length();
126 data
= buffer
.Data();
127 } else if (aSource
.IsArrayBufferView()) {
128 const ArrayBufferView
& view
= aSource
.GetAsArrayBufferView();
130 length
= view
.Length();
133 MOZ_CRASH("Uninitialized union: expected buffer or view");
136 auto paddingPolicy
= aOptions
.mPad
? Base64URLEncodePaddingPolicy::Include
137 : Base64URLEncodePaddingPolicy::Omit
;
138 nsresult rv
= mozilla::Base64URLEncode(length
, data
, paddingPolicy
, aResult
);
139 if (NS_WARN_IF(NS_FAILED(rv
))) {
146 void ChromeUtils::Base64URLDecode(GlobalObject
& aGlobal
,
147 const nsACString
& aString
,
148 const Base64URLDecodeOptions
& aOptions
,
149 JS::MutableHandle
<JSObject
*> aRetval
,
151 Base64URLDecodePaddingPolicy paddingPolicy
;
152 switch (aOptions
.mPadding
) {
153 case Base64URLDecodePadding::Require
:
154 paddingPolicy
= Base64URLDecodePaddingPolicy::Require
;
157 case Base64URLDecodePadding::Ignore
:
158 paddingPolicy
= Base64URLDecodePaddingPolicy::Ignore
;
161 case Base64URLDecodePadding::Reject
:
162 paddingPolicy
= Base64URLDecodePaddingPolicy::Reject
;
166 aRv
.Throw(NS_ERROR_INVALID_ARG
);
169 FallibleTArray
<uint8_t> data
;
170 nsresult rv
= mozilla::Base64URLDecode(aString
, paddingPolicy
, data
);
171 if (NS_WARN_IF(NS_FAILED(rv
))) {
176 JS::Rooted
<JSObject
*> buffer(
178 ArrayBuffer::Create(aGlobal
.Context(), data
.Length(), data
.Elements()));
179 if (NS_WARN_IF(!buffer
)) {
180 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
187 void ChromeUtils::ReleaseAssert(GlobalObject
& aGlobal
, bool aCondition
,
188 const nsAString
& aMessage
) {
189 // If the condition didn't fail, which is the likely case, immediately return.
190 if (MOZ_LIKELY(aCondition
)) {
194 // Extract the current stack from the JS runtime to embed in the crash reason.
195 nsAutoString filename
;
198 if (nsCOMPtr
<nsIStackFrame
> location
= GetCurrentJSStack(1)) {
199 location
->GetFilename(aGlobal
.Context(), filename
);
200 lineNo
= location
->GetLineNumber(aGlobal
.Context());
202 filename
.Assign(u
"<unknown>"_ns
);
205 // Convert to utf-8 for adding as the MozCrashReason.
206 NS_ConvertUTF16toUTF8
filenameUtf8(filename
);
207 NS_ConvertUTF16toUTF8
messageUtf8(aMessage
);
210 MOZ_CRASH_UNSAFE_PRINTF("Failed ChromeUtils.releaseAssert(\"%s\") @ %s:%u",
211 messageUtf8
.get(), filenameUtf8
.get(), lineNo
);
215 void ChromeUtils::AddProfilerMarker(
216 GlobalObject
& aGlobal
, const nsACString
& aName
,
217 const ProfilerMarkerOptionsOrDouble
& aOptions
,
218 const Optional
<nsACString
>& aText
) {
219 if (!profiler_thread_is_being_profiled_for_markers()) {
223 MarkerOptions options
;
225 MarkerCategory category
= ::geckoprofiler::category::JS
;
227 DOMHighResTimeStamp startTime
= 0;
228 uint64_t innerWindowId
= 0;
229 if (aOptions
.IsDouble()) {
230 startTime
= aOptions
.GetAsDouble();
232 const ProfilerMarkerOptions
& opt
= aOptions
.GetAsProfilerMarkerOptions();
233 startTime
= opt
.mStartTime
;
234 innerWindowId
= opt
.mInnerWindowId
;
236 if (opt
.mCaptureStack
) {
237 // If we will be capturing a stack, change the category of the
238 // ChromeUtils.addProfilerMarker label automatically added by the webidl
239 // binding from DOM to PROFILER so that this function doesn't appear in
241 JSContext
* cx
= aGlobal
.Context();
242 ProfilingStack
* stack
= js::GetContextProfilingStackIfEnabled(cx
);
243 if (MOZ_LIKELY(stack
)) {
244 uint32_t sp
= stack
->stackPointer
;
245 if (MOZ_LIKELY(sp
> 0)) {
246 js::ProfilingStackFrame
& frame
= stack
->frames
[sp
- 1];
247 if (frame
.isLabelFrame() && "ChromeUtils"_ns
.Equals(frame
.label()) &&
248 "addProfilerMarker"_ns
.Equals(frame
.dynamicString())) {
249 frame
.setLabelCategory(JS::ProfilingCategoryPair::PROFILER
);
254 options
.Set(MarkerStack::Capture());
256 #define BEGIN_CATEGORY(name, labelAsString, color) \
257 if (opt.mCategory.Equals(labelAsString)) { \
258 category = ::geckoprofiler::category::name; \
260 #define SUBCATEGORY(supercategory, name, labelAsString)
262 MOZ_PROFILING_CATEGORY_LIST(BEGIN_CATEGORY
, SUBCATEGORY
, END_CATEGORY
)
263 #undef BEGIN_CATEGORY
267 category
= ::geckoprofiler::category::OTHER
;
271 RefPtr
<Performance
> performance
;
273 if (NS_IsMainThread()) {
274 nsCOMPtr
<nsPIDOMWindowInner
> ownerWindow
=
275 do_QueryInterface(aGlobal
.GetAsSupports());
277 performance
= ownerWindow
->GetPerformance();
280 JSContext
* cx
= aGlobal
.Context();
281 WorkerPrivate
* workerPrivate
= GetWorkerPrivateFromContext(cx
);
283 performance
= workerPrivate
->GlobalScope()->GetPerformance();
288 options
.Set(MarkerTiming::IntervalUntilNowFrom(
289 performance
->CreationTimeStamp() +
290 TimeDuration::FromMilliseconds(startTime
)));
292 options
.Set(MarkerTiming::IntervalUntilNowFrom(
293 TimeStamp::ProcessCreation() +
294 TimeDuration::FromMilliseconds(startTime
)));
299 options
.Set(MarkerInnerWindowId(innerWindowId
));
301 options
.Set(MarkerInnerWindowIdFromJSContext(aGlobal
.Context()));
305 AUTO_PROFILER_STATS(ChromeUtils_AddProfilerMarker
);
306 if (aText
.WasPassed()) {
307 profiler_add_marker(aName
, category
, std::move(options
),
308 ::geckoprofiler::markers::TextMarker
{},
311 profiler_add_marker(aName
, category
, std::move(options
));
317 void ChromeUtils::GetXPCOMErrorName(GlobalObject
& aGlobal
, uint32_t aErrorCode
,
318 nsACString
& aRetval
) {
319 GetErrorName((nsresult
)aErrorCode
, aRetval
);
323 void ChromeUtils::WaiveXrays(GlobalObject
& aGlobal
, JS::Handle
<JS::Value
> aVal
,
324 JS::MutableHandle
<JS::Value
> aRetval
,
326 JS::Rooted
<JS::Value
> value(aGlobal
.Context(), aVal
);
327 if (!xpc::WrapperFactory::WaiveXrayAndWrap(aGlobal
.Context(), &value
)) {
328 aRv
.NoteJSContextException(aGlobal
.Context());
335 void ChromeUtils::UnwaiveXrays(GlobalObject
& aGlobal
,
336 JS::Handle
<JS::Value
> aVal
,
337 JS::MutableHandle
<JS::Value
> aRetval
,
339 if (!aVal
.isObject()) {
344 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(),
345 js::UncheckedUnwrap(&aVal
.toObject()));
346 if (!JS_WrapObject(aGlobal
.Context(), &obj
)) {
347 aRv
.NoteJSContextException(aGlobal
.Context());
349 aRetval
.setObject(*obj
);
354 void ChromeUtils::GetClassName(GlobalObject
& aGlobal
,
355 JS::Handle
<JSObject
*> aObj
, bool aUnwrap
,
356 nsAString
& aRetval
) {
357 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(), aObj
);
359 obj
= js::UncheckedUnwrap(obj
, /* stopAtWindowProxy = */ false);
362 aRetval
= NS_ConvertUTF8toUTF16(nsDependentCString(JS::GetClass(obj
)->name
));
366 bool ChromeUtils::IsDOMObject(GlobalObject
& aGlobal
, JS::Handle
<JSObject
*> aObj
,
368 JS::Rooted
<JSObject
*> obj(aGlobal
.Context(), aObj
);
370 obj
= js::UncheckedUnwrap(obj
, /* stopAtWindowProxy = */ false);
373 return mozilla::dom::IsDOMObject(obj
);
377 void ChromeUtils::ShallowClone(GlobalObject
& aGlobal
,
378 JS::Handle
<JSObject
*> aObj
,
379 JS::Handle
<JSObject
*> aTarget
,
380 JS::MutableHandle
<JSObject
*> aRetval
,
382 JSContext
* cx
= aGlobal
.Context();
384 auto cleanup
= MakeScopeExit([&]() { aRv
.NoteJSContextException(cx
); });
386 JS::Rooted
<JS::IdVector
> ids(cx
, JS::IdVector(cx
));
387 JS::RootedVector
<JS::Value
> values(cx
);
388 JS::RootedVector
<jsid
> valuesIds(cx
);
391 // cx represents our current Realm, so it makes sense to use it for the
392 // CheckedUnwrapDynamic call. We do want CheckedUnwrapDynamic, in case
393 // someone is shallow-cloning a Window.
394 JS::Rooted
<JSObject
*> obj(cx
, js::CheckedUnwrapDynamic(aObj
, cx
));
396 js::ReportAccessDenied(cx
);
400 if (js::IsScriptedProxy(obj
)) {
401 JS_ReportErrorASCII(cx
, "Shallow cloning a proxy object is not allowed");
405 JSAutoRealm
ar(cx
, obj
);
407 if (!JS_Enumerate(cx
, obj
, &ids
) || !values
.reserve(ids
.length()) ||
408 !valuesIds
.reserve(ids
.length())) {
412 JS::Rooted
<Maybe
<JS::PropertyDescriptor
>> desc(cx
);
413 JS::Rooted
<JS::PropertyKey
> id(cx
);
414 for (jsid idVal
: ids
) {
416 if (!JS_GetOwnPropertyDescriptorById(cx
, obj
, id
, &desc
)) {
419 if (desc
.isNothing() || desc
->isAccessorDescriptor()) {
422 valuesIds
.infallibleAppend(id
);
423 values
.infallibleAppend(desc
->value());
427 JS::Rooted
<JSObject
*> obj(cx
);
429 Maybe
<JSAutoRealm
> ar
;
431 // Our target could be anything, so we want CheckedUnwrapDynamic here.
432 // "cx" represents the current Realm when we were called from bindings, so
433 // we can just use that.
434 JS::Rooted
<JSObject
*> target(cx
, js::CheckedUnwrapDynamic(aTarget
, cx
));
436 js::ReportAccessDenied(cx
);
439 ar
.emplace(cx
, target
);
442 obj
= JS_NewPlainObject(cx
);
447 JS::Rooted
<JS::Value
> value(cx
);
448 JS::Rooted
<JS::PropertyKey
> id(cx
);
449 for (uint32_t i
= 0; i
< valuesIds
.length(); i
++) {
453 JS_MarkCrossZoneId(cx
, id
);
454 if (!JS_WrapValue(cx
, &value
) ||
455 !JS_SetPropertyById(cx
, obj
, id
, value
)) {
461 if (aTarget
&& !JS_WrapObject(cx
, &obj
)) {
470 class IdleDispatchRunnable final
: public IdleRunnable
,
471 public nsITimerCallback
{
473 NS_DECL_ISUPPORTS_INHERITED
475 IdleDispatchRunnable(nsIGlobalObject
* aParent
, IdleRequestCallback
& aCallback
)
476 : IdleRunnable("ChromeUtils::IdleDispatch"),
477 mCallback(&aCallback
),
480 // MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT.
482 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
Run() override
{
486 auto deadline
= mDeadline
- TimeStamp::ProcessCreation();
489 RefPtr
<IdleDeadline
> idleDeadline
=
490 new IdleDeadline(mParent
, mTimedOut
, deadline
.ToMilliseconds());
492 RefPtr
<IdleRequestCallback
> callback(std::move(mCallback
));
493 MOZ_ASSERT(!mCallback
);
494 callback
->Call(*idleDeadline
, "ChromeUtils::IdleDispatch handler");
500 void SetDeadline(TimeStamp aDeadline
) override
{ mDeadline
= aDeadline
; }
502 NS_IMETHOD
Notify(nsITimer
* aTimer
) override
{
504 SetDeadline(TimeStamp::Now());
508 void SetTimer(uint32_t aDelay
, nsIEventTarget
* aTarget
) override
{
511 NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, aDelay
,
512 nsITimer::TYPE_ONE_SHOT
, aTarget
);
516 virtual ~IdleDispatchRunnable() { CancelTimer(); }
526 RefPtr
<IdleRequestCallback
> mCallback
;
527 nsCOMPtr
<nsIGlobalObject
> mParent
;
529 nsCOMPtr
<nsITimer
> mTimer
;
531 TimeStamp mDeadline
{};
532 bool mTimedOut
= false;
535 NS_IMPL_ISUPPORTS_INHERITED(IdleDispatchRunnable
, IdleRunnable
,
537 } // anonymous namespace
540 void ChromeUtils::IdleDispatch(const GlobalObject
& aGlobal
,
541 IdleRequestCallback
& aCallback
,
542 const IdleRequestOptions
& aOptions
,
544 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
547 auto runnable
= MakeRefPtr
<IdleDispatchRunnable
>(global
, aCallback
);
549 if (aOptions
.mTimeout
.WasPassed()) {
550 aRv
= NS_DispatchToCurrentThreadQueue(
551 runnable
.forget(), aOptions
.mTimeout
.Value(), EventQueuePriority::Idle
);
553 aRv
= NS_DispatchToCurrentThreadQueue(runnable
.forget(),
554 EventQueuePriority::Idle
);
559 void ChromeUtils::Import(const GlobalObject
& aGlobal
,
560 const nsACString
& aResourceURI
,
561 const Optional
<JS::Handle
<JSObject
*>>& aTargetObj
,
562 JS::MutableHandle
<JSObject
*> aRetval
,
564 RefPtr moduleloader
= mozJSModuleLoader::Get();
565 MOZ_ASSERT(moduleloader
);
567 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE("ChromeUtils::Import",
568 OTHER
, aResourceURI
);
570 JSContext
* cx
= aGlobal
.Context();
572 JS::Rooted
<JSObject
*> global(cx
);
573 JS::Rooted
<JSObject
*> exports(cx
);
574 nsresult rv
= moduleloader
->Import(cx
, aResourceURI
, &global
, &exports
);
580 // Import() on the component loader can return NS_OK while leaving an
581 // exception on the JSContext. Check for that case.
582 if (JS_IsExceptionPending(cx
)) {
583 aRv
.NoteJSContextException(cx
);
587 if (aTargetObj
.WasPassed()) {
588 if (!JS_AssignObject(cx
, aTargetObj
.Value(), exports
)) {
589 aRv
.Throw(NS_ERROR_FAILURE
);
594 if (!JS_WrapObject(cx
, &exports
)) {
595 aRv
.Throw(NS_ERROR_FAILURE
);
598 aRetval
.set(exports
);
601 static mozJSModuleLoader
* GetContextualESLoader(
602 const Optional
<bool>& aLoadInDevToolsLoader
, JSObject
* aGlobal
) {
603 RefPtr devToolsModuleloader
= mozJSModuleLoader::GetDevToolsLoader();
604 // We should load the module in the DevTools loader if:
605 // - ChromeUtils.importESModule's `loadInDevToolsLoader` option is true, or,
606 // - if the callsite is from a module loaded in the DevTools loader and
607 // `loadInDevToolsLoader` isn't an explicit false.
608 bool shouldUseDevToolsLoader
=
609 (aLoadInDevToolsLoader
.WasPassed() && aLoadInDevToolsLoader
.Value()) ||
610 (devToolsModuleloader
&& !aLoadInDevToolsLoader
.WasPassed() &&
611 devToolsModuleloader
->IsLoaderGlobal(aGlobal
));
612 if (shouldUseDevToolsLoader
) {
613 return mozJSModuleLoader::GetOrCreateDevToolsLoader();
615 return mozJSModuleLoader::Get();
619 void ChromeUtils::ImportESModule(
620 const GlobalObject
& aGlobal
, const nsAString
& aResourceURI
,
621 const ImportESModuleOptionsDictionary
& aOptions
,
622 JS::MutableHandle
<JSObject
*> aRetval
, ErrorResult
& aRv
) {
623 RefPtr moduleloader
=
624 GetContextualESLoader(aOptions
.mLoadInDevToolsLoader
, aGlobal
.Get());
625 MOZ_ASSERT(moduleloader
);
627 NS_ConvertUTF16toUTF8
registryLocation(aResourceURI
);
629 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE(
630 "ChromeUtils::ImportESModule", OTHER
, registryLocation
);
632 JSContext
* cx
= aGlobal
.Context();
634 JS::Rooted
<JSObject
*> moduleNamespace(cx
);
636 moduleloader
->ImportESModule(cx
, registryLocation
, &moduleNamespace
);
642 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
644 if (!JS_WrapObject(cx
, &moduleNamespace
)) {
645 aRv
.Throw(NS_ERROR_FAILURE
);
648 aRetval
.set(moduleNamespace
);
651 namespace lazy_getter
{
653 static const size_t SLOT_ID
= 0;
654 static const size_t SLOT_URI
= 1;
655 static const size_t SLOT_PARAMS
= 1;
657 static const size_t PARAM_INDEX_TARGET
= 0;
658 static const size_t PARAM_INDEX_LAMBDA
= 1;
659 static const size_t PARAMS_COUNT
= 2;
661 static bool ExtractArgs(JSContext
* aCx
, JS::CallArgs
& aArgs
,
662 JS::MutableHandle
<JSObject
*> aCallee
,
663 JS::MutableHandle
<JSObject
*> aThisObj
,
664 JS::MutableHandle
<jsid
> aId
) {
665 aCallee
.set(&aArgs
.callee());
667 JS::Handle
<JS::Value
> thisv
= aArgs
.thisv();
668 if (!thisv
.isObject()) {
669 JS_ReportErrorASCII(aCx
, "Invalid target object");
673 aThisObj
.set(&thisv
.toObject());
675 JS::Rooted
<JS::Value
> id(aCx
,
676 js::GetFunctionNativeReserved(aCallee
, SLOT_ID
));
677 MOZ_ALWAYS_TRUE(JS_ValueToId(aCx
, id
, aId
));
681 static bool JSLazyGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
682 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
684 JS::Rooted
<JSObject
*> callee(aCx
);
685 JS::Rooted
<JSObject
*> unused(aCx
);
686 JS::Rooted
<jsid
> id(aCx
);
687 if (!ExtractArgs(aCx
, args
, &callee
, &unused
, &id
)) {
691 JS::Rooted
<JS::Value
> paramsVal(
692 aCx
, js::GetFunctionNativeReserved(callee
, SLOT_PARAMS
));
693 if (paramsVal
.isUndefined()) {
694 args
.rval().setUndefined();
697 // Avoid calling the lambda multiple times, in case of:
698 // * the getter function is retrieved from property descriptor and called
699 // * the lambda gets the property again
700 // * the getter function throws and accessed again
701 js::SetFunctionNativeReserved(callee
, SLOT_PARAMS
, JS::UndefinedHandleValue
);
703 JS::Rooted
<JSObject
*> paramsObj(aCx
, ¶msVal
.toObject());
705 JS::Rooted
<JS::Value
> targetVal(aCx
);
706 JS::Rooted
<JS::Value
> lambdaVal(aCx
);
707 if (!JS_GetElement(aCx
, paramsObj
, PARAM_INDEX_TARGET
, &targetVal
)) {
710 if (!JS_GetElement(aCx
, paramsObj
, PARAM_INDEX_LAMBDA
, &lambdaVal
)) {
714 JS::Rooted
<JSObject
*> targetObj(aCx
, &targetVal
.toObject());
716 JS::Rooted
<JS::Value
> value(aCx
);
717 if (!JS::Call(aCx
, targetObj
, lambdaVal
, JS::HandleValueArray::empty(),
722 if (!JS_DefinePropertyById(aCx
, targetObj
, id
, value
, JSPROP_ENUMERATE
)) {
726 args
.rval().set(value
);
730 static bool DefineLazyGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
731 JS::Handle
<JS::Value
> aName
,
732 JS::Handle
<JSObject
*> aLambda
) {
733 JS::Rooted
<jsid
> id(aCx
);
734 if (!JS_ValueToId(aCx
, aName
, &id
)) {
738 JS::Rooted
<JSObject
*> getter(
739 aCx
, JS_GetFunctionObject(
740 js::NewFunctionByIdWithReserved(aCx
, JSLazyGetter
, 0, 0, id
)));
742 JS_ReportOutOfMemory(aCx
);
746 JS::RootedVector
<JS::Value
> params(aCx
);
747 if (!params
.resize(PARAMS_COUNT
)) {
750 params
[PARAM_INDEX_TARGET
].setObject(*aTarget
);
751 params
[PARAM_INDEX_LAMBDA
].setObject(*aLambda
);
752 JS::Rooted
<JSObject
*> paramsObj(aCx
, JS::NewArrayObject(aCx
, params
));
757 js::SetFunctionNativeReserved(getter
, SLOT_ID
, aName
);
758 js::SetFunctionNativeReserved(getter
, SLOT_PARAMS
,
759 JS::ObjectValue(*paramsObj
));
761 return JS_DefinePropertyById(aCx
, aTarget
, id
, getter
, nullptr,
765 enum class ModuleType
{ JSM
, ESM
};
767 static bool ModuleGetterImpl(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
,
769 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
771 JS::Rooted
<JSObject
*> callee(aCx
);
772 JS::Rooted
<JSObject
*> thisObj(aCx
);
773 JS::Rooted
<jsid
> id(aCx
);
774 if (!ExtractArgs(aCx
, args
, &callee
, &thisObj
, &id
)) {
778 JS::Rooted
<JSString
*> moduleURI(
779 aCx
, js::GetFunctionNativeReserved(callee
, SLOT_URI
).toString());
780 JS::UniqueChars bytes
= JS_EncodeStringToUTF8(aCx
, moduleURI
);
784 nsDependentCString
uri(bytes
.get());
786 RefPtr moduleloader
=
787 aType
== ModuleType::JSM
788 ? mozJSModuleLoader::Get()
789 : GetContextualESLoader(
791 JS::GetNonCCWObjectGlobal(js::UncheckedUnwrap(thisObj
)));
792 MOZ_ASSERT(moduleloader
);
794 JS::Rooted
<JS::Value
> value(aCx
);
795 if (aType
== ModuleType::JSM
) {
796 JS::Rooted
<JSObject
*> moduleGlobal(aCx
);
797 JS::Rooted
<JSObject
*> moduleExports(aCx
);
798 nsresult rv
= moduleloader
->Import(aCx
, uri
, &moduleGlobal
, &moduleExports
);
804 // JSM's exports is from the same realm.
805 if (!JS_GetPropertyById(aCx
, moduleExports
, id
, &value
)) {
809 JS::Rooted
<JSObject
*> moduleNamespace(aCx
);
810 nsresult rv
= moduleloader
->ImportESModule(aCx
, uri
, &moduleNamespace
);
816 // ESM's namespace is from the module's realm.
818 JSAutoRealm
ar(aCx
, moduleNamespace
);
819 if (!JS_GetPropertyById(aCx
, moduleNamespace
, id
, &value
)) {
823 if (!JS_WrapValue(aCx
, &value
)) {
828 if (!JS_DefinePropertyById(aCx
, thisObj
, id
, value
, JSPROP_ENUMERATE
)) {
832 args
.rval().set(value
);
836 static bool JSModuleGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
837 return ModuleGetterImpl(aCx
, aArgc
, aVp
, ModuleType::JSM
);
840 static bool ESModuleGetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
841 return ModuleGetterImpl(aCx
, aArgc
, aVp
, ModuleType::ESM
);
844 static bool ModuleSetterImpl(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
845 JS::CallArgs args
= JS::CallArgsFromVp(aArgc
, aVp
);
847 JS::Rooted
<JSObject
*> callee(aCx
);
848 JS::Rooted
<JSObject
*> thisObj(aCx
);
849 JS::Rooted
<jsid
> id(aCx
);
850 if (!ExtractArgs(aCx
, args
, &callee
, &thisObj
, &id
)) {
854 return JS_DefinePropertyById(aCx
, thisObj
, id
, args
.get(0), JSPROP_ENUMERATE
);
857 static bool JSModuleSetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
858 return ModuleSetterImpl(aCx
, aArgc
, aVp
);
861 static bool ESModuleSetter(JSContext
* aCx
, unsigned aArgc
, JS::Value
* aVp
) {
862 return ModuleSetterImpl(aCx
, aArgc
, aVp
);
865 static bool DefineJSModuleGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
866 const nsAString
& aId
,
867 const nsAString
& aResourceURI
) {
868 JS::Rooted
<JS::Value
> uri(aCx
);
869 JS::Rooted
<JS::Value
> idValue(aCx
);
870 JS::Rooted
<jsid
> id(aCx
);
871 if (!xpc::NonVoidStringToJsval(aCx
, aResourceURI
, &uri
) ||
872 !xpc::NonVoidStringToJsval(aCx
, aId
, &idValue
) ||
873 !JS_ValueToId(aCx
, idValue
, &id
)) {
876 idValue
= js::IdToValue(id
);
878 JS::Rooted
<JSObject
*> getter(
879 aCx
, JS_GetFunctionObject(
880 js::NewFunctionByIdWithReserved(aCx
, JSModuleGetter
, 0, 0, id
)));
882 JS::Rooted
<JSObject
*> setter(
883 aCx
, JS_GetFunctionObject(
884 js::NewFunctionByIdWithReserved(aCx
, JSModuleSetter
, 0, 0, id
)));
886 if (!getter
|| !setter
) {
887 JS_ReportOutOfMemory(aCx
);
891 js::SetFunctionNativeReserved(getter
, SLOT_ID
, idValue
);
892 js::SetFunctionNativeReserved(setter
, SLOT_ID
, idValue
);
894 js::SetFunctionNativeReserved(getter
, SLOT_URI
, uri
);
896 return JS_DefinePropertyById(aCx
, aTarget
, id
, getter
, setter
,
900 static bool DefineESModuleGetter(JSContext
* aCx
, JS::Handle
<JSObject
*> aTarget
,
901 JS::Handle
<JS::PropertyKey
> aId
,
902 JS::Handle
<JS::Value
> aResourceURI
) {
903 JS::Rooted
<JS::Value
> idVal(aCx
, JS::StringValue(aId
.toString()));
905 JS::Rooted
<JSObject
*> getter(
906 aCx
, JS_GetFunctionObject(js::NewFunctionByIdWithReserved(
907 aCx
, ESModuleGetter
, 0, 0, aId
)));
909 JS::Rooted
<JSObject
*> setter(
910 aCx
, JS_GetFunctionObject(js::NewFunctionByIdWithReserved(
911 aCx
, ESModuleSetter
, 0, 0, aId
)));
913 if (!getter
|| !setter
) {
914 JS_ReportOutOfMemory(aCx
);
918 js::SetFunctionNativeReserved(getter
, SLOT_ID
, idVal
);
919 js::SetFunctionNativeReserved(setter
, SLOT_ID
, idVal
);
921 js::SetFunctionNativeReserved(getter
, SLOT_URI
, aResourceURI
);
923 return JS_DefinePropertyById(aCx
, aTarget
, aId
, getter
, setter
,
927 } // namespace lazy_getter
930 void ChromeUtils::DefineLazyGetter(const GlobalObject
& aGlobal
,
931 JS::Handle
<JSObject
*> aTarget
,
932 JS::Handle
<JS::Value
> aName
,
933 JS::Handle
<JSObject
*> aLambda
,
935 JSContext
* cx
= aGlobal
.Context();
936 if (!lazy_getter::DefineLazyGetter(cx
, aTarget
, aName
, aLambda
)) {
937 aRv
.NoteJSContextException(cx
);
943 void ChromeUtils::DefineModuleGetter(const GlobalObject
& global
,
944 JS::Handle
<JSObject
*> target
,
946 const nsAString
& resourceURI
,
948 if (!lazy_getter::DefineJSModuleGetter(global
.Context(), target
, id
,
950 aRv
.NoteJSContextException(global
.Context());
955 void ChromeUtils::DefineESModuleGetters(const GlobalObject
& global
,
956 JS::Handle
<JSObject
*> target
,
957 JS::Handle
<JSObject
*> modules
,
959 JSContext
* cx
= global
.Context();
961 JS::Rooted
<JS::IdVector
> props(cx
, JS::IdVector(cx
));
962 if (!JS_Enumerate(cx
, modules
, &props
)) {
963 aRv
.NoteJSContextException(cx
);
967 JS::Rooted
<JS::PropertyKey
> prop(cx
);
968 JS::Rooted
<JS::Value
> resourceURIVal(cx
);
969 for (JS::PropertyKey tmp
: props
) {
972 if (!prop
.isString()) {
973 aRv
.Throw(NS_ERROR_FAILURE
);
977 if (!JS_GetPropertyById(cx
, modules
, prop
, &resourceURIVal
)) {
978 aRv
.NoteJSContextException(cx
);
982 if (!lazy_getter::DefineESModuleGetter(cx
, target
, prop
, resourceURIVal
)) {
983 aRv
.NoteJSContextException(cx
);
991 void ChromeUtils::GetLibcConstants(const GlobalObject
&,
992 LibcConstants
& aConsts
) {
993 aConsts
.mEINTR
.Construct(EINTR
);
994 aConsts
.mEACCES
.Construct(EACCES
);
995 aConsts
.mEAGAIN
.Construct(EAGAIN
);
996 aConsts
.mEINVAL
.Construct(EINVAL
);
997 aConsts
.mENOSYS
.Construct(ENOSYS
);
999 aConsts
.mF_SETFD
.Construct(F_SETFD
);
1000 aConsts
.mF_SETFL
.Construct(F_SETFL
);
1002 aConsts
.mFD_CLOEXEC
.Construct(FD_CLOEXEC
);
1004 aConsts
.mAT_EACCESS
.Construct(AT_EACCESS
);
1006 aConsts
.mO_CREAT
.Construct(O_CREAT
);
1007 aConsts
.mO_NONBLOCK
.Construct(O_NONBLOCK
);
1008 aConsts
.mO_WRONLY
.Construct(O_WRONLY
);
1010 aConsts
.mPOLLERR
.Construct(POLLERR
);
1011 aConsts
.mPOLLHUP
.Construct(POLLHUP
);
1012 aConsts
.mPOLLIN
.Construct(POLLIN
);
1013 aConsts
.mPOLLNVAL
.Construct(POLLNVAL
);
1014 aConsts
.mPOLLOUT
.Construct(POLLOUT
);
1016 aConsts
.mWNOHANG
.Construct(WNOHANG
);
1019 aConsts
.mPR_CAPBSET_READ
.Construct(PR_CAPBSET_READ
);
1025 void ChromeUtils::OriginAttributesToSuffix(
1026 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1030 OriginAttributes
attrs(aAttrs
);
1031 attrs
.CreateSuffix(aSuffix
);
1035 bool ChromeUtils::OriginAttributesMatchPattern(
1036 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1037 const dom::OriginAttributesPatternDictionary
& aPattern
) {
1038 OriginAttributes
attrs(aAttrs
);
1039 OriginAttributesPattern
pattern(aPattern
);
1040 return pattern
.Matches(attrs
);
1044 void ChromeUtils::CreateOriginAttributesFromOrigin(
1045 dom::GlobalObject
& aGlobal
, const nsAString
& aOrigin
,
1046 dom::OriginAttributesDictionary
& aAttrs
, ErrorResult
& aRv
) {
1047 OriginAttributes attrs
;
1048 nsAutoCString suffix
;
1049 if (!attrs
.PopulateFromOrigin(NS_ConvertUTF16toUTF8(aOrigin
), suffix
)) {
1050 aRv
.Throw(NS_ERROR_FAILURE
);
1057 void ChromeUtils::CreateOriginAttributesFromOriginSuffix(
1058 dom::GlobalObject
& aGlobal
, const nsAString
& aSuffix
,
1059 dom::OriginAttributesDictionary
& aAttrs
, ErrorResult
& aRv
) {
1060 OriginAttributes attrs
;
1061 nsAutoCString suffix
;
1062 if (!attrs
.PopulateFromSuffix(NS_ConvertUTF16toUTF8(aSuffix
))) {
1063 aRv
.Throw(NS_ERROR_FAILURE
);
1070 void ChromeUtils::FillNonDefaultOriginAttributes(
1071 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aAttrs
,
1072 dom::OriginAttributesDictionary
& aNewAttrs
) {
1077 bool ChromeUtils::IsOriginAttributesEqual(
1078 dom::GlobalObject
& aGlobal
, const dom::OriginAttributesDictionary
& aA
,
1079 const dom::OriginAttributesDictionary
& aB
) {
1080 return IsOriginAttributesEqual(aA
, aB
);
1084 bool ChromeUtils::IsOriginAttributesEqual(
1085 const dom::OriginAttributesDictionary
& aA
,
1086 const dom::OriginAttributesDictionary
& aB
) {
1091 void ChromeUtils::GetBaseDomainFromPartitionKey(dom::GlobalObject
& aGlobal
,
1092 const nsAString
& aPartitionKey
,
1093 nsAString
& aBaseDomain
,
1096 nsString pkBaseDomain
;
1099 if (!mozilla::OriginAttributes::ParsePartitionKey(aPartitionKey
, scheme
,
1100 pkBaseDomain
, port
)) {
1101 aRv
.Throw(NS_ERROR_FAILURE
);
1105 aBaseDomain
= pkBaseDomain
;
1109 void ChromeUtils::GetPartitionKeyFromURL(dom::GlobalObject
& aGlobal
,
1110 const nsAString
& aURL
,
1111 nsAString
& aPartitionKey
,
1113 nsCOMPtr
<nsIURI
> uri
;
1114 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURL
);
1115 if (NS_SUCCEEDED(rv
) && uri
->SchemeIs("chrome")) {
1116 rv
= NS_ERROR_FAILURE
;
1119 if (NS_WARN_IF(NS_FAILED(rv
))) {
1120 aPartitionKey
.Truncate();
1125 mozilla::OriginAttributes attrs
;
1126 attrs
.SetPartitionKey(uri
);
1128 aPartitionKey
= attrs
.mPartitionKey
;
1131 #ifdef NIGHTLY_BUILD
1133 void ChromeUtils::GetRecentJSDevError(GlobalObject
& aGlobal
,
1134 JS::MutableHandle
<JS::Value
> aRetval
,
1136 aRetval
.setUndefined();
1137 auto runtime
= CycleCollectedJSRuntime::Get();
1138 MOZ_ASSERT(runtime
);
1140 auto cx
= aGlobal
.Context();
1141 if (!runtime
->GetRecentDevError(cx
, aRetval
)) {
1142 aRv
.NoteJSContextException(cx
);
1148 void ChromeUtils::ClearRecentJSDevError(GlobalObject
&) {
1149 auto runtime
= CycleCollectedJSRuntime::Get();
1150 MOZ_ASSERT(runtime
);
1152 runtime
->ClearRecentDevError();
1154 #endif // NIGHTLY_BUILD
1156 void ChromeUtils::ClearStyleSheetCacheByPrincipal(GlobalObject
&,
1157 nsIPrincipal
* aForPrincipal
) {
1158 SharedStyleSheetCache::Clear(aForPrincipal
);
1161 void ChromeUtils::ClearStyleSheetCacheByBaseDomain(
1162 GlobalObject
&, const nsACString
& aBaseDomain
) {
1163 SharedStyleSheetCache::Clear(nullptr, &aBaseDomain
);
1166 void ChromeUtils::ClearStyleSheetCache(GlobalObject
&) {
1167 SharedStyleSheetCache::Clear();
1170 #define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \
1171 case mozilla::ProcType::_procType: \
1172 return WebIDLProcType::_webidl
1174 static WebIDLProcType
ProcTypeToWebIDL(mozilla::ProcType aType
) {
1175 // Max is the value of the last enum, not the length, so add one.
1177 WebIDLProcTypeValues::Count
== static_cast<size_t>(ProcType::Max
) + 1,
1178 "In order for this static cast to be okay, "
1179 "WebIDLProcType must match ProcType exactly");
1181 // These must match the similar ones in E10SUtils.sys.mjs, RemoteTypes.h,
1182 // ProcInfo.h and ChromeUtils.webidl
1184 PROCTYPE_TO_WEBIDL_CASE(Web
, Web
);
1185 PROCTYPE_TO_WEBIDL_CASE(WebIsolated
, WebIsolated
);
1186 PROCTYPE_TO_WEBIDL_CASE(File
, File
);
1187 PROCTYPE_TO_WEBIDL_CASE(Extension
, Extension
);
1188 PROCTYPE_TO_WEBIDL_CASE(PrivilegedAbout
, Privilegedabout
);
1189 PROCTYPE_TO_WEBIDL_CASE(PrivilegedMozilla
, Privilegedmozilla
);
1190 PROCTYPE_TO_WEBIDL_CASE(WebCOOPCOEP
, WithCoopCoep
);
1191 PROCTYPE_TO_WEBIDL_CASE(WebServiceWorker
, WebServiceWorker
);
1193 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1194 process_bin_type, procinfo_typename, \
1195 webidl_typename, allcaps_name) \
1196 PROCTYPE_TO_WEBIDL_CASE(procinfo_typename, webidl_typename);
1197 #define SKIP_PROCESS_TYPE_CONTENT
1198 #ifndef MOZ_ENABLE_FORKSERVER
1199 # define SKIP_PROCESS_TYPE_FORKSERVER
1200 #endif // MOZ_ENABLE_FORKSERVER
1201 #include "mozilla/GeckoProcessTypes.h"
1202 #undef SKIP_PROCESS_TYPE_CONTENT
1203 #ifndef MOZ_ENABLE_FORKSERVER
1204 # undef SKIP_PROCESS_TYPE_FORKSERVER
1205 #endif // MOZ_ENABLE_FORKSERVER
1206 #undef GECKO_PROCESS_TYPE
1208 PROCTYPE_TO_WEBIDL_CASE(Preallocated
, Preallocated
);
1209 PROCTYPE_TO_WEBIDL_CASE(Unknown
, Unknown
);
1212 MOZ_ASSERT(false, "Unhandled case in ProcTypeToWebIDL");
1213 return WebIDLProcType::Unknown
;
1216 #undef PROCTYPE_TO_WEBIDL_CASE
1219 already_AddRefed
<Promise
> ChromeUtils::RequestProcInfo(GlobalObject
& aGlobal
,
1221 // This function will use IPDL to enable threads info on macOS
1222 // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023
1223 if (!XRE_IsParentProcess()) {
1224 aRv
.Throw(NS_ERROR_FAILURE
);
1227 // Prepare the JS promise that will hold our response.
1228 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1230 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
1231 if (NS_WARN_IF(aRv
.Failed())) {
1234 MOZ_ASSERT(domPromise
);
1236 // Get a list of processes to examine and pre-fill them with available info.
1237 // Note that this is subject to race conditions: just because we have a
1238 // process in the list doesn't mean that the process will still be alive when
1239 // we attempt to get its information. Followup code MUST be able to fail
1240 // gracefully on some processes and still return whichever information is
1243 // Get all the content parents.
1244 // Note that this array includes even the long dead content parents, so we
1245 // might have some garbage, especially with Fission.
1246 // SAFETY NOTE: `contentParents` is only valid if used synchronously.
1247 // Anything else and you may end up dealing with dangling pointers.
1248 nsTArray
<ContentParent
*> contentParents
;
1249 ContentParent::GetAll(contentParents
);
1251 // Prepare our background request.
1252 // We reserve one more slot for the browser process itself.
1253 nsTArray
<ProcInfoRequest
> requests(contentParents
.Length() + 1);
1254 // Requesting process info for the browser process itself.
1255 requests
.EmplaceBack(
1256 /* aPid = */ base::GetCurrentProcId(),
1257 /* aProcessType = */ ProcType::Browser
,
1258 /* aOrigin = */ ""_ns
,
1259 /* aWindowInfo = */ nsTArray
<WindowInfo
>(),
1260 /* aUtilityInfo = */ nsTArray
<UtilityInfo
>());
1262 // First handle non-ContentParent processes.
1263 mozilla::ipc::GeckoChildProcessHost::GetAll(
1264 [&requests
](mozilla::ipc::GeckoChildProcessHost
* aGeckoProcess
) {
1265 base::ProcessId childPid
= aGeckoProcess
->GetChildProcessId();
1266 if (childPid
== 0) {
1267 // Something went wrong with this process, it may be dead already,
1271 mozilla::ProcType type
= mozilla::ProcType::Unknown
;
1273 switch (aGeckoProcess
->GetProcessType()) {
1274 case GeckoProcessType::GeckoProcessType_Content
: {
1275 // These processes are handled separately.
1279 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1280 process_bin_type, procinfo_typename, \
1281 webidl_typename, allcaps_name) \
1282 case GeckoProcessType::GeckoProcessType_##enum_name: { \
1283 type = mozilla::ProcType::procinfo_typename; \
1286 #define SKIP_PROCESS_TYPE_CONTENT
1287 #ifndef MOZ_ENABLE_FORKSERVER
1288 # define SKIP_PROCESS_TYPE_FORKSERVER
1289 #endif // MOZ_ENABLE_FORKSERVER
1290 #include "mozilla/GeckoProcessTypes.h"
1291 #ifndef MOZ_ENABLE_FORKSERVER
1292 # undef SKIP_PROCESS_TYPE_FORKSERVER
1293 #endif // MOZ_ENABLE_FORKSERVER
1294 #undef SKIP_PROCESS_TYPE_CONTENT
1295 #undef GECKO_PROCESS_TYPE
1297 // Leave the default Unknown value in |type|.
1301 // Attach utility actor information to the process.
1302 nsTArray
<UtilityInfo
> utilityActors
;
1303 if (aGeckoProcess
->GetProcessType() ==
1304 GeckoProcessType::GeckoProcessType_Utility
) {
1305 RefPtr
<mozilla::ipc::UtilityProcessManager
> upm
=
1306 mozilla::ipc::UtilityProcessManager::GetSingleton();
1307 if (!utilityActors
.AppendElements(upm
->GetActors(aGeckoProcess
),
1309 NS_WARNING("Error adding actors");
1314 requests
.EmplaceBack(
1315 /* aPid = */ childPid
,
1316 /* aProcessType = */ type
,
1317 /* aOrigin = */ ""_ns
,
1318 /* aWindowInfo = */ nsTArray
<WindowInfo
>(), // Without a
1319 // ContentProcess, no
1321 /* aUtilityInfo = */ std::move(utilityActors
),
1322 /* aChild = */ 0 // Without a ContentProcess, no ChildId.
1325 /* aChildTask = */ aGeckoProcess
->GetChildTask()
1330 // Now handle ContentParents.
1331 for (const auto* contentParent
: contentParents
) {
1332 if (!contentParent
|| !contentParent
->Process()) {
1333 // Presumably, the process is dead or dying.
1336 base::ProcessId pid
= contentParent
->Process()->GetChildProcessId();
1338 // Presumably, the process is dead or dying.
1341 if (contentParent
->Process()->GetProcessType() !=
1342 GeckoProcessType::GeckoProcessType_Content
) {
1343 // We're probably racing against a process changing type.
1344 // We'll get it in the next call, skip it for the moment.
1348 // Since this code is executed synchronously on the main thread,
1349 // processes cannot die while we're in this loop.
1350 mozilla::ProcType type
= mozilla::ProcType::Unknown
;
1352 // Convert the remoteType into a ProcType.
1353 // Ideally, the remoteType should be strongly typed
1354 // upstream, this would make the conversion less brittle.
1355 const nsAutoCString
remoteType(contentParent
->GetRemoteType());
1356 if (StringBeginsWith(remoteType
, FISSION_WEB_REMOTE_TYPE
)) {
1357 // WARNING: Do not change the order, as
1358 // `DEFAULT_REMOTE_TYPE` is a prefix of
1359 // `FISSION_WEB_REMOTE_TYPE`.
1360 type
= mozilla::ProcType::WebIsolated
;
1361 } else if (StringBeginsWith(remoteType
, SERVICEWORKER_REMOTE_TYPE
)) {
1362 type
= mozilla::ProcType::WebServiceWorker
;
1363 } else if (StringBeginsWith(remoteType
,
1364 WITH_COOP_COEP_REMOTE_TYPE_PREFIX
)) {
1365 type
= mozilla::ProcType::WebCOOPCOEP
;
1366 } else if (remoteType
== FILE_REMOTE_TYPE
) {
1367 type
= mozilla::ProcType::File
;
1368 } else if (remoteType
== EXTENSION_REMOTE_TYPE
) {
1369 type
= mozilla::ProcType::Extension
;
1370 } else if (remoteType
== PRIVILEGEDABOUT_REMOTE_TYPE
) {
1371 type
= mozilla::ProcType::PrivilegedAbout
;
1372 } else if (remoteType
== PRIVILEGEDMOZILLA_REMOTE_TYPE
) {
1373 type
= mozilla::ProcType::PrivilegedMozilla
;
1374 } else if (remoteType
== PREALLOC_REMOTE_TYPE
) {
1375 type
= mozilla::ProcType::Preallocated
;
1376 } else if (StringBeginsWith(remoteType
, DEFAULT_REMOTE_TYPE
)) {
1377 type
= mozilla::ProcType::Web
;
1379 MOZ_CRASH_UNSAFE_PRINTF("Unknown remoteType '%s'", remoteType
.get());
1382 // By convention, everything after '=' is the origin.
1383 nsAutoCString origin
;
1384 nsACString::const_iterator cursor
;
1385 nsACString::const_iterator end
;
1386 remoteType
.BeginReading(cursor
);
1387 remoteType
.EndReading(end
);
1388 if (FindCharInReadable('=', cursor
, end
)) {
1389 origin
= Substring(++cursor
, end
);
1392 // Attach DOM window information to the process.
1393 nsTArray
<WindowInfo
> windows
;
1394 for (const auto& browserParentWrapperKey
:
1395 contentParent
->ManagedPBrowserParent()) {
1396 for (const auto& windowGlobalParentWrapperKey
:
1397 browserParentWrapperKey
->ManagedPWindowGlobalParent()) {
1398 // WindowGlobalParent is the only immediate subclass of
1399 // PWindowGlobalParent.
1400 auto* windowGlobalParent
=
1401 static_cast<WindowGlobalParent
*>(windowGlobalParentWrapperKey
);
1403 nsString documentTitle
;
1404 windowGlobalParent
->GetDocumentTitle(documentTitle
);
1405 WindowInfo
* window
= windows
.EmplaceBack(
1407 /* aOuterWindowId = */ windowGlobalParent
->OuterWindowId(),
1408 /* aDocumentURI = */ windowGlobalParent
->GetDocumentURI(),
1409 /* aDocumentTitle = */ std::move(documentTitle
),
1410 /* aIsProcessRoot = */ windowGlobalParent
->IsProcessRoot(),
1411 /* aIsInProcess = */ windowGlobalParent
->IsInProcess());
1413 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
1418 requests
.EmplaceBack(
1420 /* aProcessType = */ type
,
1421 /* aOrigin = */ origin
,
1422 /* aWindowInfo = */ std::move(windows
),
1423 /* aUtilityInfo = */ nsTArray
<UtilityInfo
>(),
1424 /* aChild = */ contentParent
->ChildID()
1427 /* aChildTask = */ contentParent
->Process()->GetChildTask()
1432 // Now place background request.
1433 RefPtr
<nsISerialEventTarget
> target
=
1434 global
->EventTargetFor(TaskCategory::Performance
);
1435 mozilla::GetProcInfo(std::move(requests
))
1439 domPromise
](const HashMap
<base::ProcessId
, ProcInfo
>& aSysProcInfo
) {
1440 ParentProcInfoDictionary parentInfo
;
1441 if (aSysProcInfo
.count() == 0) {
1442 // For some reason, we couldn't get *any* info.
1443 // Maybe a sandboxing issue?
1444 domPromise
->MaybeReject(NS_ERROR_UNEXPECTED
);
1447 nsTArray
<ChildProcInfoDictionary
> childrenInfo(
1448 aSysProcInfo
.count() - 1);
1449 for (auto iter
= aSysProcInfo
.iter(); !iter
.done(); iter
.next()) {
1450 const auto& sysProcInfo
= iter
.get().value();
1452 if (sysProcInfo
.type
== ProcType::Browser
) {
1453 rv
= mozilla::CopySysProcInfoToDOM(sysProcInfo
, &parentInfo
);
1454 if (NS_FAILED(rv
)) {
1455 // Failing to copy? That's probably not something from we can
1456 // (or should) try to recover gracefully.
1457 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1460 MOZ_ASSERT(sysProcInfo
.childId
== 0);
1461 MOZ_ASSERT(sysProcInfo
.origin
.IsEmpty());
1463 mozilla::dom::ChildProcInfoDictionary
* childInfo
=
1464 childrenInfo
.AppendElement(fallible
);
1466 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1469 rv
= mozilla::CopySysProcInfoToDOM(sysProcInfo
, childInfo
);
1470 if (NS_FAILED(rv
)) {
1471 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1474 // Copy Firefox info.
1475 childInfo
->mChildID
= sysProcInfo
.childId
;
1476 childInfo
->mOrigin
= sysProcInfo
.origin
;
1477 childInfo
->mType
= ProcTypeToWebIDL(sysProcInfo
.type
);
1479 for (const auto& source
: sysProcInfo
.windows
) {
1480 auto* dest
= childInfo
->mWindows
.AppendElement(fallible
);
1482 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1485 dest
->mOuterWindowId
= source
.outerWindowId
;
1486 dest
->mDocumentURI
= source
.documentURI
;
1487 dest
->mDocumentTitle
= source
.documentTitle
;
1488 dest
->mIsProcessRoot
= source
.isProcessRoot
;
1489 dest
->mIsInProcess
= source
.isInProcess
;
1492 if (sysProcInfo
.type
== ProcType::Utility
) {
1493 for (const auto& source
: sysProcInfo
.utilityActors
) {
1495 childInfo
->mUtilityActors
.AppendElement(fallible
);
1497 domPromise
->MaybeReject(NS_ERROR_OUT_OF_MEMORY
);
1501 dest
->mActorName
= source
.actorName
;
1507 // Attach the children to the parent.
1508 mozilla::dom::Sequence
<mozilla::dom::ChildProcInfoDictionary
>
1509 children(std::move(childrenInfo
));
1510 parentInfo
.mChildren
= std::move(children
);
1511 domPromise
->MaybeResolve(parentInfo
);
1513 [domPromise
](nsresult aRv
) { domPromise
->MaybeReject(aRv
); });
1514 MOZ_ASSERT(domPromise
);
1516 // sending back the promise instance
1517 return domPromise
.forget();
1521 bool ChromeUtils::VsyncEnabled(GlobalObject
& aGlobal
) {
1522 return mozilla::gfx::VsyncSource::GetFastestVsyncRate().isSome();
1525 void ChromeUtils::SetPerfStatsCollectionMask(GlobalObject
& aGlobal
,
1527 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask
>(aMask
));
1530 already_AddRefed
<Promise
> ChromeUtils::CollectPerfStats(GlobalObject
& aGlobal
,
1532 // Creating a JS promise
1533 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1536 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
1541 RefPtr
<PerfStats::PerfStatsPromise
> extPromise
=
1542 PerfStats::CollectPerfStatsJSON();
1545 GetCurrentSerialEventTarget(), __func__
,
1546 [promise
](const nsCString
& aResult
) {
1547 promise
->MaybeResolve(NS_ConvertUTF8toUTF16(aResult
));
1549 [promise
](bool aValue
) { promise
->MaybeReject(NS_ERROR_FAILURE
); });
1551 return promise
.forget();
1554 constexpr auto kSkipSelfHosted
= JS::SavedFrameSelfHosted::Exclude
;
1557 void ChromeUtils::GetCallerLocation(const GlobalObject
& aGlobal
,
1558 nsIPrincipal
* aPrincipal
,
1559 JS::MutableHandle
<JSObject
*> aRetval
) {
1560 JSContext
* cx
= aGlobal
.Context();
1562 auto* principals
= nsJSPrincipals::get(aPrincipal
);
1564 JS::StackCapture
captureMode(JS::FirstSubsumedFrame(cx
, principals
));
1566 JS::Rooted
<JSObject
*> frame(cx
);
1567 if (!JS::CaptureCurrentStack(cx
, &frame
, std::move(captureMode
))) {
1568 JS_ClearPendingException(cx
);
1569 aRetval
.set(nullptr);
1573 // FirstSubsumedFrame gets us a stack which stops at the first principal which
1574 // is subsumed by the given principal. That means that we may have a lot of
1575 // privileged frames that we don't care about at the top of the stack, though.
1576 // We need to filter those out to get the frame we actually want.
1578 js::GetFirstSubsumedSavedFrame(cx
, principals
, frame
, kSkipSelfHosted
));
1582 void ChromeUtils::CreateError(const GlobalObject
& aGlobal
,
1583 const nsAString
& aMessage
,
1584 JS::Handle
<JSObject
*> aStack
,
1585 JS::MutableHandle
<JSObject
*> aRetVal
,
1587 if (aStack
&& !JS::IsMaybeWrappedSavedFrame(aStack
)) {
1588 aRv
.Throw(NS_ERROR_INVALID_ARG
);
1592 JSContext
* cx
= aGlobal
.Context();
1594 auto cleanup
= MakeScopeExit([&]() { aRv
.NoteJSContextException(cx
); });
1596 JS::Rooted
<JSObject
*> retVal(cx
);
1598 JS::Rooted
<JSString
*> fileName(cx
, JS_GetEmptyString(cx
));
1600 JS::TaggedColumnNumberOneOrigin column
;
1602 Maybe
<JSAutoRealm
> ar
;
1603 JS::Rooted
<JSObject
*> stack(cx
);
1605 stack
= UncheckedUnwrap(aStack
);
1606 ar
.emplace(cx
, stack
);
1608 JSPrincipals
* principals
=
1609 JS::GetRealmPrincipals(js::GetContextRealm(cx
));
1610 if (JS::GetSavedFrameLine(cx
, principals
, stack
, &line
) !=
1611 JS::SavedFrameResult::Ok
||
1612 JS::GetSavedFrameColumn(cx
, principals
, stack
, &column
) !=
1613 JS::SavedFrameResult::Ok
||
1614 JS::GetSavedFrameSource(cx
, principals
, stack
, &fileName
) !=
1615 JS::SavedFrameResult::Ok
) {
1620 JS::Rooted
<JSString
*> message(cx
);
1622 JS::Rooted
<JS::Value
> msgVal(cx
);
1623 if (!xpc::NonVoidStringToJsval(cx
, aMessage
, &msgVal
)) {
1626 message
= msgVal
.toString();
1629 JS::Rooted
<JS::Value
> err(cx
);
1630 if (!JS::CreateError(cx
, JSEXN_ERR
, stack
, fileName
, line
,
1631 JS::ColumnNumberOneOrigin(column
.oneOriginValue()),
1632 nullptr, message
, JS::NothingHandleValue
, &err
)) {
1636 MOZ_ASSERT(err
.isObject());
1637 retVal
= &err
.toObject();
1640 if (aStack
&& !JS_WrapObject(cx
, &retVal
)) {
1645 aRetVal
.set(retVal
);
1649 already_AddRefed
<Promise
> ChromeUtils::RequestIOActivity(GlobalObject
& aGlobal
,
1651 MOZ_ASSERT(XRE_IsParentProcess());
1652 MOZ_ASSERT(Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF
, false));
1653 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1655 RefPtr
<Promise
> domPromise
= Promise::Create(global
, aRv
);
1656 if (NS_WARN_IF(aRv
.Failed())) {
1659 MOZ_ASSERT(domPromise
);
1660 mozilla::net::IOActivityMonitor::RequestActivities(domPromise
);
1661 return domPromise
.forget();
1665 bool ChromeUtils::HasReportingHeaderForOrigin(GlobalObject
& global
,
1666 const nsAString
& aOrigin
,
1668 if (!XRE_IsParentProcess()) {
1669 aRv
.Throw(NS_ERROR_FAILURE
);
1673 return ReportingHeader::HasReportingHeaderForOrigin(
1674 NS_ConvertUTF16toUTF8(aOrigin
));
1678 PopupBlockerState
ChromeUtils::GetPopupControlState(GlobalObject
& aGlobal
) {
1679 switch (PopupBlocker::GetPopupControlState()) {
1680 case PopupBlocker::PopupControlState::openAllowed
:
1681 return PopupBlockerState::OpenAllowed
;
1683 case PopupBlocker::PopupControlState::openControlled
:
1684 return PopupBlockerState::OpenControlled
;
1686 case PopupBlocker::PopupControlState::openBlocked
:
1687 return PopupBlockerState::OpenBlocked
;
1689 case PopupBlocker::PopupControlState::openAbused
:
1690 return PopupBlockerState::OpenAbused
;
1692 case PopupBlocker::PopupControlState::openOverridden
:
1693 return PopupBlockerState::OpenOverridden
;
1697 "PopupBlocker::PopupControlState and PopupBlockerState are out of "
1703 double ChromeUtils::LastExternalProtocolIframeAllowed(GlobalObject
& aGlobal
) {
1704 TimeStamp when
= PopupBlocker::WhenLastExternalProtocolIframeAllowed();
1705 if (when
.IsNull()) {
1709 TimeDuration duration
= TimeStamp::Now() - when
;
1710 return duration
.ToMilliseconds();
1714 void ChromeUtils::ResetLastExternalProtocolIframeAllowed(
1715 GlobalObject
& aGlobal
) {
1716 PopupBlocker::ResetLastExternalProtocolIframeAllowed();
1720 void ChromeUtils::EndWheelTransaction(GlobalObject
& aGlobal
) {
1721 // This allows us to end the current wheel transaction from the browser
1722 // chrome. We do not need to perform any checks before calling
1723 // EndTransaction(), as it should do nothing in the case that there is
1724 // no current wheel transaction.
1725 WheelTransaction::EndTransaction();
1729 void ChromeUtils::RegisterWindowActor(const GlobalObject
& aGlobal
,
1730 const nsACString
& aName
,
1731 const WindowActorOptions
& aOptions
,
1733 MOZ_ASSERT(XRE_IsParentProcess());
1735 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1736 service
->RegisterWindowActor(aName
, aOptions
, aRv
);
1740 void ChromeUtils::UnregisterWindowActor(const GlobalObject
& aGlobal
,
1741 const nsACString
& aName
) {
1742 MOZ_ASSERT(XRE_IsParentProcess());
1744 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1745 service
->UnregisterWindowActor(aName
);
1749 void ChromeUtils::RegisterProcessActor(const GlobalObject
& aGlobal
,
1750 const nsACString
& aName
,
1751 const ProcessActorOptions
& aOptions
,
1753 MOZ_ASSERT(XRE_IsParentProcess());
1755 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1756 service
->RegisterProcessActor(aName
, aOptions
, aRv
);
1760 void ChromeUtils::UnregisterProcessActor(const GlobalObject
& aGlobal
,
1761 const nsACString
& aName
) {
1762 MOZ_ASSERT(XRE_IsParentProcess());
1764 RefPtr
<JSActorService
> service
= JSActorService::GetSingleton();
1765 service
->UnregisterProcessActor(aName
);
1769 bool ChromeUtils::IsClassifierBlockingErrorCode(GlobalObject
& aGlobal
,
1771 return net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
1772 static_cast<nsresult
>(aError
));
1776 void ChromeUtils::PrivateNoteIntentionalCrash(const GlobalObject
& aGlobal
,
1777 ErrorResult
& aError
) {
1778 if (XRE_IsContentProcess()) {
1779 NoteIntentionalCrash("tab");
1782 aError
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
1786 nsIDOMProcessChild
* ChromeUtils::GetDomProcessChild(const GlobalObject
&) {
1787 return nsIDOMProcessChild::GetSingleton();
1791 void ChromeUtils::GetAllDOMProcesses(
1792 GlobalObject
& aGlobal
, nsTArray
<RefPtr
<nsIDOMProcessParent
>>& aParents
,
1794 if (!XRE_IsParentProcess()) {
1795 aRv
.ThrowNotAllowedError(
1796 "getAllDOMProcesses() may only be called in the parent process");
1800 // Always add the parent process nsIDOMProcessParent first
1801 aParents
.AppendElement(InProcessParent::Singleton());
1803 // Before adding nsIDOMProcessParent for all the content processes
1804 for (auto* cp
: ContentParent::AllProcesses(ContentParent::eLive
)) {
1805 aParents
.AppendElement(cp
);
1810 void ChromeUtils::ConsumeInteractionData(
1811 GlobalObject
& aGlobal
, Record
<nsString
, InteractionData
>& aInteractions
,
1813 if (!XRE_IsParentProcess()) {
1814 aRv
.ThrowNotAllowedError(
1815 "consumeInteractionData() may only be called in the parent "
1819 EventStateManager::ConsumeInteractionData(aInteractions
);
1822 already_AddRefed
<Promise
> ChromeUtils::CollectScrollingData(
1823 GlobalObject
& aGlobal
, ErrorResult
& aRv
) {
1824 // Creating a JS promise
1825 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
1828 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
1833 RefPtr
<ScrollingMetrics::ScrollingMetricsPromise
> extPromise
=
1834 ScrollingMetrics::CollectScrollingMetrics();
1837 GetCurrentSerialEventTarget(), __func__
,
1838 [promise
](const std::tuple
<uint32_t, uint32_t>& aResult
) {
1839 InteractionData out
= {};
1840 out
.mInteractionTimeInMilliseconds
= std::get
<0>(aResult
);
1841 out
.mScrollingDistanceInPixels
= std::get
<1>(aResult
);
1842 promise
->MaybeResolve(out
);
1844 [promise
](bool aValue
) { promise
->MaybeReject(NS_ERROR_FAILURE
); });
1846 return promise
.forget();
1850 void ChromeUtils::GetFormAutofillConfidences(
1851 GlobalObject
& aGlobal
, const Sequence
<OwningNonNull
<Element
>>& aElements
,
1852 nsTArray
<FormAutofillConfidences
>& aResults
, ErrorResult
& aRv
) {
1853 FormAutofillNative::GetFormAutofillConfidences(aGlobal
, aElements
, aResults
,
1857 bool ChromeUtils::IsDarkBackground(GlobalObject
&, Element
& aElement
) {
1858 nsIFrame
* f
= aElement
.GetPrimaryFrame(FlushType::Frames
);
1862 return nsNativeTheme::IsDarkBackground(f
);
1865 double ChromeUtils::DateNow(GlobalObject
&) { return JS_Now() / 1000.0; }
1868 void ChromeUtils::EnsureJSOracleStarted(GlobalObject
&) {
1869 if (StaticPrefs::browser_opaqueResponseBlocking_javascriptValidator()) {
1870 JSOracleParent::WithJSOracle([](JSOracleParent
* aParent
) {});
1875 unsigned ChromeUtils::AliveUtilityProcesses(const GlobalObject
&) {
1876 const auto& utilityProcessManager
=
1877 mozilla::ipc::UtilityProcessManager::GetIfExists();
1878 return utilityProcessManager
? utilityProcessManager
->AliveProcesses() : 0;
1882 void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject
& aGlobal
,
1883 nsTArray
<nsCString
>& aNames
) {
1885 for (size_t i
= 0; i
< WebIDLUtilityActorNameValues::Count
; ++i
) {
1886 auto idlName
= static_cast<UtilityActorName
>(i
);
1887 aNames
.AppendElement(WebIDLUtilityActorNameValues::GetString(idlName
));
1892 bool ChromeUtils::ShouldResistFingerprinting(GlobalObject
& aGlobal
,
1893 JSRFPTarget aTarget
) {
1896 case JSRFPTarget::RoundWindowSize
:
1897 target
= RFPTarget::RoundWindowSize
;
1899 case JSRFPTarget::SiteSpecificZoom
:
1900 target
= RFPTarget::SiteSpecificZoom
;
1903 MOZ_CRASH("Unhandled JSRFPTarget enum value");
1906 return nsRFPService::IsRFPEnabledFor(target
);
1909 std::atomic
<uint32_t> ChromeUtils::sDevToolsOpenedCount
= 0;
1912 bool ChromeUtils::IsDevToolsOpened() {
1913 return ChromeUtils::sDevToolsOpenedCount
> 0;
1917 bool ChromeUtils::IsDevToolsOpened(GlobalObject
& aGlobal
) {
1918 return ChromeUtils::IsDevToolsOpened();
1922 void ChromeUtils::NotifyDevToolsOpened(GlobalObject
& aGlobal
) {
1923 ChromeUtils::sDevToolsOpenedCount
++;
1927 void ChromeUtils::NotifyDevToolsClosed(GlobalObject
& aGlobal
) {
1928 MOZ_ASSERT(ChromeUtils::sDevToolsOpenedCount
>= 1);
1929 ChromeUtils::sDevToolsOpenedCount
--;
1932 } // namespace mozilla::dom