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 "BrowserChild.h"
10 # include "mozilla/a11y/DocAccessibleChild.h"
14 #include "BrowserParent.h"
15 #include "ContentChild.h"
16 #include "EventStateManager.h"
17 #include "MMPrinter.h"
18 #include "PuppetWidget.h"
19 #include "StructuredCloneData.h"
20 #include "UnitTransforms.h"
22 #include "VRManagerChild.h"
23 #include "mozilla/Assertions.h"
24 #include "mozilla/BasePrincipal.h"
25 #include "mozilla/EventForwards.h"
26 #include "mozilla/EventListenerManager.h"
27 #include "mozilla/HoldDropJSObjects.h"
28 #include "mozilla/IMEStateManager.h"
29 #include "mozilla/LookAndFeel.h"
30 #include "mozilla/MouseEvents.h"
31 #include "mozilla/NativeKeyBindingsType.h"
32 #include "mozilla/NullPrincipal.h"
33 #include "mozilla/PresShell.h"
34 #include "mozilla/ProcessHangMonitor.h"
35 #include "mozilla/ProfilerLabels.h"
36 #include "mozilla/SchedulerGroup.h"
37 #include "mozilla/ScopeExit.h"
38 #include "mozilla/Services.h"
39 #include "mozilla/StaticPrefs_dom.h"
40 #include "mozilla/TextEvents.h"
41 #include "mozilla/ToString.h"
42 #include "mozilla/Unused.h"
43 #include "mozilla/dom/AutoPrintEventDispatcher.h"
44 #include "mozilla/dom/BrowserBridgeChild.h"
45 #include "mozilla/dom/DataTransfer.h"
46 #include "mozilla/dom/Element.h"
47 #include "mozilla/dom/Event.h"
48 #include "mozilla/dom/JSWindowActorChild.h"
49 #include "mozilla/dom/ImageDocument.h"
50 #include "mozilla/dom/LoadURIOptionsBinding.h"
51 #include "mozilla/dom/MessageManagerBinding.h"
52 #include "mozilla/dom/MouseEventBinding.h"
53 #include "mozilla/dom/Nullable.h"
54 #include "mozilla/dom/PaymentRequestChild.h"
55 #include "mozilla/dom/PBrowser.h"
56 #include "mozilla/dom/PointerEventHandler.h"
57 #include "mozilla/dom/SessionStoreUtils.h"
58 #include "mozilla/dom/SessionStoreChild.h"
59 #include "mozilla/dom/UserActivation.h"
60 #include "mozilla/dom/WindowGlobalChild.h"
61 #include "mozilla/dom/WindowProxyHolder.h"
62 #include "mozilla/gfx/CrossProcessPaint.h"
63 #include "mozilla/gfx/Matrix.h"
64 #include "mozilla/ipc/BackgroundChild.h"
65 #include "mozilla/ipc/BackgroundUtils.h"
66 #include "mozilla/ipc/PBackgroundChild.h"
67 #include "mozilla/layers/APZCCallbackHelper.h"
68 #include "mozilla/layers/TouchActionHelper.h"
69 #include "mozilla/layers/APZCTreeManagerChild.h"
70 #include "mozilla/layers/APZChild.h"
71 #include "mozilla/layers/APZEventState.h"
72 #include "mozilla/layers/CompositorBridgeChild.h"
73 #include "mozilla/layers/ContentProcessController.h"
74 #include "mozilla/layers/DoubleTapToZoom.h"
75 #include "mozilla/layers/IAPZCTreeManager.h"
76 #include "mozilla/layers/ImageBridgeChild.h"
77 #include "mozilla/layers/InputAPZContext.h"
78 #include "mozilla/layers/WebRenderLayerManager.h"
79 #include "nsBrowserStatusFilter.h"
80 #include "nsCommandParams.h"
81 #include "nsContentPermissionHelper.h"
82 #include "nsContentUtils.h"
83 #include "nsDeviceContext.h"
84 #include "nsDocShell.h"
85 #include "nsDocShellLoadState.h"
86 #include "nsExceptionHandler.h"
87 #include "nsFilePickerProxy.h"
88 #include "nsFocusManager.h"
89 #include "nsGlobalWindowOuter.h"
90 #include "nsIBaseWindow.h"
91 #include "nsIBrowserDOMWindow.h"
92 #include "nsIClassifiedChannel.h"
93 #include "nsIDocShell.h"
95 #include "nsILoadContext.h"
96 #include "nsISHEntry.h"
97 #include "nsISHistory.h"
98 #include "nsIScreenManager.h"
99 #include "nsIScriptError.h"
101 #include "nsIURIMutator.h"
102 #include "nsIWeakReferenceUtils.h"
103 #include "nsIWebBrowser.h"
104 #include "nsIWebProgress.h"
105 #include "nsLayoutUtils.h"
106 #include "nsNetUtil.h"
107 #include "nsIOpenWindowInfo.h"
108 #include "nsPIDOMWindow.h"
109 #include "nsPIWindowRoot.h"
110 #include "nsPrintfCString.h"
111 #include "nsRefreshDriver.h"
112 #include "nsThreadManager.h"
113 #include "nsThreadUtils.h"
114 #include "nsViewManager.h"
115 #include "nsWebBrowser.h"
116 #include "nsWindowWatcher.h"
117 #include "nsIXULRuntime.h"
120 # include "nsAppRunner.h"
124 # include "mozilla/layout/RemotePrintJobChild.h"
125 # include "nsIPrintSettings.h"
126 # include "nsIPrintSettingsService.h"
127 # include "nsIWebBrowserPrint.h"
130 static mozilla::LazyLogModule
sApzChildLog("apz.child");
132 using namespace mozilla
;
133 using namespace mozilla::dom
;
134 using namespace mozilla::dom::ipc
;
135 using namespace mozilla::ipc
;
136 using namespace mozilla::layers
;
137 using namespace mozilla::layout
;
138 using namespace mozilla::widget
;
139 using mozilla::layers::GeckoContentController
;
141 static const char BEFORE_FIRST_PAINT
[] = "before-first-paint";
143 static uint32_t sConsecutiveTouchMoveCount
= 0;
145 using BrowserChildMap
= nsTHashMap
<nsUint64HashKey
, BrowserChild
*>;
146 static BrowserChildMap
* sBrowserChildren
;
147 StaticMutex sBrowserChildrenMutex
;
149 already_AddRefed
<Document
> BrowserChild::GetTopLevelDocument() const {
150 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
151 nsCOMPtr
<Document
> doc
= docShell
? docShell
->GetExtantDocument() : nullptr;
155 PresShell
* BrowserChild::GetTopLevelPresShell() const {
156 if (RefPtr
<Document
> doc
= GetTopLevelDocument()) {
157 return doc
->GetPresShell();
162 bool BrowserChild::UpdateFrame(const RepaintRequest
& aRequest
) {
163 MOZ_ASSERT(aRequest
.GetScrollId() != ScrollableLayerGuid::NULL_SCROLL_ID
);
165 if (aRequest
.IsRootContent()) {
166 if (PresShell
* presShell
= GetTopLevelPresShell()) {
167 // Guard against stale updates (updates meant for a pres shell which
168 // has since been torn down and destroyed).
169 if (aRequest
.GetPresShellId() == presShell
->GetPresShellId()) {
170 APZCCallbackHelper::UpdateRootFrame(aRequest
);
175 // aRequest.mIsRoot is false, so we are trying to update a subframe.
176 // This requires special handling.
177 APZCCallbackHelper::UpdateSubFrame(aRequest
);
183 class BrowserChild::DelayedDeleteRunnable final
: public Runnable
,
184 public nsIRunnablePriority
{
185 RefPtr
<BrowserChild
> mBrowserChild
;
187 // In order to try that this runnable runs after everything that could
188 // possibly touch this tab, we send it through the event queue twice.
189 bool mReadyToDelete
= false;
192 explicit DelayedDeleteRunnable(BrowserChild
* aBrowserChild
)
193 : Runnable("BrowserChild::DelayedDeleteRunnable"),
194 mBrowserChild(aBrowserChild
) {
195 MOZ_ASSERT(NS_IsMainThread());
196 MOZ_ASSERT(aBrowserChild
);
199 NS_DECL_ISUPPORTS_INHERITED
202 ~DelayedDeleteRunnable() {
203 MOZ_ASSERT(NS_IsMainThread());
204 MOZ_ASSERT(!mBrowserChild
);
207 NS_IMETHOD
GetPriority(uint32_t* aPriority
) override
{
208 *aPriority
= nsIRunnablePriority::PRIORITY_NORMAL
;
214 MOZ_ASSERT(NS_IsMainThread());
215 MOZ_ASSERT(mBrowserChild
);
217 if (!mReadyToDelete
) {
218 // This time run this runnable at input priority.
219 mReadyToDelete
= true;
220 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(this));
224 // Check in case ActorDestroy was called after RecvDestroy message.
225 if (mBrowserChild
->IPCOpen()) {
226 Unused
<< PBrowserChild::Send__delete__(mBrowserChild
);
229 mBrowserChild
= nullptr;
234 NS_IMPL_ISUPPORTS_INHERITED(BrowserChild::DelayedDeleteRunnable
, Runnable
,
238 std::map
<TabId
, RefPtr
<BrowserChild
>>& NestedBrowserChildMap() {
239 MOZ_ASSERT(NS_IsMainThread());
240 static std::map
<TabId
, RefPtr
<BrowserChild
>> sNestedBrowserChildMap
;
241 return sNestedBrowserChildMap
;
245 already_AddRefed
<BrowserChild
> BrowserChild::FindBrowserChild(
246 const TabId
& aTabId
) {
247 auto iter
= NestedBrowserChildMap().find(aTabId
);
248 if (iter
== NestedBrowserChildMap().end()) {
251 RefPtr
<BrowserChild
> browserChild
= iter
->second
;
252 return browserChild
.forget();
256 already_AddRefed
<BrowserChild
> BrowserChild::Create(
257 ContentChild
* aManager
, const TabId
& aTabId
, const TabContext
& aContext
,
258 BrowsingContext
* aBrowsingContext
, uint32_t aChromeFlags
,
260 RefPtr
<BrowserChild
> iframe
= new BrowserChild(
261 aManager
, aTabId
, aContext
, aBrowsingContext
, aChromeFlags
, aIsTopLevel
);
262 return iframe
.forget();
265 BrowserChild::BrowserChild(ContentChild
* aManager
, const TabId
& aTabId
,
266 const TabContext
& aContext
,
267 BrowsingContext
* aBrowsingContext
,
268 uint32_t aChromeFlags
, bool aIsTopLevel
)
269 : TabContext(aContext
),
270 mBrowserChildMessageManager(nullptr),
272 mBrowsingContext(aBrowsingContext
),
273 mChromeFlags(aChromeFlags
),
276 mEffectsInfo
{EffectsInfo::FullyHidden()},
277 mDynamicToolbarMaxHeight(0),
280 mTriedBrowserInit(false),
281 mIgnoreKeyPressEvent(false),
282 mHasValidInnerSize(false),
284 mIsTopLevel(aIsTopLevel
),
285 mIsTransparent(false),
287 mDidSetRealShowInfo(false),
288 mDidLoadURLInit(false),
289 mSkipKeyPress(false),
290 mShouldSendWebProgressEventsToParent(false),
292 mIsPreservingLayers(false),
293 #if defined(XP_WIN) && defined(ACCESSIBILITY)
294 mNativeWindowHandle(0),
296 mCancelContentJSEpoch(0) {
297 mozilla::HoldJSObjects(this);
299 // preloaded BrowserChild should not be added to child map
301 MOZ_ASSERT(NestedBrowserChildMap().find(mUniqueId
) ==
302 NestedBrowserChildMap().end());
303 NestedBrowserChildMap()[mUniqueId
] = this;
305 mCoalesceMouseMoveEvents
= StaticPrefs::dom_events_coalesce_mousemove();
306 if (mCoalesceMouseMoveEvents
) {
307 mCoalescedMouseEventFlusher
= new CoalescedMouseMoveFlusher(this);
310 if (StaticPrefs::dom_events_coalesce_touchmove()) {
311 mCoalescedTouchMoveEventFlusher
= new CoalescedTouchMoveFlusher(this);
315 const CompositorOptions
& BrowserChild::GetCompositorOptions() const {
316 // If you're calling this before mCompositorOptions is set, well.. don't.
317 MOZ_ASSERT(mCompositorOptions
);
318 return mCompositorOptions
.ref();
321 bool BrowserChild::AsyncPanZoomEnabled() const {
322 // This might get called by the TouchEvent::PrefEnabled code before we have
323 // mCompositorOptions populated (bug 1370089). In that case we just assume
324 // APZ is enabled because we're in a content process (because BrowserChild)
325 // and APZ is probably going to be enabled here since e10s is enabled.
326 return mCompositorOptions
? mCompositorOptions
->UseAPZ() : true;
330 BrowserChild::Observe(nsISupports
* aSubject
, const char* aTopic
,
331 const char16_t
* aData
) {
332 if (!strcmp(aTopic
, BEFORE_FIRST_PAINT
)) {
333 if (AsyncPanZoomEnabled()) {
334 nsCOMPtr
<Document
> subject(do_QueryInterface(aSubject
));
335 nsCOMPtr
<Document
> doc(GetTopLevelDocument());
337 if (subject
== doc
) {
338 RefPtr
<PresShell
> presShell
= doc
->GetPresShell();
340 presShell
->SetIsFirstPaint(true);
343 APZCCallbackHelper::InitializeRootDisplayport(presShell
);
351 void BrowserChild::ContentReceivedInputBlock(uint64_t aInputBlockId
,
352 bool aPreventDefault
) const {
353 if (mApzcTreeManager
) {
354 mApzcTreeManager
->ContentReceivedInputBlock(aInputBlockId
, aPreventDefault
);
358 void BrowserChild::SetTargetAPZC(
359 uint64_t aInputBlockId
,
360 const nsTArray
<ScrollableLayerGuid
>& aTargets
) const {
361 if (mApzcTreeManager
) {
362 mApzcTreeManager
->SetTargetAPZC(aInputBlockId
, aTargets
);
366 bool BrowserChild::DoUpdateZoomConstraints(
367 const uint32_t& aPresShellId
, const ViewID
& aViewId
,
368 const Maybe
<ZoomConstraints
>& aConstraints
) {
369 if (!mApzcTreeManager
|| mDestroyed
) {
373 ScrollableLayerGuid guid
=
374 ScrollableLayerGuid(mLayersId
, aPresShellId
, aViewId
);
376 mApzcTreeManager
->UpdateZoomConstraints(guid
, aConstraints
);
380 nsresult
BrowserChild::Init(mozIDOMWindowProxy
* aParent
,
381 WindowGlobalChild
* aInitialWindowChild
) {
382 MOZ_ASSERT_IF(aInitialWindowChild
,
383 aInitialWindowChild
->BrowsingContext() == mBrowsingContext
);
385 nsCOMPtr
<nsIWidget
> widget
= nsIWidget::CreatePuppetWidget(this);
386 mPuppetWidget
= static_cast<PuppetWidget
*>(widget
.get());
387 if (!mPuppetWidget
) {
388 NS_ERROR("couldn't create fake widget");
389 return NS_ERROR_FAILURE
;
391 mPuppetWidget
->InfallibleCreate(nullptr,
392 nullptr, // no parents
393 LayoutDeviceIntRect(0, 0, 0, 0),
394 nullptr); // HandleWidgetEvent
396 mWebBrowser
= nsWebBrowser::Create(this, mPuppetWidget
, mBrowsingContext
,
397 aInitialWindowChild
);
398 nsIWebBrowser
* webBrowser
= mWebBrowser
;
400 mWebNav
= do_QueryInterface(webBrowser
);
401 NS_ASSERTION(mWebNav
, "nsWebBrowser doesn't implement nsIWebNavigation?");
403 // IPC uses a WebBrowser object for which DNS prefetching is turned off
404 // by default. But here we really want it, so enable it explicitly
405 mWebBrowser
->SetAllowDNSPrefetch(true);
407 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
408 MOZ_ASSERT(docShell
);
410 mStatusFilter
= new nsBrowserStatusFilter();
413 mStatusFilter
->AddProgressListener(this, nsIWebProgress::NOTIFY_ALL
);
414 NS_ENSURE_SUCCESS(rv
, rv
);
417 nsCOMPtr
<nsIWebProgress
> webProgress
= do_QueryInterface(docShell
);
418 rv
= webProgress
->AddProgressListener(mStatusFilter
,
419 nsIWebProgress::NOTIFY_ALL
);
420 NS_ENSURE_SUCCESS(rv
, rv
);
424 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(WebNavigation());
425 MOZ_ASSERT(loadContext
);
426 MOZ_ASSERT(loadContext
->UseRemoteTabs() ==
427 !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
));
428 MOZ_ASSERT(loadContext
->UseRemoteSubframes() ==
429 !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
));
430 #endif // defined(DEBUG)
432 // Few lines before, baseWindow->Create() will end up creating a new
433 // window root in nsGlobalWindowOuter::SetDocShell.
434 // Then this chrome event handler, will be inherited to inner windows.
435 // We want to also set it to the docshell so that inner windows
436 // and any code that has access to the docshell
437 // can all listen to the same chrome event handler.
438 // XXX: ideally, we would set a chrome event handler earlier,
439 // and all windows, even the root one, will use the docshell one.
440 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
441 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
442 nsCOMPtr
<EventTarget
> chromeHandler
= window
->GetChromeEventHandler();
443 docShell
->SetChromeEventHandler(chromeHandler
);
445 // Window scrollbar flags only affect top level remote frames, not fission
448 nsContentUtils::SetScrollbarsVisibility(
449 docShell
, !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_SCROLLBARS
));
452 nsWeakPtr weakPtrThis
= do_GetWeakReference(
453 static_cast<nsIBrowserChild
*>(this)); // for capture by the lambda
454 ContentReceivedInputBlockCallback
callback(
455 [weakPtrThis
](uint64_t aInputBlockId
, bool aPreventDefault
) {
456 if (nsCOMPtr
<nsIBrowserChild
> browserChild
=
457 do_QueryReferent(weakPtrThis
)) {
458 static_cast<BrowserChild
*>(browserChild
.get())
459 ->ContentReceivedInputBlock(aInputBlockId
, aPreventDefault
);
462 mAPZEventState
= new APZEventState(mPuppetWidget
, std::move(callback
));
466 if (SessionStorePlatformCollection()) {
467 mSessionStoreChild
= SessionStoreChild::GetOrCreate(mBrowsingContext
);
470 // We've all set up, make sure our visibility state is consistent. This is
471 // important for OOP iframes, which start off as hidden.
477 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChild
)
479 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild
)
480 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChildMessageManager
)
481 tmp
->nsMessageManagerScriptExecutor::Unlink();
482 NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter
)
483 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav
)
484 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext
)
485 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChild
)
486 NS_IMPL_CYCLE_COLLECTION_UNLINK(mContentTransformPromise
)
487 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
488 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
490 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild
)
491 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChildMessageManager
)
492 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter
)
493 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav
)
494 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext
)
495 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChild
)
496 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentTransformPromise
)
497 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
499 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild
)
500 tmp
->nsMessageManagerScriptExecutor::Trace(aCallbacks
, aClosure
);
501 NS_IMPL_CYCLE_COLLECTION_TRACE_END
503 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild
)
504 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome
)
505 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus
)
506 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
507 NS_INTERFACE_MAP_ENTRY(nsIWindowProvider
)
508 NS_INTERFACE_MAP_ENTRY(nsIBrowserChild
)
509 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
510 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
511 NS_INTERFACE_MAP_ENTRY(nsITooltipListener
)
512 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener
)
513 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener2
)
514 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIBrowserChild
)
517 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserChild
)
518 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserChild
)
521 BrowserChild::GetChromeFlags(uint32_t* aChromeFlags
) {
522 *aChromeFlags
= mChromeFlags
;
527 BrowserChild::SetChromeFlags(uint32_t aChromeFlags
) {
528 NS_WARNING("trying to SetChromeFlags from content process?");
530 return NS_ERROR_NOT_IMPLEMENTED
;
534 BrowserChild::RemoteDropLinks(
535 const nsTArray
<RefPtr
<nsIDroppedLinkItem
>>& aLinks
) {
536 nsTArray
<nsString
> linksArray
;
538 for (nsIDroppedLinkItem
* link
: aLinks
) {
540 rv
= link
->GetUrl(tmp
);
544 linksArray
.AppendElement(tmp
);
546 rv
= link
->GetName(tmp
);
550 linksArray
.AppendElement(tmp
);
552 rv
= link
->GetType(tmp
);
556 linksArray
.AppendElement(tmp
);
558 bool sent
= SendDropLinks(linksArray
);
560 return sent
? NS_OK
: NS_ERROR_FAILURE
;
564 BrowserChild::ShowAsModal() {
565 NS_WARNING("BrowserChild::ShowAsModal not supported in BrowserChild");
567 return NS_ERROR_NOT_IMPLEMENTED
;
571 BrowserChild::IsWindowModal(bool* aRetVal
) {
577 BrowserChild::SetLinkStatus(const nsAString
& aStatusText
) {
578 // We can only send the status after the ipc machinery is set up
580 SendSetLinkStatus(aStatusText
);
586 BrowserChild::SetDimensions(DimensionRequest
&& aRequest
) {
587 // The parent is in charge of the dimension changes. If JS code wants to
588 // change the dimensions (moveTo, screenX, etc.) we send a message to the
589 // parent about the new requested dimension, the parent does the resize/move
590 // then send a message to the child to update itself. For APIs like screenX
591 // this function is called with only the changed values. In a series of calls
592 // like window.screenX = 10; window.screenY = 10; for the second call, since
593 // screenX is not yet updated we might accidentally reset back screenX to it's
594 // old value. To avoid this, if a parameter did not change, we want the parent
595 // to handle the unchanged values.
597 double scale
= mPuppetWidget
? mPuppetWidget
->GetDefaultScale().scale
: 1.0;
598 SendSetDimensions(aRequest
, scale
);
603 BrowserChild::GetDimensions(DimensionKind aDimensionKind
, int32_t* aX
,
604 int32_t* aY
, int32_t* aCx
, int32_t* aCy
) {
605 ScreenIntRect rect
= GetOuterRect();
606 if (aDimensionKind
== DimensionKind::Inner
) {
608 return NS_ERROR_NOT_IMPLEMENTED
;
610 rect
.SizeTo(GetInnerSize());
628 BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED
; }
631 BrowserChild::FocusNextElement(bool aForDocumentNavigation
) {
632 SendMoveFocus(true, aForDocumentNavigation
);
637 BrowserChild::FocusPrevElement(bool aForDocumentNavigation
) {
638 SendMoveFocus(false, aForDocumentNavigation
);
643 BrowserChild::GetInterface(const nsIID
& aIID
, void** aSink
) {
644 // XXXbz should we restrict the set of interfaces we hand out here?
646 return QueryInterface(aIID
, aSink
);
650 BrowserChild::ProvideWindow(nsIOpenWindowInfo
* aOpenWindowInfo
,
651 uint32_t aChromeFlags
, bool aCalledFromJS
,
652 nsIURI
* aURI
, const nsAString
& aName
,
653 const nsACString
& aFeatures
,
654 const UserActivation::Modifiers
& aModifiers
,
655 bool aForceNoOpener
, bool aForceNoReferrer
,
656 bool aIsPopupRequested
,
657 nsDocShellLoadState
* aLoadState
, bool* aWindowIsNew
,
658 BrowsingContext
** aReturn
) {
661 RefPtr
<BrowsingContext
> parent
= aOpenWindowInfo
->GetParent();
663 int32_t openLocation
= nsWindowWatcher::GetWindowOpenLocation(
664 parent
->GetDOMWindow(), aChromeFlags
, aModifiers
, aCalledFromJS
,
665 aOpenWindowInfo
->GetIsForPrinting());
667 // If it turns out we're opening in the current browser, just hand over the
668 // current browser's docshell.
669 if (openLocation
== nsIBrowserDOMWindow::OPEN_CURRENTWINDOW
) {
670 nsCOMPtr
<nsIWebBrowser
> browser
= do_GetInterface(WebNavigation());
671 *aWindowIsNew
= false;
673 nsCOMPtr
<mozIDOMWindowProxy
> win
;
674 MOZ_TRY(browser
->GetContentDOMWindow(getter_AddRefs(win
)));
676 RefPtr
<BrowsingContext
> bc(
677 nsPIDOMWindowOuter::From(win
)->GetBrowsingContext());
682 // Note that ProvideWindowCommon may return NS_ERROR_ABORT if the
683 // open window call was canceled. It's important that we pass this error
684 // code back to our caller.
685 ContentChild
* cc
= ContentChild::GetSingleton();
686 return cc
->ProvideWindowCommon(
687 WrapNotNull(this), aOpenWindowInfo
, aChromeFlags
, aCalledFromJS
, aURI
,
688 aName
, aFeatures
, aModifiers
, aForceNoOpener
, aForceNoReferrer
,
689 aIsPopupRequested
, aLoadState
, aWindowIsNew
, aReturn
);
692 void BrowserChild::DestroyWindow() {
693 mBrowsingContext
= nullptr;
696 if (nsCOMPtr
<nsIWebProgress
> webProgress
=
697 do_QueryInterface(WebNavigation())) {
698 webProgress
->RemoveProgressListener(mStatusFilter
);
701 mStatusFilter
->RemoveProgressListener(this);
702 mStatusFilter
= nullptr;
705 if (mCoalescedMouseEventFlusher
) {
706 mCoalescedMouseEventFlusher
->RemoveObserver();
707 mCoalescedMouseEventFlusher
= nullptr;
710 if (mCoalescedTouchMoveEventFlusher
) {
711 mCoalescedTouchMoveEventFlusher
->RemoveObserver();
712 mCoalescedTouchMoveEventFlusher
= nullptr;
715 if (mSessionStoreChild
) {
716 mSessionStoreChild
->Stop();
717 mSessionStoreChild
= nullptr;
720 // In case we don't have chance to process all entries, clean all data in
722 while (mToBeDispatchedMouseData
.GetSize() > 0) {
723 UniquePtr
<CoalescedMouseData
> data(
724 static_cast<CoalescedMouseData
*>(mToBeDispatchedMouseData
.PopFront()));
728 nsCOMPtr
<nsIBaseWindow
> baseWindow
= do_QueryInterface(WebNavigation());
729 if (baseWindow
) baseWindow
->Destroy();
732 mPuppetWidget
->Destroy();
735 mLayersConnected
= Nothing();
737 if (mLayersId
.IsValid()) {
738 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
740 MOZ_ASSERT(sBrowserChildren
);
741 sBrowserChildren
->Remove(uint64_t(mLayersId
));
742 if (!sBrowserChildren
->Count()) {
743 delete sBrowserChildren
;
744 sBrowserChildren
= nullptr;
746 mLayersId
= layers::LayersId
{0};
749 if (mAPZEventState
) {
750 mAPZEventState
->Destroy();
751 mAPZEventState
= nullptr;
755 void BrowserChild::ActorDestroy(ActorDestroyReason why
) {
760 if (mBrowserChildMessageManager
) {
761 // We should have a message manager if the global is alive, but it
762 // seems sometimes we don't. Assert in aurora/nightly, but don't
763 // crash in release builds.
764 MOZ_DIAGNOSTIC_ASSERT(mBrowserChildMessageManager
->GetMessageManager());
765 if (mBrowserChildMessageManager
->GetMessageManager()) {
766 // The messageManager relays messages via the BrowserChild which
768 mBrowserChildMessageManager
->DisconnectMessageManager();
772 if (GetTabId() != 0) {
773 NestedBrowserChildMap().erase(GetTabId());
777 BrowserChild::~BrowserChild() {
778 mAnonymousGlobalScopes
.Clear();
782 nsCOMPtr
<nsIWebBrowser
> webBrowser
= do_QueryInterface(WebNavigation());
784 webBrowser
->SetContainerWindow(nullptr);
787 mozilla::DropJSObjects(this);
790 mozilla::ipc::IPCResult
BrowserChild::RecvWillChangeProcess() {
792 mWebBrowser
->SetWillChangeProcess();
797 mozilla::ipc::IPCResult
BrowserChild::RecvLoadURL(
798 nsDocShellLoadState
* aLoadState
, const ParentShowInfo
& aInfo
) {
799 if (!mDidLoadURLInit
) {
800 mDidLoadURLInit
= true;
801 if (!InitBrowserChildMessageManager()) {
802 return IPC_FAIL_NO_REASON(this);
805 ApplyParentShowInfo(aInfo
);
808 aLoadState
->URI()->GetSpec(spec
);
810 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
812 NS_WARNING("WebNavigation does not have a docshell");
815 docShell
->LoadURI(aLoadState
, true);
817 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL
,
822 mozilla::ipc::IPCResult
BrowserChild::RecvCreateAboutBlankDocumentViewer(
823 nsIPrincipal
* aPrincipal
, nsIPrincipal
* aPartitionedPrincipal
) {
824 if (aPrincipal
->GetIsExpandedPrincipal() ||
825 aPartitionedPrincipal
->GetIsExpandedPrincipal()) {
826 return IPC_FAIL(this, "Cannot create document with an expanded principal");
828 if (aPrincipal
->IsSystemPrincipal() ||
829 aPartitionedPrincipal
->IsSystemPrincipal()) {
830 MOZ_ASSERT_UNREACHABLE(
831 "Cannot use CreateAboutBlankDocumentViewer to create system principal "
832 "document in content");
836 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
838 MOZ_ASSERT_UNREACHABLE("WebNavigation does not have a docshell");
842 nsCOMPtr
<nsIURI
> currentURI
;
844 WebNavigation()->GetCurrentURI(getter_AddRefs(currentURI
)));
845 if (!currentURI
|| !NS_IsAboutBlank(currentURI
)) {
846 NS_WARNING("Can't create a ContentViewer unless on about:blank");
850 docShell
->CreateAboutBlankDocumentViewer(aPrincipal
, aPartitionedPrincipal
,
855 mozilla::ipc::IPCResult
BrowserChild::RecvResumeLoad(
856 const uint64_t& aPendingSwitchID
, const ParentShowInfo
& aInfo
) {
857 if (!mDidLoadURLInit
) {
858 mDidLoadURLInit
= true;
859 if (!InitBrowserChildMessageManager()) {
860 return IPC_FAIL_NO_REASON(this);
863 ApplyParentShowInfo(aInfo
);
866 nsresult rv
= WebNavigation()->ResumeRedirectedLoad(aPendingSwitchID
, -1);
868 NS_WARNING("WebNavigation()->ResumeRedirectedLoad failed");
874 nsresult
BrowserChild::CloneDocumentTreeIntoSelf(
875 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
876 const embedding::PrintData
& aPrintData
) {
878 if (NS_WARN_IF(aSourceBC
.IsNullOrDiscarded())) {
879 return NS_ERROR_FAILURE
;
881 nsCOMPtr
<Document
> sourceDocument
= aSourceBC
.get()->GetDocument();
882 if (NS_WARN_IF(!sourceDocument
)) {
883 return NS_ERROR_FAILURE
;
886 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
887 if (NS_WARN_IF(!ourDocShell
)) {
888 return NS_ERROR_FAILURE
;
891 nsCOMPtr
<nsIDocumentViewer
> viewer
;
892 ourDocShell
->GetDocViewer(getter_AddRefs(viewer
));
893 if (NS_WARN_IF(!viewer
)) {
894 return NS_ERROR_FAILURE
;
897 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
898 do_GetService("@mozilla.org/gfx/printsettings-service;1");
899 if (NS_WARN_IF(!printSettingsSvc
)) {
900 return NS_ERROR_FAILURE
;
903 nsCOMPtr
<nsIPrintSettings
> printSettings
;
905 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
906 if (NS_WARN_IF(NS_FAILED(rv
))) {
910 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
912 RefPtr
<Document
> clone
;
914 AutoPrintEventDispatcher
dispatcher(*sourceDocument
);
915 nsAutoScriptBlocker scriptBlocker
;
916 bool hasInProcessCallbacks
= false;
917 clone
= sourceDocument
->CreateStaticClone(
918 ourDocShell
, viewer
, printSettings
, &hasInProcessCallbacks
);
919 if (NS_WARN_IF(!clone
)) {
920 return NS_ERROR_FAILURE
;
924 rv
= UpdateRemotePrintSettings(aPrintData
);
933 mozilla::ipc::IPCResult
BrowserChild::RecvCloneDocumentTreeIntoSelf(
934 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
935 const embedding::PrintData
& aPrintData
,
936 CloneDocumentTreeIntoSelfResolver
&& aResolve
) {
940 rv
= CloneDocumentTreeIntoSelf(aSourceBC
, aPrintData
);
943 aResolve(NS_SUCCEEDED(rv
));
947 nsresult
BrowserChild::UpdateRemotePrintSettings(
948 const embedding::PrintData
& aPrintData
) {
950 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
951 if (NS_WARN_IF(!ourDocShell
)) {
952 return NS_ERROR_FAILURE
;
955 RefPtr
<Document
> doc
= ourDocShell
->GetExtantDocument();
956 if (NS_WARN_IF(!doc
) || NS_WARN_IF(!doc
->IsStaticDocument())) {
957 return NS_ERROR_FAILURE
;
960 RefPtr
<BrowsingContext
> bc
= ourDocShell
->GetBrowsingContext();
961 if (NS_WARN_IF(!bc
)) {
962 return NS_ERROR_FAILURE
;
965 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
966 do_GetService("@mozilla.org/gfx/printsettings-service;1");
967 if (NS_WARN_IF(!printSettingsSvc
)) {
968 return NS_ERROR_FAILURE
;
971 nsCOMPtr
<nsIPrintSettings
> printSettings
;
973 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
974 if (NS_WARN_IF(NS_FAILED(rv
))) {
978 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
980 bc
->PreOrderWalk([&](BrowsingContext
* aBc
) {
981 if (nsCOMPtr
<nsIDocShell
> inProcess
= aBc
->GetDocShell()) {
982 nsCOMPtr
<nsIDocumentViewer
> viewer
;
983 inProcess
->GetDocViewer(getter_AddRefs(viewer
));
984 if (NS_WARN_IF(!viewer
)) {
985 return BrowsingContext::WalkFlag::Skip
;
987 // The CanRunScript analysis is not smart enough to see across
988 // the std::function PreOrderWalk uses, so we cheat a bit here, but it is
989 // fine because PreOrderWalk does deal with arbitrary script changing the
990 // BC tree, and our code above is simple enough and keeps strong refs to
992 ([&]() MOZ_CAN_RUN_SCRIPT_BOUNDARY
{
993 RefPtr
<RemotePrintJobChild
> printJob
=
994 static_cast<RemotePrintJobChild
*>(
995 aPrintData
.remotePrintJob().AsChild());
996 viewer
->SetPrintSettingsForSubdocument(printSettings
, printJob
);
998 } else if (RefPtr
<BrowserBridgeChild
> remoteChild
=
999 BrowserBridgeChild::GetFrom(aBc
->GetEmbedderElement())) {
1000 Unused
<< remoteChild
->SendUpdateRemotePrintSettings(aPrintData
);
1001 return BrowsingContext::WalkFlag::Skip
;
1003 return BrowsingContext::WalkFlag::Next
;
1010 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemotePrintSettings(
1011 const embedding::PrintData
& aPrintData
) {
1013 UpdateRemotePrintSettings(aPrintData
);
1019 void BrowserChild::DoFakeShow(const ParentShowInfo
& aParentShowInfo
) {
1020 OwnerShowInfo ownerInfo
{ScreenIntSize(), ScrollbarPreference::Auto
,
1022 RecvShow(aParentShowInfo
, ownerInfo
);
1023 mDidFakeShow
= true;
1026 void BrowserChild::ApplyParentShowInfo(const ParentShowInfo
& aInfo
) {
1027 // Even if we already set real show info, the dpi / rounding & scale may still
1028 // be invalid (if BrowserParent wasn't able to get widget it would just send
1029 // 0). So better to always set up-to-date values here.
1030 if (aInfo
.dpi() > 0) {
1031 mPuppetWidget
->UpdateBackingScaleCache(aInfo
.dpi(), aInfo
.widgetRounding(),
1032 aInfo
.defaultScale());
1035 if (mDidSetRealShowInfo
) {
1039 if (!aInfo
.fakeShowInfo()) {
1040 // Once we've got one ShowInfo from parent, no need to update the values
1042 mDidSetRealShowInfo
= true;
1045 mIsTransparent
= aInfo
.isTransparent();
1048 mozilla::ipc::IPCResult
BrowserChild::RecvShow(
1049 const ParentShowInfo
& aParentInfo
, const OwnerShowInfo
& aOwnerInfo
) {
1052 mPuppetWidget
->SetSizeMode(aOwnerInfo
.sizeMode());
1053 if (!mDidFakeShow
) {
1054 nsCOMPtr
<nsIBaseWindow
> baseWindow
= do_QueryInterface(WebNavigation());
1056 NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
1057 return IPC_FAIL_NO_REASON(this);
1060 baseWindow
->SetVisibility(true);
1061 res
= InitBrowserChildMessageManager();
1064 ApplyParentShowInfo(aParentInfo
);
1067 RecvScrollbarPreferenceChanged(aOwnerInfo
.scrollbarPreference());
1071 return IPC_FAIL_NO_REASON(this);
1079 mozilla::ipc::IPCResult
BrowserChild::RecvInitRendering(
1080 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
1081 const layers::LayersId
& aLayersId
,
1082 const CompositorOptions
& aCompositorOptions
, const bool& aLayersConnected
) {
1083 mLayersConnected
= Some(aLayersConnected
);
1084 mLayersConnectRequested
= Some(aLayersConnected
);
1085 InitRenderingState(aTextureFactoryIdentifier
, aLayersId
, aCompositorOptions
);
1089 mozilla::ipc::IPCResult
BrowserChild::RecvScrollbarPreferenceChanged(
1090 ScrollbarPreference aPreference
) {
1091 MOZ_ASSERT(!mIsTopLevel
,
1092 "Scrollbar visibility should be derived from chrome flags for "
1093 "top-level windows");
1094 if (nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation())) {
1095 nsDocShell::Cast(docShell
)->SetScrollbarPreference(aPreference
);
1100 mozilla::ipc::IPCResult
BrowserChild::RecvCompositorOptionsChanged(
1101 const CompositorOptions
& aNewOptions
) {
1102 MOZ_ASSERT(mCompositorOptions
);
1104 // The only compositor option we currently support changing is APZ
1105 // enablement. Even that is only partially supported for now:
1106 // * Going from APZ to non-APZ is fine - we just flip the stored flag.
1107 // Note that we keep the actors (mApzcTreeManager, and the APZChild
1108 // created in InitAPZState()) around (read on for why).
1109 // * Going from non-APZ to APZ is only supported if we were using
1110 // APZ initially (at InitRendering() time) and we are transitioning
1111 // back. In this case, we just reuse the actors which we kept around.
1112 // Fully supporting a non-APZ to APZ transition (i.e. even in cases
1113 // where we initialized as non-APZ) would require setting up the actors
1114 // here. (In that case, we would also have the options of destroying
1115 // the actors in the APZ --> non-APZ case, and always re-creating them
1116 // during a non-APZ --> APZ transition).
1117 mCompositorOptions
->SetUseAPZ(aNewOptions
.UseAPZ());
1121 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateDimensions(
1122 const DimensionInfo
& aDimensionInfo
) {
1123 if (mLayersConnected
.isNothing()) {
1127 mUnscaledOuterRect
= aDimensionInfo
.rect();
1128 mClientOffset
= aDimensionInfo
.clientOffset();
1129 mChromeOffset
= aDimensionInfo
.chromeOffset();
1130 MOZ_ASSERT_IF(!IsTopLevel(), mChromeOffset
== LayoutDeviceIntPoint());
1132 SetUnscaledInnerSize(aDimensionInfo
.size());
1133 if (!mHasValidInnerSize
&& aDimensionInfo
.size().width
!= 0 &&
1134 aDimensionInfo
.size().height
!= 0) {
1135 mHasValidInnerSize
= true;
1138 ScreenIntSize screenSize
= GetInnerSize();
1139 ScreenIntRect screenRect
= GetOuterRect();
1141 // Make sure to set the size on the document viewer first. The
1142 // MobileViewportManager needs the content viewer size to be updated before
1143 // the reflow, otherwise it gets a stale size when it computes a new CSS
1145 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
1146 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
1147 nsIBaseWindow::eRepaint
);
1149 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
1150 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
1151 screenSize
.width
, screenSize
.height
, true);
1153 RecvSafeAreaInsetsChanged(mPuppetWidget
->GetSafeAreaInsets());
1158 mozilla::ipc::IPCResult
BrowserChild::RecvSizeModeChanged(
1159 const nsSizeMode
& aSizeMode
) {
1160 mPuppetWidget
->SetSizeMode(aSizeMode
);
1161 if (!mPuppetWidget
->IsVisible()) {
1164 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1168 nsPresContext
* presContext
= document
->GetPresContext();
1170 presContext
->SizeModeChanged(aSizeMode
);
1175 mozilla::ipc::IPCResult
BrowserChild::RecvChildToParentMatrix(
1176 const Maybe
<gfx::Matrix4x4
>& aMatrix
,
1177 const ScreenRect
& aTopLevelViewportVisibleRectInBrowserCoords
) {
1178 mChildToParentConversionMatrix
=
1179 LayoutDeviceToLayoutDeviceMatrix4x4::FromUnknownMatrix(aMatrix
);
1180 mTopLevelViewportVisibleRectInBrowserCoords
=
1181 aTopLevelViewportVisibleRectInBrowserCoords
;
1183 if (mContentTransformPromise
) {
1184 mContentTransformPromise
->MaybeResolveWithUndefined();
1185 mContentTransformPromise
= nullptr;
1188 // Trigger an intersection observation update since ancestor viewports
1190 if (RefPtr
<Document
> toplevelDoc
= GetTopLevelDocument()) {
1191 if (nsPresContext
* pc
= toplevelDoc
->GetPresContext()) {
1192 pc
->RefreshDriver()->EnsureIntersectionObservationsUpdateHappens();
1199 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemoteStyle(
1200 const StyleImageRendering
& aImageRendering
) {
1201 BrowsingContext
* context
= GetBrowsingContext();
1206 Document
* document
= context
->GetDocument();
1211 if (document
->IsImageDocument()) {
1212 document
->AsImageDocument()->UpdateRemoteStyle(aImageRendering
);
1218 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarMaxHeightChanged(
1219 const ScreenIntCoord
& aHeight
) {
1220 #if defined(MOZ_WIDGET_ANDROID)
1221 mDynamicToolbarMaxHeight
= aHeight
;
1223 RefPtr
<Document
> document
= GetTopLevelDocument();
1228 if (RefPtr
<nsPresContext
> presContext
= document
->GetPresContext()) {
1229 presContext
->SetDynamicToolbarMaxHeight(aHeight
);
1235 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarOffsetChanged(
1236 const ScreenIntCoord
& aOffset
) {
1237 #if defined(MOZ_WIDGET_ANDROID)
1238 RefPtr
<Document
> document
= GetTopLevelDocument();
1243 if (nsPresContext
* presContext
= document
->GetPresContext()) {
1244 presContext
->UpdateDynamicToolbarOffset(aOffset
);
1250 mozilla::ipc::IPCResult
BrowserChild::RecvSuppressDisplayport(
1251 const bool& aEnabled
) {
1252 if (RefPtr
<PresShell
> presShell
= GetTopLevelPresShell()) {
1253 presShell
->SuppressDisplayport(aEnabled
);
1258 void BrowserChild::HandleDoubleTap(const CSSPoint
& aPoint
,
1259 const Modifiers
& aModifiers
,
1260 const ScrollableLayerGuid
& aGuid
,
1261 const DoubleTapToZoomMetrics
& aMetrics
) {
1263 sApzChildLog
, LogLevel::Debug
,
1264 ("Handling double tap at %s with %p %p\n", ToString(aPoint
).c_str(),
1265 mBrowserChildMessageManager
? mBrowserChildMessageManager
->GetWrapper()
1267 mBrowserChildMessageManager
.get()));
1269 if (!mBrowserChildMessageManager
) {
1273 // Note: there is nothing to do with the modifiers here, as we are not
1274 // synthesizing any sort of mouse event.
1275 RefPtr
<Document
> document
= GetTopLevelDocument();
1276 ZoomTarget zoomTarget
= CalculateRectToZoomTo(document
, aPoint
, aMetrics
);
1277 // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
1278 // the guid of any scroll frame), but the zoom-to-rect operation must be
1279 // performed by the root content scroll frame, so query its identifiers
1280 // for the SendZoomToRect() call rather than using the ones from |aGuid|.
1281 uint32_t presShellId
;
1283 if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
1284 document
->GetDocumentElement(), &presShellId
, &viewId
) &&
1286 ScrollableLayerGuid
guid(mLayersId
, presShellId
, viewId
);
1288 mApzcTreeManager
->ZoomToRect(guid
, zoomTarget
,
1289 ZoomToRectBehavior::DEFAULT_BEHAVIOR
);
1293 mozilla::ipc::IPCResult
BrowserChild::RecvHandleTap(
1294 const GeckoContentController::TapType
& aType
,
1295 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1296 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
,
1297 const Maybe
<DoubleTapToZoomMetrics
>& aDoubleTapToZoomMetrics
) {
1298 // IPDL doesn't hold a strong reference to protocols as they're not required
1299 // to be refcounted. This function can run script, which may trigger a nested
1300 // event loop, which may release this, so we hold a strong reference here.
1301 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1302 RefPtr
<PresShell
> presShell
= GetTopLevelPresShell();
1303 if (!presShell
|| !presShell
->GetPresContext() || !mAPZEventState
) {
1306 CSSToLayoutDeviceScale
scale(
1307 presShell
->GetPresContext()->CSSToDevPixelScale());
1308 CSSPoint point
= aPoint
/ scale
;
1310 // Stash the guid in InputAPZContext so that when the visual-to-layout
1311 // transform is applied to the event's coordinates, we use the right transform
1312 // based on the scroll frame being targeted.
1313 // The other values don't really matter.
1314 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1317 case GeckoContentController::TapType::eSingleTap
:
1318 if (mBrowserChildMessageManager
) {
1319 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1320 eventState
->ProcessSingleTap(point
, scale
, aModifiers
, 1,
1324 case GeckoContentController::TapType::eDoubleTap
:
1325 HandleDoubleTap(point
, aModifiers
, aGuid
, *aDoubleTapToZoomMetrics
);
1327 case GeckoContentController::TapType::eSecondTap
:
1328 if (mBrowserChildMessageManager
) {
1329 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1330 eventState
->ProcessSingleTap(point
, scale
, aModifiers
, 2,
1334 case GeckoContentController::TapType::eLongTap
:
1335 if (mBrowserChildMessageManager
) {
1336 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1337 eventState
->ProcessLongTap(presShell
, point
, scale
, aModifiers
,
1341 case GeckoContentController::TapType::eLongTapUp
:
1342 if (mBrowserChildMessageManager
) {
1343 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1344 eventState
->ProcessLongTapUp(presShell
, point
, scale
, aModifiers
);
1351 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityHandleTap(
1352 const GeckoContentController::TapType
& aType
,
1353 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1354 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
,
1355 const Maybe
<DoubleTapToZoomMetrics
>& aDoubleTapToZoomMetrics
) {
1356 // IPDL doesn't hold a strong reference to protocols as they're not required
1357 // to be refcounted. This function can run script, which may trigger a nested
1358 // event loop, which may release this, so we hold a strong reference here.
1359 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1360 return RecvHandleTap(aType
, aPoint
, aModifiers
, aGuid
, aInputBlockId
,
1361 aDoubleTapToZoomMetrics
);
1364 void BrowserChild::NotifyAPZStateChange(
1365 const ViewID
& aViewId
,
1366 const layers::GeckoContentController::APZStateChange
& aChange
,
1367 const int& aArg
, Maybe
<uint64_t> aInputBlockId
) {
1368 if (mAPZEventState
) {
1369 mAPZEventState
->ProcessAPZStateChange(aViewId
, aChange
, aArg
,
1372 nsCOMPtr
<nsIObserverService
> observerService
=
1373 mozilla::services::GetObserverService();
1375 layers::GeckoContentController::APZStateChange::eTransformEnd
) {
1376 // This is used by tests to determine when the APZ is done doing whatever
1377 // it's doing. XXX generify this as needed when writing additional tests.
1378 observerService
->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
1379 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1381 } else if (aChange
==
1382 layers::GeckoContentController::APZStateChange::eTransformBegin
) {
1383 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1388 void BrowserChild::StartScrollbarDrag(
1389 const layers::AsyncDragMetrics
& aDragMetrics
) {
1390 ScrollableLayerGuid
guid(mLayersId
, aDragMetrics
.mPresShellId
,
1391 aDragMetrics
.mViewId
);
1393 if (mApzcTreeManager
) {
1394 mApzcTreeManager
->StartScrollbarDrag(guid
, aDragMetrics
);
1398 void BrowserChild::ZoomToRect(const uint32_t& aPresShellId
,
1399 const ScrollableLayerGuid::ViewID
& aViewId
,
1400 const CSSRect
& aRect
, const uint32_t& aFlags
) {
1401 ScrollableLayerGuid
guid(mLayersId
, aPresShellId
, aViewId
);
1403 if (mApzcTreeManager
) {
1404 mApzcTreeManager
->ZoomToRect(guid
, ZoomTarget
{aRect
}, aFlags
);
1408 mozilla::ipc::IPCResult
BrowserChild::RecvActivate(uint64_t aActionId
) {
1409 MOZ_ASSERT(mWebBrowser
);
1410 mWebBrowser
->FocusActivate(aActionId
);
1414 mozilla::ipc::IPCResult
BrowserChild::RecvDeactivate(uint64_t aActionId
) {
1415 MOZ_ASSERT(mWebBrowser
);
1416 mWebBrowser
->FocusDeactivate(aActionId
);
1420 mozilla::ipc::IPCResult
BrowserChild::RecvStopIMEStateManagement() {
1421 IMEStateManager::StopIMEStateManagement();
1425 void BrowserChild::ProcessPendingCoalescedTouchData() {
1426 MOZ_ASSERT(StaticPrefs::dom_events_coalesce_touchmove());
1428 if (mCoalescedTouchData
.IsEmpty()) {
1432 if (mCoalescedTouchMoveEventFlusher
) {
1433 mCoalescedTouchMoveEventFlusher
->RemoveObserver();
1436 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1437 mCoalescedTouchData
.TakeCoalescedEvent();
1438 Unused
<< RecvRealTouchEvent(*touchMoveEvent
,
1439 mCoalescedTouchData
.GetScrollableLayerGuid(),
1440 mCoalescedTouchData
.GetInputBlockId(),
1441 mCoalescedTouchData
.GetApzResponse());
1444 void BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() {
1445 if (!mCoalesceMouseMoveEvents
|| !mCoalescedMouseEventFlusher
) {
1446 // We don't enable mouse coalescing or we are destroying BrowserChild.
1450 // We may reentry the event loop and push more data to
1451 // mToBeDispatchedMouseData while dispatching an event.
1453 // We may have some pending coalesced data while dispatch an event and reentry
1454 // the event loop. In that case we don't have chance to consume the remainding
1455 // pending data until we get new mouse events. Get some helps from
1456 // mCoalescedMouseEventFlusher to trigger it.
1457 mCoalescedMouseEventFlusher
->StartObserver();
1459 while (mToBeDispatchedMouseData
.GetSize() > 0) {
1460 UniquePtr
<CoalescedMouseData
> data(
1461 static_cast<CoalescedMouseData
*>(mToBeDispatchedMouseData
.PopFront()));
1463 UniquePtr
<WidgetMouseEvent
> event
= data
->TakeCoalescedEvent();
1465 // Dispatch the pending events. Using HandleRealMouseButtonEvent
1466 // to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
1467 // RecvRealMouseButtonEvent because we may also put some mouse events
1468 // other than mousemove.
1469 HandleRealMouseButtonEvent(*event
, data
->GetScrollableLayerGuid(),
1470 data
->GetInputBlockId());
1473 // mCoalescedMouseEventFlusher may be destroyed when reentrying the event
1475 if (mCoalescedMouseEventFlusher
) {
1476 mCoalescedMouseEventFlusher
->RemoveObserver();
1480 LayoutDeviceToLayoutDeviceMatrix4x4
1481 BrowserChild::GetChildToParentConversionMatrix() const {
1482 if (mChildToParentConversionMatrix
) {
1483 return *mChildToParentConversionMatrix
;
1485 LayoutDevicePoint
offset(GetChromeOffset());
1486 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset
);
1489 Maybe
<ScreenRect
> BrowserChild::GetTopLevelViewportVisibleRectInBrowserCoords()
1491 if (!mChildToParentConversionMatrix
) {
1494 return Some(mTopLevelViewportVisibleRectInBrowserCoords
);
1497 void BrowserChild::FlushAllCoalescedMouseData() {
1498 MOZ_ASSERT(mCoalesceMouseMoveEvents
);
1500 // Move all entries from mCoalescedMouseData to mToBeDispatchedMouseData.
1501 for (const auto& data
: mCoalescedMouseData
.Values()) {
1502 if (!data
|| data
->IsEmpty()) {
1505 UniquePtr
<CoalescedMouseData
> dispatchData
=
1506 MakeUnique
<CoalescedMouseData
>();
1508 dispatchData
->RetrieveDataFrom(*data
);
1509 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1511 mCoalescedMouseData
.Clear();
1514 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEvent(
1515 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1516 const uint64_t& aInputBlockId
) {
1517 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
) {
1518 CoalescedMouseData
* data
=
1519 mCoalescedMouseData
.GetOrInsertNew(aEvent
.pointerId
);
1521 if (data
->CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1522 data
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1523 mCoalescedMouseEventFlusher
->StartObserver();
1526 // Can't coalesce current mousemove event. Put the coalesced mousemove data
1527 // with the same pointer id to mToBeDispatchedMouseData, coalesce the
1528 // current one, and process all pending data in mToBeDispatchedMouseData.
1529 UniquePtr
<CoalescedMouseData
> dispatchData
=
1530 MakeUnique
<CoalescedMouseData
>();
1532 dispatchData
->RetrieveDataFrom(*data
);
1533 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1535 // Put new data to replace the old one in the hash table.
1536 CoalescedMouseData
* newData
=
1538 .InsertOrUpdate(aEvent
.pointerId
, MakeUnique
<CoalescedMouseData
>())
1540 newData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1542 // Dispatch all pending mouse events.
1543 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1544 mCoalescedMouseEventFlusher
->StartObserver();
1545 } else if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1546 return IPC_FAIL_NO_REASON(this);
1551 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEventForTests(
1552 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1553 const uint64_t& aInputBlockId
) {
1554 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1557 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseMoveEvent(
1558 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1559 const uint64_t& aInputBlockId
) {
1560 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1563 mozilla::ipc::IPCResult
1564 BrowserChild::RecvNormalPriorityRealMouseMoveEventForTests(
1565 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1566 const uint64_t& aInputBlockId
) {
1567 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1570 mozilla::ipc::IPCResult
BrowserChild::RecvSynthMouseMoveEvent(
1571 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1572 const uint64_t& aInputBlockId
) {
1573 if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1574 return IPC_FAIL_NO_REASON(this);
1579 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySynthMouseMoveEvent(
1580 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1581 const uint64_t& aInputBlockId
) {
1582 return RecvSynthMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1585 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseButtonEvent(
1586 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1587 const uint64_t& aInputBlockId
) {
1588 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
&&
1589 aEvent
.mMessage
!= eMouseMove
) {
1590 // When receiving a mouse event other than mousemove, we have to dispatch
1591 // all coalesced events before it. However, we can't dispatch all pending
1592 // coalesced events directly because we may reentry the event loop while
1593 // dispatching. To make sure we won't dispatch disorder events, we move all
1594 // coalesced mousemove events and current event to a deque to dispatch them.
1595 // When reentrying the event loop and dispatching more events, we put new
1596 // events in the end of the nsQueue and dispatch events from the beginning.
1597 FlushAllCoalescedMouseData();
1599 UniquePtr
<CoalescedMouseData
> dispatchData
=
1600 MakeUnique
<CoalescedMouseData
>();
1602 dispatchData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1603 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1605 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1608 HandleRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1612 void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent
& aEvent
,
1613 const ScrollableLayerGuid
& aGuid
,
1614 const uint64_t& aInputBlockId
) {
1615 WidgetMouseEvent
localEvent(aEvent
);
1616 localEvent
.mWidget
= mPuppetWidget
;
1618 // We need one InputAPZContext here to propagate |aGuid| to places in
1619 // SendSetTargetAPZCNotification() which apply the visual-to-layout transform,
1620 // and another below to propagate the |postLayerization| flag (whose value
1621 // we don't know until SendSetTargetAPZCNotification() returns) into
1622 // the event dispatch code.
1623 InputAPZContext
context1(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1625 // Mouse events like eMouseEnterIntoWidget, that are created in the parent
1626 // process EventStateManager code, have an input block id which they get from
1627 // the InputAPZContext in the parent process stack. However, they did not
1628 // actually go through the APZ code and so their mHandledByAPZ flag is false.
1629 // Since thos events didn't go through APZ, we don't need to send
1630 // notifications for them.
1631 RefPtr
<DisplayportSetListener
> postLayerization
;
1632 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
) {
1633 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1634 postLayerization
= APZCCallbackHelper::SendSetTargetAPZCNotification(
1635 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
, aInputBlockId
);
1638 InputAPZContext
context2(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
,
1639 postLayerization
!= nullptr);
1641 DispatchWidgetEventViaAPZ(localEvent
);
1643 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
&& mAPZEventState
) {
1644 mAPZEventState
->ProcessMouseEvent(localEvent
, aInputBlockId
);
1647 // Do this after the DispatchWidgetEventViaAPZ call above, so that if the
1648 // mouse event triggered a post-refresh AsyncDragMetrics message to be sent
1649 // to APZ (from scrollbar dragging in nsSliderFrame), then that will reach
1650 // APZ before the SetTargetAPZC message. This ensures the drag input block
1651 // gets the drag metrics before handling the input events.
1652 if (postLayerization
) {
1653 postLayerization
->Register();
1657 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseButtonEvent(
1658 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1659 const uint64_t& aInputBlockId
) {
1660 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1663 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseEnterExitWidgetEvent(
1664 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1665 const uint64_t& aInputBlockId
) {
1666 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1669 mozilla::ipc::IPCResult
1670 BrowserChild::RecvNormalPriorityRealMouseEnterExitWidgetEvent(
1671 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1672 const uint64_t& aInputBlockId
) {
1673 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1676 nsEventStatus
BrowserChild::DispatchWidgetEventViaAPZ(WidgetGUIEvent
& aEvent
) {
1677 aEvent
.ResetWaitingReplyFromRemoteProcessState();
1678 return APZCCallbackHelper::DispatchWidgetEvent(aEvent
);
1681 void BrowserChild::DispatchCoalescedWheelEvent() {
1682 UniquePtr
<WidgetWheelEvent
> wheelEvent
=
1683 mCoalescedWheelData
.TakeCoalescedEvent();
1684 MOZ_ASSERT(wheelEvent
);
1685 DispatchWheelEvent(*wheelEvent
, mCoalescedWheelData
.GetScrollableLayerGuid(),
1686 mCoalescedWheelData
.GetInputBlockId());
1689 void BrowserChild::DispatchWheelEvent(const WidgetWheelEvent
& aEvent
,
1690 const ScrollableLayerGuid
& aGuid
,
1691 const uint64_t& aInputBlockId
) {
1692 WidgetWheelEvent
localEvent(aEvent
);
1693 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
) {
1694 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1695 RefPtr
<DisplayportSetListener
> postLayerization
=
1696 APZCCallbackHelper::SendSetTargetAPZCNotification(
1697 mPuppetWidget
, document
, aEvent
, aGuid
.mLayersId
, aInputBlockId
);
1698 if (postLayerization
) {
1699 postLayerization
->Register();
1703 localEvent
.mWidget
= mPuppetWidget
;
1705 // Stash the guid in InputAPZContext so that when the visual-to-layout
1706 // transform is applied to the event's coordinates, we use the right transform
1707 // based on the scroll frame being targeted.
1708 // The other values don't really matter.
1709 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1711 DispatchWidgetEventViaAPZ(localEvent
);
1713 if (localEvent
.mCanTriggerSwipe
) {
1714 SendRespondStartSwipeEvent(aInputBlockId
, localEvent
.TriggersSwipe());
1717 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
&& mAPZEventState
) {
1718 mAPZEventState
->ProcessWheelEvent(localEvent
, aInputBlockId
);
1722 mozilla::ipc::IPCResult
BrowserChild::RecvMouseWheelEvent(
1723 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1724 const uint64_t& aInputBlockId
) {
1725 bool isNextWheelEvent
= false;
1726 // We only coalesce the current event when
1727 // 1. It's eWheel (we don't coalesce eOperationStart and eWheelOperationEnd)
1728 // 2. It has same attributes as the coalesced wheel event which is not yet
1730 if (aEvent
.mMessage
== eWheel
) {
1731 GetIPCChannel()->PeekMessages(
1732 [&isNextWheelEvent
](const IPC::Message
& aMsg
) -> bool {
1733 if (aMsg
.type() == mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID
) {
1734 isNextWheelEvent
= true;
1736 return false; // Stop peeking.
1739 if (!mCoalescedWheelData
.IsEmpty() &&
1740 !mCoalescedWheelData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1741 DispatchCoalescedWheelEvent();
1742 MOZ_ASSERT(mCoalescedWheelData
.IsEmpty());
1744 mCoalescedWheelData
.Coalesce(aEvent
, aGuid
, aInputBlockId
);
1746 MOZ_ASSERT(!mCoalescedWheelData
.IsEmpty());
1747 // If the next event isn't a wheel event, make sure we dispatch.
1748 if (!isNextWheelEvent
) {
1749 DispatchCoalescedWheelEvent();
1752 DispatchWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1758 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityMouseWheelEvent(
1759 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1760 const uint64_t& aInputBlockId
) {
1761 return RecvMouseWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1764 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchEvent(
1765 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1766 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1767 MOZ_LOG(sApzChildLog
, LogLevel::Debug
,
1768 ("Receiving touch event of type %d\n", aEvent
.mMessage
));
1770 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1771 if (aEvent
.mMessage
== eTouchEnd
|| aEvent
.mMessage
== eTouchStart
) {
1772 ProcessPendingCoalescedTouchData();
1775 if (aEvent
.mMessage
!= eTouchMove
) {
1776 sConsecutiveTouchMoveCount
= 0;
1780 WidgetTouchEvent
localEvent(aEvent
);
1781 localEvent
.mWidget
= mPuppetWidget
;
1783 // Stash the guid in InputAPZContext so that when the visual-to-layout
1784 // transform is applied to the event's coordinates, we use the right transform
1785 // based on the scroll frame being targeted.
1786 // The other values don't really matter.
1787 InputAPZContext
context(aGuid
, aInputBlockId
, aApzResponse
);
1789 nsTArray
<TouchBehaviorFlags
> allowedTouchBehaviors
;
1790 if (localEvent
.mMessage
== eTouchStart
&& AsyncPanZoomEnabled()) {
1791 nsCOMPtr
<Document
> document
= GetTopLevelDocument();
1792 allowedTouchBehaviors
= TouchActionHelper::GetAllowedTouchBehavior(
1793 mPuppetWidget
, document
, localEvent
);
1794 if (!allowedTouchBehaviors
.IsEmpty() && mApzcTreeManager
) {
1795 mApzcTreeManager
->SetAllowedTouchBehavior(aInputBlockId
,
1796 allowedTouchBehaviors
);
1798 RefPtr
<DisplayportSetListener
> postLayerization
=
1799 APZCCallbackHelper::SendSetTargetAPZCNotification(
1800 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
,
1802 if (postLayerization
) {
1803 postLayerization
->Register();
1807 // Dispatch event to content (potentially a long-running operation)
1808 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
1810 if (!AsyncPanZoomEnabled()) {
1811 // We shouldn't have any e10s platforms that have touch events enabled
1817 if (mAPZEventState
) {
1818 mAPZEventState
->ProcessTouchEvent(localEvent
, aGuid
, aInputBlockId
,
1819 aApzResponse
, status
,
1820 std::move(allowedTouchBehaviors
));
1825 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchEvent(
1826 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1827 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1828 return RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
1831 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchMoveEvent(
1832 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1833 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1834 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1835 ++sConsecutiveTouchMoveCount
;
1836 if (mCoalescedTouchMoveEventFlusher
) {
1837 MOZ_ASSERT(aEvent
.mMessage
== eTouchMove
);
1838 if (mCoalescedTouchData
.IsEmpty() ||
1839 mCoalescedTouchData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
,
1841 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1844 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1845 mCoalescedTouchData
.TakeCoalescedEvent();
1847 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1850 if (!RecvRealTouchEvent(*touchMoveEvent
,
1851 mCoalescedTouchData
.GetScrollableLayerGuid(),
1852 mCoalescedTouchData
.GetInputBlockId(),
1853 mCoalescedTouchData
.GetApzResponse())) {
1854 return IPC_FAIL_NO_REASON(this);
1858 if (sConsecutiveTouchMoveCount
> 1) {
1859 mCoalescedTouchMoveEventFlusher
->StartObserver();
1861 // Flush the pending coalesced touch in order to avoid the first
1862 // touchmove be overridden by the second one.
1863 ProcessPendingCoalescedTouchData();
1869 if (!RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
)) {
1870 return IPC_FAIL_NO_REASON(this);
1875 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchMoveEvent(
1876 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1877 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1878 return RecvRealTouchMoveEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
1881 mozilla::ipc::IPCResult
BrowserChild::RecvRealDragEvent(
1882 const WidgetDragEvent
& aEvent
, const uint32_t& aDragAction
,
1883 const uint32_t& aDropEffect
, nsIPrincipal
* aPrincipal
,
1884 nsIContentSecurityPolicy
* aCsp
) {
1885 WidgetDragEvent
localEvent(aEvent
);
1886 localEvent
.mWidget
= mPuppetWidget
;
1888 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
1890 dragSession
->SetDragAction(aDragAction
);
1891 dragSession
->SetTriggeringPrincipal(aPrincipal
);
1892 dragSession
->SetCsp(aCsp
);
1893 RefPtr
<DataTransfer
> initialDataTransfer
= dragSession
->GetDataTransfer();
1894 if (initialDataTransfer
) {
1895 initialDataTransfer
->SetDropEffectInt(aDropEffect
);
1899 if (aEvent
.mMessage
== eDrop
) {
1900 bool canDrop
= true;
1901 if (!dragSession
|| NS_FAILED(dragSession
->GetCanDrop(&canDrop
)) ||
1903 localEvent
.mMessage
= eDragExit
;
1905 } else if (aEvent
.mMessage
== eDragOver
) {
1906 nsCOMPtr
<nsIDragService
> dragService
=
1907 do_GetService("@mozilla.org/widget/dragservice;1");
1909 // This will dispatch 'drag' event at the source if the
1910 // drag transaction started in this process.
1911 dragService
->FireDragEventAtSource(eDrag
, aEvent
.mModifiers
);
1915 DispatchWidgetEventViaAPZ(localEvent
);
1919 void BrowserChild::RequestEditCommands(NativeKeyBindingsType aType
,
1920 const WidgetKeyboardEvent
& aEvent
,
1921 nsTArray
<CommandInt
>& aCommands
) {
1922 MOZ_ASSERT(aCommands
.IsEmpty());
1924 if (NS_WARN_IF(aEvent
.IsEditCommandsInitialized(aType
))) {
1925 aCommands
= aEvent
.EditCommandsConstRef(aType
).Clone();
1930 case NativeKeyBindingsType::SingleLineEditor
:
1931 case NativeKeyBindingsType::MultiLineEditor
:
1932 case NativeKeyBindingsType::RichTextEditor
:
1935 MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type");
1938 // Don't send aEvent to the parent process directly because it'll be marked
1939 // as posted to remote process.
1940 WidgetKeyboardEvent
localEvent(aEvent
);
1941 SendRequestNativeKeyBindings(static_cast<uint32_t>(aType
), localEvent
,
1945 mozilla::ipc::IPCResult
BrowserChild::RecvNativeSynthesisResponse(
1946 const uint64_t& aObserverId
, const nsCString
& aResponse
) {
1947 mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId
,
1952 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateSHistory() {
1953 if (mSessionStoreChild
) {
1954 mSessionStoreChild
->UpdateSHistoryChanges();
1959 // In case handling repeated keys takes much time, we skip firing new ones.
1960 bool BrowserChild::SkipRepeatedKeyEvent(const WidgetKeyboardEvent
& aEvent
) {
1961 if (mRepeatedKeyEventTime
.IsNull() || !aEvent
.CanSkipInRemoteProcess() ||
1962 (aEvent
.mMessage
!= eKeyDown
&& aEvent
.mMessage
!= eKeyPress
)) {
1963 mRepeatedKeyEventTime
= TimeStamp();
1964 mSkipKeyPress
= false;
1968 if ((aEvent
.mMessage
== eKeyDown
&&
1969 (mRepeatedKeyEventTime
> aEvent
.mTimeStamp
)) ||
1970 (mSkipKeyPress
&& (aEvent
.mMessage
== eKeyPress
))) {
1971 // If we skip a keydown event, also the following keypress events should be
1973 mSkipKeyPress
|= aEvent
.mMessage
== eKeyDown
;
1977 if (aEvent
.mMessage
== eKeyDown
) {
1978 // If keydown wasn't skipped, nor should the possible following keypress.
1979 mRepeatedKeyEventTime
= TimeStamp();
1980 mSkipKeyPress
= false;
1985 void BrowserChild::UpdateRepeatedKeyEventEndTime(
1986 const WidgetKeyboardEvent
& aEvent
) {
1987 if (aEvent
.mIsRepeat
&&
1988 (aEvent
.mMessage
== eKeyDown
|| aEvent
.mMessage
== eKeyPress
)) {
1989 mRepeatedKeyEventTime
= TimeStamp::Now();
1993 mozilla::ipc::IPCResult
BrowserChild::RecvRealKeyEvent(
1994 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
1995 MOZ_ASSERT_IF(aEvent
.mMessage
== eKeyPress
,
1996 aEvent
.AreAllEditCommandsInitialized());
1998 // If content code called preventDefault() on a keydown event, then we don't
1999 // want to process any following keypress events.
2000 const bool isPrecedingKeyDownEventConsumed
=
2001 aEvent
.mMessage
== eKeyPress
&& mIgnoreKeyPressEvent
;
2003 WidgetKeyboardEvent
localEvent(aEvent
);
2004 localEvent
.mWidget
= mPuppetWidget
;
2005 localEvent
.mUniqueId
= aEvent
.mUniqueId
;
2007 if (!SkipRepeatedKeyEvent(aEvent
) && !isPrecedingKeyDownEventConsumed
) {
2008 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
2010 // Update the end time of the possible repeated event so that we can skip
2011 // some incoming events in case event handling took long time.
2012 UpdateRepeatedKeyEventEndTime(localEvent
);
2014 if (aEvent
.mMessage
== eKeyDown
) {
2015 mIgnoreKeyPressEvent
= status
== nsEventStatus_eConsumeNoDefault
;
2018 if (localEvent
.mFlags
.mIsSuppressedOrDelayed
) {
2019 localEvent
.PreventDefault();
2022 // If the event's default isn't prevented but the status is no default,
2023 // That means that the event was consumed by EventStateManager or something
2024 // which is not a usual event handler. In such case, prevent its default
2025 // as a default handler. For example, when an eKeyPress event matches
2026 // with a content accesskey, and it's executed, preventDefault() of the
2027 // event won't be called but the status is set to "no default". Then,
2028 // the event shouldn't be handled by nsMenuBarListener in the main process.
2029 if (!localEvent
.DefaultPrevented() &&
2030 status
== nsEventStatus_eConsumeNoDefault
) {
2031 localEvent
.PreventDefault();
2034 MOZ_DIAGNOSTIC_ASSERT(!localEvent
.PropagationStopped());
2036 // The keyboard event which we ignore should not be handled in the main
2037 // process for shortcut key handling. For notifying if we skipped it, we can
2038 // use "stop propagation" flag here because it must be cleared by
2039 // `EventTargetChainItem` if we've dispatched it.
2041 localEvent
.StopPropagation();
2044 // If we don't need to send a rely for the given keyboard event, we do nothing
2046 if (!aEvent
.WantReplyFromContentProcess()) {
2050 // This is an ugly hack, mNoRemoteProcessDispatch is set to true when the
2051 // event's PreventDefault() or StopScrollProcessForwarding() is called.
2052 // And then, it'll be checked by ParamTraits<mozilla::WidgetEvent>::Write()
2053 // whether the event is being sent to remote process unexpectedly.
2054 // However, unfortunately, it cannot check the destination. Therefore,
2055 // we need to clear the flag explicitly here because ParamTraits should
2056 // keep checking the flag for avoiding regression.
2057 localEvent
.mFlags
.mNoRemoteProcessDispatch
= false;
2058 SendReplyKeyEvent(localEvent
, aUUID
);
2063 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealKeyEvent(
2064 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
2065 return RecvRealKeyEvent(aEvent
, aUUID
);
2068 mozilla::ipc::IPCResult
BrowserChild::RecvCompositionEvent(
2069 const WidgetCompositionEvent
& aEvent
) {
2070 WidgetCompositionEvent
localEvent(aEvent
);
2071 localEvent
.mWidget
= mPuppetWidget
;
2072 DispatchWidgetEventViaAPZ(localEvent
);
2073 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
,
2074 localEvent
.mCompositionId
);
2078 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityCompositionEvent(
2079 const WidgetCompositionEvent
& aEvent
) {
2080 return RecvCompositionEvent(aEvent
);
2083 mozilla::ipc::IPCResult
BrowserChild::RecvSelectionEvent(
2084 const WidgetSelectionEvent
& aEvent
) {
2085 WidgetSelectionEvent
localEvent(aEvent
);
2086 localEvent
.mWidget
= mPuppetWidget
;
2087 DispatchWidgetEventViaAPZ(localEvent
);
2088 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
, 0u);
2092 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySelectionEvent(
2093 const WidgetSelectionEvent
& aEvent
) {
2094 return RecvSelectionEvent(aEvent
);
2097 mozilla::ipc::IPCResult
BrowserChild::RecvInsertText(
2098 const nsAString
& aStringToInsert
) {
2099 // Use normal event path to reach focused document.
2100 WidgetContentCommandEvent
localEvent(true, eContentCommandInsertText
,
2102 localEvent
.mString
= Some(nsString(aStringToInsert
));
2103 DispatchWidgetEventViaAPZ(localEvent
);
2107 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityInsertText(
2108 const nsAString
& aStringToInsert
) {
2109 return RecvInsertText(aStringToInsert
);
2112 mozilla::ipc::IPCResult
BrowserChild::RecvPasteTransferable(
2113 const IPCTransferable
& aTransferable
) {
2115 nsCOMPtr
<nsITransferable
> trans
=
2116 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
2117 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2118 trans
->Init(nullptr);
2120 rv
= nsContentUtils::IPCTransferableToTransferable(
2121 aTransferable
, true /* aAddDataFlavor */, trans
,
2122 false /* aFilterUnknownFlavors */);
2123 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2125 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2126 if (NS_WARN_IF(!ourDocShell
)) {
2130 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
2131 rv
= params
->SetISupports("transferable", trans
);
2132 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2134 ourDocShell
->DoCommandWithParams("cmd_pasteTransferable", params
);
2138 #ifdef ACCESSIBILITY
2139 a11y::PDocAccessibleChild
* BrowserChild::AllocPDocAccessibleChild(
2140 PDocAccessibleChild
*, const uint64_t&,
2141 const MaybeDiscardedBrowsingContext
&) {
2142 MOZ_ASSERT(false, "should never call this!");
2146 bool BrowserChild::DeallocPDocAccessibleChild(
2147 a11y::PDocAccessibleChild
* aChild
) {
2148 delete static_cast<mozilla::a11y::DocAccessibleChild
*>(aChild
);
2153 RefPtr
<VsyncMainChild
> BrowserChild::GetVsyncChild() {
2154 // Initializing mVsyncChild here turns on per-BrowserChild Vsync for a
2155 // given platform. Note: this only makes sense if nsWindow returns a
2156 // window-specific VsyncSource.
2157 #if defined(MOZ_WAYLAND)
2158 if (IsWaylandEnabled() && !mVsyncChild
) {
2159 mVsyncChild
= MakeRefPtr
<VsyncMainChild
>();
2160 if (!SendPVsyncConstructor(mVsyncChild
)) {
2161 mVsyncChild
= nullptr;
2168 mozilla::ipc::IPCResult
BrowserChild::RecvLoadRemoteScript(
2169 const nsAString
& aURL
, const bool& aRunInGlobalScope
) {
2170 if (!InitBrowserChildMessageManager())
2171 // This can happen if we're half-destroyed. It's not a fatal
2175 JS::Rooted
<JSObject
*> mm(RootingCx(),
2176 mBrowserChildMessageManager
->GetOrCreateWrapper());
2178 // This can happen if we're half-destroyed. It's not a fatal error.
2182 LoadScriptInternal(mm
, aURL
, !aRunInGlobalScope
);
2186 mozilla::ipc::IPCResult
BrowserChild::RecvAsyncMessage(
2187 const nsAString
& aMessage
, const ClonedMessageData
& aData
) {
2188 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserChild::RecvAsyncMessage",
2190 MMPrinter::Print("BrowserChild::RecvAsyncMessage", aMessage
, aData
);
2192 if (!mBrowserChildMessageManager
) {
2196 RefPtr
<nsFrameMessageManager
> mm
=
2197 mBrowserChildMessageManager
->GetMessageManager();
2199 // We should have a message manager if the global is alive, but it
2200 // seems sometimes we don't. Assert in aurora/nightly, but don't
2201 // crash in release builds.
2202 MOZ_DIAGNOSTIC_ASSERT(mm
);
2207 JS::Rooted
<JSObject
*> kungFuDeathGrip(
2208 dom::RootingCx(), mBrowserChildMessageManager
->GetWrapper());
2209 StructuredCloneData data
;
2210 UnpackClonedMessageData(aData
, data
);
2211 mm
->ReceiveMessage(static_cast<EventTarget
*>(mBrowserChildMessageManager
),
2212 nullptr, aMessage
, false, &data
, nullptr, IgnoreErrors());
2216 mozilla::ipc::IPCResult
BrowserChild::RecvSwappedWithOtherRemoteLoader(
2217 const IPCTabContext
& aContext
) {
2218 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2219 if (NS_WARN_IF(!ourDocShell
)) {
2223 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= ourDocShell
->GetWindow();
2224 if (NS_WARN_IF(!ourWindow
)) {
2228 RefPtr
<nsDocShell
> docShell
= static_cast<nsDocShell
*>(ourDocShell
.get());
2230 nsCOMPtr
<EventTarget
> ourEventTarget
= nsGlobalWindowOuter::Cast(ourWindow
);
2232 docShell
->SetInFrameSwap(true);
2234 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2235 ourDocShell
, ourEventTarget
, false, true);
2236 nsContentUtils::FirePageHideEventForFrameLoaderSwap(ourDocShell
,
2237 ourEventTarget
, true);
2239 // Owner content type may have changed, so store the possibly updated context
2240 // and notify others.
2241 MaybeInvalidTabContext
maybeContext(aContext
);
2242 if (!maybeContext
.IsValid()) {
2243 NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
2244 "the parent process. (%s)",
2245 maybeContext
.GetInvalidReason())
2247 MOZ_CRASH("Invalid TabContext received from the parent process.");
2250 if (!UpdateTabContextAfterSwap(maybeContext
.GetTabContext())) {
2251 MOZ_CRASH("Update to TabContext after swap was denied.");
2254 // Ignore previous value of mTriedBrowserInit since owner content has changed.
2255 mTriedBrowserInit
= true;
2257 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2258 ourDocShell
, ourEventTarget
, true, true);
2260 docShell
->SetInFrameSwap(false);
2262 // This is needed to get visibility state right in cases when we swapped a
2263 // visible tab (foreground in visible window) with a non-visible tab.
2264 if (RefPtr
<Document
> doc
= docShell
->GetDocument()) {
2265 doc
->UpdateVisibilityState();
2271 mozilla::ipc::IPCResult
BrowserChild::RecvHandleAccessKey(
2272 const WidgetKeyboardEvent
& aEvent
, nsTArray
<uint32_t>&& aCharCodes
) {
2273 nsCOMPtr
<Document
> document(GetTopLevelDocument());
2274 RefPtr
<nsPresContext
> pc
= document
->GetPresContext();
2276 if (!pc
->EventStateManager()->HandleAccessKey(
2277 &(const_cast<WidgetKeyboardEvent
&>(aEvent
)), pc
, aCharCodes
)) {
2278 // If no accesskey was found, inform the parent so that accesskeys on
2279 // menus can be handled.
2280 WidgetKeyboardEvent
localEvent(aEvent
);
2281 localEvent
.mWidget
= mPuppetWidget
;
2282 SendAccessKeyNotHandled(localEvent
);
2289 mozilla::ipc::IPCResult
BrowserChild::RecvPrintPreview(
2290 const PrintData
& aPrintData
, const MaybeDiscardedBrowsingContext
& aSourceBC
,
2291 PrintPreviewResolver
&& aCallback
) {
2293 // If we didn't succeed in passing off ownership of aCallback, then something
2295 auto sendCallbackError
= MakeScopeExit([&] {
2298 aCallback(PrintPreviewResultInfo(0, 0, false, false, false, {}, {}, {}));
2302 if (NS_WARN_IF(aSourceBC
.IsDiscarded())) {
2306 RefPtr
<nsGlobalWindowOuter
> sourceWindow
;
2307 if (!aSourceBC
.IsNull()) {
2308 sourceWindow
= nsGlobalWindowOuter::Cast(aSourceBC
.get()->GetDOMWindow());
2309 if (NS_WARN_IF(!sourceWindow
)) {
2313 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= do_GetInterface(WebNavigation());
2314 if (NS_WARN_IF(!ourWindow
)) {
2317 sourceWindow
= nsGlobalWindowOuter::Cast(ourWindow
);
2320 RefPtr
<nsIPrintSettings
> printSettings
;
2321 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2322 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2323 if (NS_WARN_IF(!printSettingsSvc
)) {
2326 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2327 if (NS_WARN_IF(!printSettings
)) {
2330 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2332 nsCOMPtr
<nsIDocShell
> docShellToCloneInto
;
2333 if (!aSourceBC
.IsNull()) {
2334 docShellToCloneInto
= do_GetInterface(WebNavigation());
2335 if (NS_WARN_IF(!docShellToCloneInto
)) {
2340 sourceWindow
->Print(printSettings
,
2341 /* aRemotePrintJob = */ nullptr,
2342 /* aListener = */ nullptr, docShellToCloneInto
,
2343 nsGlobalWindowOuter::IsPreview::Yes
,
2344 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2345 std::move(aCallback
), nullptr, IgnoreErrors());
2350 mozilla::ipc::IPCResult
BrowserChild::RecvExitPrintPreview() {
2352 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
=
2353 do_GetInterface(ToSupports(WebNavigation()));
2354 if (NS_WARN_IF(!webBrowserPrint
)) {
2357 webBrowserPrint
->ExitPrintPreview();
2362 mozilla::ipc::IPCResult
BrowserChild::CommonPrint(
2363 const MaybeDiscardedBrowsingContext
& aBc
, const PrintData
& aPrintData
,
2364 RefPtr
<BrowsingContext
>* aCachedBrowsingContext
) {
2366 if (NS_WARN_IF(aBc
.IsNullOrDiscarded())) {
2369 RefPtr
<nsGlobalWindowOuter
> outerWindow
=
2370 nsGlobalWindowOuter::Cast(aBc
.get()->GetDOMWindow());
2371 if (NS_WARN_IF(!outerWindow
)) {
2375 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2376 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2377 if (NS_WARN_IF(!printSettingsSvc
)) {
2381 nsCOMPtr
<nsIPrintSettings
> printSettings
;
2383 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2384 if (NS_WARN_IF(NS_FAILED(rv
))) {
2388 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2390 IgnoredErrorResult rv
;
2391 RefPtr printJob
= static_cast<RemotePrintJobChild
*>(
2392 aPrintData
.remotePrintJob().AsChild());
2394 printSettings
, printJob
,
2395 /* aListener = */ nullptr,
2396 /* aWindowToCloneInto = */ nullptr, nsGlobalWindowOuter::IsPreview::No
,
2397 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2398 /* aPrintPreviewCallback = */ nullptr, aCachedBrowsingContext
, rv
);
2399 if (NS_WARN_IF(rv
.Failed())) {
2407 mozilla::ipc::IPCResult
BrowserChild::RecvPrint(
2408 const MaybeDiscardedBrowsingContext
& aBc
, const PrintData
& aPrintData
,
2409 bool aReturnStaticClone
, PrintResolver
&& aResolve
) {
2411 RefPtr
<BrowsingContext
> browsingContext
;
2412 auto result
= CommonPrint(aBc
, aPrintData
,
2413 aReturnStaticClone
? &browsingContext
: nullptr);
2414 aResolve(browsingContext
);
2422 mozilla::ipc::IPCResult
BrowserChild::RecvPrintClonedPage(
2423 const MaybeDiscardedBrowsingContext
& aBc
, const PrintData
& aPrintData
,
2424 const MaybeDiscardedBrowsingContext
& aClonedBc
) {
2426 if (aClonedBc
.IsNullOrDiscarded()) {
2429 RefPtr
<BrowsingContext
> clonedBc
= aClonedBc
.get();
2430 return CommonPrint(aBc
, aPrintData
, &clonedBc
);
2436 mozilla::ipc::IPCResult
BrowserChild::RecvDestroyPrintClone(
2437 const MaybeDiscardedBrowsingContext
& aCachedPage
) {
2440 RefPtr
<nsPIDOMWindowOuter
> window
= aCachedPage
->GetDOMWindow();
2441 if (NS_WARN_IF(!window
)) {
2450 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateNativeWindowHandle(
2451 const uintptr_t& aNewHandle
) {
2452 #if defined(XP_WIN) && defined(ACCESSIBILITY)
2453 mNativeWindowHandle
= aNewHandle
;
2456 return IPC_FAIL_NO_REASON(this);
2460 mozilla::ipc::IPCResult
BrowserChild::RecvDestroy() {
2461 MOZ_ASSERT(!mDestroyed
);
2464 nsTArray
<PContentPermissionRequestChild
*> childArray
=
2465 nsContentPermissionUtils::GetContentPermissionRequestChildById(
2468 // Need to close undeleted ContentPermissionRequestChilds before tab is
2470 for (auto& permissionRequestChild
: childArray
) {
2471 auto* child
= static_cast<RemotePermissionRequest
*>(permissionRequestChild
);
2475 if (mBrowserChildMessageManager
) {
2476 // Message handlers are called from the event loop, so it better be safe to
2478 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
2479 mBrowserChildMessageManager
->DispatchTrustedEvent(u
"unload"_ns
);
2482 nsCOMPtr
<nsIObserverService
> observerService
=
2483 mozilla::services::GetObserverService();
2485 observerService
->RemoveObserver(this, BEFORE_FIRST_PAINT
);
2487 // XXX what other code in ~BrowserChild() should we be running here?
2490 // Bounce through the event loop once to allow any delayed teardown runnables
2491 // that were just generated to have a chance to run.
2492 nsCOMPtr
<nsIRunnable
> deleteRunnable
= new DelayedDeleteRunnable(this);
2493 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable
));
2498 mozilla::ipc::IPCResult
BrowserChild::RecvRenderLayers(const bool& aEnabled
) {
2499 auto clearPaintWhileInterruptingJS
= MakeScopeExit([&] {
2500 // We might force a paint, or we might already have painted and this is a
2501 // no-op. In either case, once we exit this scope, we need to alert the
2502 // ProcessHangMonitor that we've finished responding to what might have
2503 // been a request to force paint. This is so that the BackgroundHangMonitor
2504 // for force painting can be made to wait again.
2506 ProcessHangMonitor::ClearPaintWhileInterruptingJS();
2511 ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS();
2514 mRenderLayers
= aEnabled
;
2515 const bool wasVisible
= IsVisible();
2519 // If we just became visible, try to trigger a paint as soon as possible.
2520 const bool becameVisible
= !wasVisible
&& IsVisible();
2521 if (!becameVisible
) {
2525 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2530 // We don't use BrowserChildBase::GetPresShell() here because that would
2531 // create a content viewer if one doesn't exist yet. Creating a content
2532 // viewer can cause JS to run, which we want to avoid.
2533 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2534 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2539 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2540 root
->SchedulePaint();
2543 Telemetry::AutoTimer
<Telemetry::TABCHILD_PAINT_TIME
> timer
;
2544 // If we need to repaint, let's do that right away. No sense waiting until
2545 // we get back to the event loop again. We suppress the display port so
2546 // that we only paint what's visible. This ensures that the tab we're
2547 // switching to paints as quickly as possible.
2548 presShell
->SuppressDisplayport(true);
2549 if (nsContentUtils::IsSafeToRunScript()) {
2550 WebWidget()->PaintNowIfNeeded();
2552 RefPtr
<nsViewManager
> vm
= presShell
->GetViewManager();
2553 if (nsView
* view
= vm
->GetRootView()) {
2554 presShell
->PaintAndRequestComposite(view
, PaintFlags::None
);
2557 presShell
->SuppressDisplayport(false);
2561 mozilla::ipc::IPCResult
BrowserChild::RecvNavigateByKey(
2562 const bool& aForward
, const bool& aForDocumentNavigation
) {
2563 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2568 RefPtr
<Element
> result
;
2569 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2571 // Move to the first or last document.
2575 ? (aForDocumentNavigation
2576 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC
)
2577 : StaticPrefs::dom_disable_tab_focus_to_root_element()
2578 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRST
)
2579 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT
))
2580 : (aForDocumentNavigation
2581 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC
)
2582 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LAST
));
2583 uint32_t flags
= nsIFocusManager::FLAG_BYKEY
;
2584 if (aForward
|| aForDocumentNavigation
) {
2585 flags
|= nsIFocusManager::FLAG_NOSCROLL
;
2587 fm
->MoveFocus(window
, nullptr, type
, flags
, getter_AddRefs(result
));
2590 // No valid root element was found, so move to the first focusable element.
2591 if (!result
&& aForward
&& !aForDocumentNavigation
) {
2592 fm
->MoveFocus(window
, nullptr, nsIFocusManager::MOVEFOCUS_FIRST
,
2593 nsIFocusManager::FLAG_BYKEY
, getter_AddRefs(result
));
2596 SendRequestFocus(false, CallerType::System
);
2600 bool BrowserChild::InitBrowserChildMessageManager() {
2601 mShouldSendWebProgressEventsToParent
= true;
2603 if (!mBrowserChildMessageManager
) {
2604 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2605 NS_ENSURE_TRUE(window
, false);
2606 nsCOMPtr
<EventTarget
> chromeHandler
= window
->GetChromeEventHandler();
2607 NS_ENSURE_TRUE(chromeHandler
, false);
2609 RefPtr
<BrowserChildMessageManager
> scope
= mBrowserChildMessageManager
=
2610 new BrowserChildMessageManager(this);
2612 MOZ_ALWAYS_TRUE(nsMessageManagerScriptExecutor::Init());
2614 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(chromeHandler
);
2615 if (NS_WARN_IF(!root
)) {
2616 mBrowserChildMessageManager
= nullptr;
2619 root
->SetParentTarget(scope
);
2622 if (!mTriedBrowserInit
) {
2623 mTriedBrowserInit
= true;
2629 void BrowserChild::InitRenderingState(
2630 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
2631 const layers::LayersId
& aLayersId
,
2632 const CompositorOptions
& aCompositorOptions
) {
2633 mPuppetWidget
->InitIMEState();
2635 MOZ_ASSERT(aLayersId
.IsValid());
2636 mTextureFactoryIdentifier
= aTextureFactoryIdentifier
;
2638 // Pushing layers transactions directly to a separate
2639 // compositor context.
2640 PCompositorBridgeChild
* compositorChild
= CompositorBridgeChild::Get();
2641 if (!compositorChild
) {
2642 mLayersConnected
= Some(false);
2643 NS_WARNING("failed to get CompositorBridgeChild instance");
2647 mCompositorOptions
= Some(aCompositorOptions
);
2649 if (aLayersId
.IsValid()) {
2650 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2652 if (!sBrowserChildren
) {
2653 sBrowserChildren
= new BrowserChildMap
;
2655 MOZ_ASSERT(!sBrowserChildren
->Contains(uint64_t(aLayersId
)));
2656 sBrowserChildren
->InsertOrUpdate(uint64_t(aLayersId
), this);
2657 mLayersId
= aLayersId
;
2660 // Depending on timing, we might paint too early and fall back to basic
2661 // layers. CreateRemoteLayerManager will destroy us if we manage to get a
2662 // remote layer manager though, so that's fine.
2663 MOZ_ASSERT(!mPuppetWidget
->HasWindowRenderer() ||
2664 mPuppetWidget
->GetWindowRenderer()->GetBackendType() ==
2665 layers::LayersBackend::LAYERS_NONE
);
2666 bool success
= false;
2667 if (mLayersConnected
== Some(true)) {
2668 success
= CreateRemoteLayerManager(compositorChild
);
2672 MOZ_ASSERT(mLayersConnected
== Some(true));
2673 // Succeeded to create "remote" layer manager
2674 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
2675 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
2678 NS_WARNING("Fallback to FallbackRenderer");
2679 mLayersConnected
= Some(false);
2682 nsCOMPtr
<nsIObserverService
> observerService
=
2683 mozilla::services::GetObserverService();
2685 if (observerService
) {
2686 observerService
->AddObserver(this, BEFORE_FIRST_PAINT
, false);
2690 bool BrowserChild::CreateRemoteLayerManager(
2691 mozilla::layers::PCompositorBridgeChild
* aCompositorChild
) {
2692 MOZ_ASSERT(aCompositorChild
);
2694 return mPuppetWidget
->CreateRemoteLayerManager(
2695 [&](WebRenderLayerManager
* aLayerManager
) -> bool {
2697 return aLayerManager
->Initialize(aCompositorChild
,
2698 wr::AsPipelineId(mLayersId
),
2699 &mTextureFactoryIdentifier
, error
);
2703 void BrowserChild::InitAPZState() {
2704 if (!mCompositorOptions
->UseAPZ()) {
2707 auto* cbc
= CompositorBridgeChild::Get();
2709 // Initialize the ApzcTreeManager. This takes multiple casts because of ugly
2710 // multiple inheritance.
2711 PAPZCTreeManagerChild
* baseProtocol
=
2712 cbc
->SendPAPZCTreeManagerConstructor(mLayersId
);
2713 if (!baseProtocol
) {
2715 "Allocating a TreeManager should not fail with APZ enabled");
2718 APZCTreeManagerChild
* derivedProtocol
=
2719 static_cast<APZCTreeManagerChild
*>(baseProtocol
);
2721 mApzcTreeManager
= RefPtr
<IAPZCTreeManager
>(derivedProtocol
);
2723 // Initialize the GeckoContentController for this tab. We don't hold a
2724 // reference because we don't need it. The ContentProcessController will hold
2725 // a reference to the tab, and will be destroyed by the compositor or ipdl
2726 // during destruction.
2727 RefPtr
<GeckoContentController
> contentController
=
2728 new ContentProcessController(this);
2729 APZChild
* apzChild
= new APZChild(contentController
);
2730 cbc
->SendPAPZConstructor(apzChild
, mLayersId
);
2733 IPCResult
BrowserChild::RecvUpdateEffects(const EffectsInfo
& aEffects
) {
2734 bool needInvalidate
= false;
2735 if (mEffectsInfo
.IsVisible() && aEffects
.IsVisible() &&
2736 mEffectsInfo
!= aEffects
) {
2737 // If we are staying visible and either the visrect or scale changed we need
2739 needInvalidate
= true;
2742 mEffectsInfo
= aEffects
;
2745 if (needInvalidate
) {
2746 if (nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation())) {
2747 // We don't use BrowserChildBase::GetPresShell() here because that would
2748 // create a content viewer if one doesn't exist yet. Creating a content
2749 // viewer can cause JS to run, which we want to avoid.
2750 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2751 if (RefPtr
<PresShell
> presShell
= docShell
->GetPresShell()) {
2752 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2753 root
->InvalidateFrame();
2762 bool BrowserChild::IsVisible() {
2763 return mPuppetWidget
&& mPuppetWidget
->IsVisible();
2766 void BrowserChild::UpdateVisibility() {
2767 const bool shouldBeVisible
= [&] {
2768 // If we're known to be visibility: hidden / display: none, just return
2769 // false here, we're pretty sure we don't want to be considered visible
2771 if (mBrowsingContext
&& mBrowsingContext
->IsUnderHiddenEmbedderElement()) {
2774 // For OOP iframes, include viewport visibility. For top-level <browser>
2775 // elements we don't use this, because the front-end relies on using
2776 // `mRenderLayers` when invisible for tab warming purposes.
2778 // An alternative, maybe more consistent approach would be to add an opt-in
2779 // into this behavior for top-level tabs managed by the tab-switcher
2781 if (!mIsTopLevel
&& !mEffectsInfo
.IsVisible()) {
2784 // If we're explicitly told not to render layers, we're also invisible.
2785 if (!mRenderLayers
) {
2791 const bool isVisible
= IsVisible();
2792 if (shouldBeVisible
== isVisible
) {
2795 if (shouldBeVisible
) {
2802 void BrowserChild::MakeVisible() {
2807 if (mPuppetWidget
) {
2808 mPuppetWidget
->Show(true);
2811 PresShellActivenessMaybeChanged();
2814 void BrowserChild::MakeHidden() {
2819 // Due to the nested event loop in ContentChild::ProvideWindowCommon,
2820 // it's possible to be told to become hidden before we're finished
2821 // setting up a layer manager. We should skip clearing cached layers
2822 // in that case, since doing so might accidentally put is into
2823 // BasicLayers mode.
2824 if (mPuppetWidget
) {
2825 if (mPuppetWidget
->HasWindowRenderer()) {
2826 ClearCachedResources();
2828 mPuppetWidget
->Show(false);
2831 PresShellActivenessMaybeChanged();
2834 IPCResult
BrowserChild::RecvPreserveLayers(bool aPreserve
) {
2835 mIsPreservingLayers
= aPreserve
;
2837 PresShellActivenessMaybeChanged();
2842 void BrowserChild::PresShellActivenessMaybeChanged() {
2843 // We don't use BrowserChildBase::GetPresShell() here because that would
2844 // create a content viewer if one doesn't exist yet. Creating a content
2845 // viewer can cause JS to run, which we want to avoid.
2846 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2848 // When this method is called we don't want to go through the browsing context
2849 // because we don't want to change the visibility state of the document, which
2850 // has side effects like firing events to content, unblocking media playback,
2851 // unthrottling timeouts... PresShell activeness has a lot less side effects.
2852 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2856 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2860 presShell
->ActivenessMaybeChanged();
2864 BrowserChild::GetMessageManager(ContentFrameMessageManager
** aResult
) {
2865 RefPtr
<ContentFrameMessageManager
> mm(mBrowserChildMessageManager
);
2867 return *aResult
? NS_OK
: NS_ERROR_FAILURE
;
2870 void BrowserChild::SendRequestFocus(bool aCanFocus
, CallerType aCallerType
) {
2871 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2876 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2881 BrowsingContext
* focusedBC
= fm
->GetFocusedBrowsingContext();
2882 if (focusedBC
== window
->GetBrowsingContext()) {
2883 // BrowsingContext has the focus already, do not request again.
2887 PBrowserChild::SendRequestFocus(aCanFocus
, aCallerType
);
2891 BrowserChild::GetTabId(uint64_t* aId
) {
2897 BrowserChild::GetChromeOuterWindowID(uint64_t* aId
) {
2898 *aId
= ChromeOuterWindowID();
2902 bool BrowserChild::DoSendBlockingMessage(
2903 const nsAString
& aMessage
, StructuredCloneData
& aData
,
2904 nsTArray
<StructuredCloneData
>* aRetVal
) {
2905 ClonedMessageData data
;
2906 if (!BuildClonedMessageData(aData
, data
)) {
2909 return SendSyncMessage(PromiseFlatString(aMessage
), data
, aRetVal
);
2912 nsresult
BrowserChild::DoSendAsyncMessage(const nsAString
& aMessage
,
2913 StructuredCloneData
& aData
) {
2914 ClonedMessageData data
;
2915 if (!BuildClonedMessageData(aData
, data
)) {
2916 return NS_ERROR_DOM_DATA_CLONE_ERR
;
2918 if (!SendAsyncMessage(PromiseFlatString(aMessage
), data
)) {
2919 return NS_ERROR_UNEXPECTED
;
2925 nsTArray
<RefPtr
<BrowserChild
>> BrowserChild::GetAll() {
2926 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2928 if (!sBrowserChildren
) {
2932 return ToTArray
<nsTArray
<RefPtr
<BrowserChild
>>>(sBrowserChildren
->Values());
2935 BrowserChild
* BrowserChild::GetFrom(PresShell
* aPresShell
) {
2936 Document
* doc
= aPresShell
->GetDocument();
2940 nsCOMPtr
<nsIDocShell
> docShell(doc
->GetDocShell());
2941 return GetFrom(docShell
);
2944 BrowserChild
* BrowserChild::GetFrom(layers::LayersId aLayersId
) {
2945 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2946 if (!sBrowserChildren
) {
2949 return sBrowserChildren
->Get(uint64_t(aLayersId
));
2952 void BrowserChild::DidComposite(mozilla::layers::TransactionId aTransactionId
,
2953 const TimeStamp
& aCompositeStart
,
2954 const TimeStamp
& aCompositeEnd
) {
2955 MOZ_ASSERT(mPuppetWidget
);
2956 RefPtr
<WebRenderLayerManager
> lm
=
2957 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2961 lm
->DidComposite(aTransactionId
, aCompositeStart
, aCompositeEnd
);
2965 void BrowserChild::ClearCachedResources() {
2966 MOZ_ASSERT(mPuppetWidget
);
2967 RefPtr
<WebRenderLayerManager
> lm
=
2968 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2970 lm
->ClearCachedResources();
2973 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
2974 nsPresContext
* presContext
= document
->GetPresContext();
2976 presContext
->NotifyPaintStatusReset();
2981 void BrowserChild::SchedulePaint() {
2982 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2987 // We don't use BrowserChildBase::GetPresShell() here because that would
2988 // create a content viewer if one doesn't exist yet. Creating a content viewer
2989 // can cause JS to run, which we want to avoid. nsIDocShell::GetPresShell
2990 // returns null if no content viewer exists yet.
2991 if (RefPtr
<PresShell
> presShell
= docShell
->GetPresShell()) {
2992 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2993 root
->SchedulePaint();
2998 void BrowserChild::ReinitRendering() {
2999 MOZ_ASSERT(mLayersId
.IsValid());
3001 // In some cases, like when we create a windowless browser,
3002 // RemoteLayerTreeOwner/BrowserChild is not connected to a compositor.
3003 if (mLayersConnectRequested
.isNothing() ||
3004 mLayersConnectRequested
== Some(false)) {
3008 // Before we establish a new PLayerTransaction, we must connect our layer tree
3009 // id, CompositorBridge, and the widget compositor all together again.
3010 // Normally this happens in BrowserParent before BrowserChild is given
3011 // rendering information.
3013 // In this case, we will send a sync message to our BrowserParent, which in
3014 // turn will send a sync message to the Compositor of the widget owning this
3015 // tab. This guarantees the correct association is in place before our
3016 // PLayerTransaction constructor message arrives on the cross-process
3017 // compositor bridge.
3018 CompositorOptions options
;
3019 SendEnsureLayersConnected(&options
);
3020 mCompositorOptions
= Some(options
);
3022 bool success
= false;
3023 RefPtr
<CompositorBridgeChild
> cb
= CompositorBridgeChild::Get();
3026 success
= CreateRemoteLayerManager(cb
);
3030 NS_WARNING("failed to recreate layer manager");
3034 mLayersConnected
= Some(true);
3035 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
3036 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
3039 if (nsCOMPtr
<Document
> doc
= GetTopLevelDocument()) {
3040 doc
->NotifyLayerManagerRecreated();
3043 if (mRenderLayers
) {
3048 void BrowserChild::ReinitRenderingForDeviceReset() {
3049 RefPtr
<WebRenderLayerManager
> lm
=
3050 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3052 lm
->DoDestroy(/* aIsSync */ true);
3055 // Proceed with destroying and recreating the layer manager.
3060 BrowserChild::OnShowTooltip(int32_t aXCoords
, int32_t aYCoords
,
3061 const nsAString
& aTipText
,
3062 const nsAString
& aTipDir
) {
3063 nsString
str(aTipText
);
3064 nsString
dir(aTipDir
);
3065 SendShowTooltip(aXCoords
, aYCoords
, str
, dir
);
3070 BrowserChild::OnHideTooltip() {
3075 void BrowserChild::NotifyJankedAnimations(
3076 const nsTArray
<uint64_t>& aJankedAnimations
) {
3077 MOZ_ASSERT(mPuppetWidget
);
3078 RefPtr
<WebRenderLayerManager
> lm
=
3079 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3081 lm
->UpdatePartialPrerenderedAnimations(aJankedAnimations
);
3085 mozilla::ipc::IPCResult
BrowserChild::RecvUIResolutionChanged(
3086 const float& aDpi
, const int32_t& aRounding
, const double& aScale
) {
3087 ScreenIntSize oldScreenSize
= GetInnerSize();
3089 mPuppetWidget
->UpdateBackingScaleCache(aDpi
, aRounding
, aScale
);
3092 ScreenIntSize screenSize
= GetInnerSize();
3093 if (mHasValidInnerSize
&& oldScreenSize
!= screenSize
) {
3094 ScreenIntRect screenRect
= GetOuterRect();
3096 // See RecvUpdateDimensions for the order of these operations.
3097 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
3098 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
3099 nsIBaseWindow::eRepaint
);
3101 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3102 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
3103 screenSize
.width
, screenSize
.height
, true);
3106 nsCOMPtr
<Document
> document(GetTopLevelDocument());
3107 RefPtr
<nsPresContext
> presContext
=
3108 document
? document
->GetPresContext() : nullptr;
3110 presContext
->UIResolutionChangedSync();
3116 mozilla::ipc::IPCResult
BrowserChild::RecvSafeAreaInsetsChanged(
3117 const mozilla::ScreenIntMargin
& aSafeAreaInsets
) {
3118 mPuppetWidget
->UpdateSafeAreaInsets(aSafeAreaInsets
);
3120 nsCOMPtr
<nsIScreenManager
> screenMgr
=
3121 do_GetService("@mozilla.org/gfx/screenmanager;1");
3122 ScreenIntMargin currentSafeAreaInsets
;
3124 // aSafeAreaInsets is for current screen. But we have to calculate
3125 // safe insets for content window.
3126 int32_t x
, y
, cx
, cy
;
3127 GetDimensions(DimensionKind::Outer
, &x
, &y
, &cx
, &cy
);
3128 nsCOMPtr
<nsIScreen
> screen
;
3129 screenMgr
->ScreenForRect(x
, y
, cx
, cy
, getter_AddRefs(screen
));
3132 LayoutDeviceIntRect
windowRect(x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3133 y
+ mClientOffset
.y
+ mChromeOffset
.y
, cx
,
3135 currentSafeAreaInsets
= nsContentUtils::GetWindowSafeAreaInsets(
3136 screen
, aSafeAreaInsets
, windowRect
);
3140 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
3141 nsPresContext
* presContext
= document
->GetPresContext();
3143 presContext
->SetSafeAreaInsets(currentSafeAreaInsets
);
3147 // https://github.com/w3c/csswg-drafts/issues/4670
3148 // Actually we don't set this value on sub document. This behaviour is
3149 // same as Blink that safe area insets isn't set on sub document.
3154 mozilla::ipc::IPCResult
BrowserChild::RecvAllowScriptsToClose() {
3155 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
3157 nsGlobalWindowOuter::Cast(window
)->AllowScriptsToClose();
3162 mozilla::ipc::IPCResult
BrowserChild::RecvReleaseAllPointerCapture() {
3163 PointerEventHandler::ReleaseAllPointerCapture();
3167 PPaymentRequestChild
* BrowserChild::AllocPPaymentRequestChild() {
3169 "We should never be manually allocating PPaymentRequestChild actors");
3173 bool BrowserChild::DeallocPPaymentRequestChild(PPaymentRequestChild
* actor
) {
3178 ScreenIntSize
BrowserChild::GetInnerSize() {
3179 LayoutDeviceIntSize innerSize
=
3180 RoundedToInt(mUnscaledInnerSize
* mPuppetWidget
->GetDefaultScale());
3181 return ViewAs
<ScreenPixel
>(
3182 innerSize
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3185 Maybe
<nsRect
> BrowserChild::GetVisibleRect() const {
3187 // We are conservative about visible rects for top-level browsers to avoid
3188 // artifacts when resizing
3191 return mEffectsInfo
.mVisibleRect
;
3194 Maybe
<LayoutDeviceRect
>
3195 BrowserChild::GetTopLevelViewportVisibleRectInSelfCoords() const {
3200 if (!mChildToParentConversionMatrix
) {
3201 // We have no way to tell this remote document visible rect right now.
3205 Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
> inverse
=
3206 mChildToParentConversionMatrix
->MaybeInverse();
3211 // Convert the remote document visible rect to the coordinate system of the
3213 Maybe
<LayoutDeviceRect
> rect
= UntransformBy(
3215 ViewAs
<LayoutDevicePixel
>(
3216 mTopLevelViewportVisibleRectInBrowserCoords
,
3217 PixelCastJustification::ContentProcessIsLayerInUiProcess
),
3218 LayoutDeviceRect::MaxIntRect());
3226 ScreenIntRect
BrowserChild::GetOuterRect() {
3227 LayoutDeviceIntRect outerRect
=
3228 RoundedToInt(mUnscaledOuterRect
* mPuppetWidget
->GetDefaultScale());
3229 return ViewAs
<ScreenPixel
>(
3230 outerRect
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3233 void BrowserChild::PaintWhileInterruptingJS() {
3234 if (!IPCOpen() || !mPuppetWidget
|| !mPuppetWidget
->HasWindowRenderer()) {
3235 // Don't bother doing anything now. Better to wait until we receive the
3236 // message on the PContent channel.
3240 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
3241 nsAutoScriptBlocker scriptBlocker
;
3242 RecvRenderLayers(/* aEnabled = */ true);
3245 void BrowserChild::UnloadLayersWhileInterruptingJS() {
3246 if (!IPCOpen() || !mPuppetWidget
|| !mPuppetWidget
->HasWindowRenderer()) {
3247 // Don't bother doing anything now. Better to wait until we receive the
3248 // message on the PContent channel.
3252 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
3253 nsAutoScriptBlocker scriptBlocker
;
3254 RecvRenderLayers(/* aEnabled = */ false);
3257 nsresult
BrowserChild::CanCancelContentJS(
3258 nsIRemoteTab::NavigationType aNavigationType
, int32_t aNavigationIndex
,
3259 nsIURI
* aNavigationURI
, int32_t aEpoch
, bool* aCanCancel
) {
3261 *aCanCancel
= false;
3263 if (aEpoch
<= mCancelContentJSEpoch
) {
3264 // The next page loaded before we got here, so we shouldn't try to cancel
3269 // If we have session history in the parent we've already performed
3270 // the checks following, so we can return early.
3271 if (mozilla::SessionHistoryInParent()) {
3276 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
3277 nsCOMPtr
<nsISHistory
> history
;
3279 history
= nsDocShell::Cast(docShell
)->GetSessionHistory()->LegacySHistory();
3283 return NS_ERROR_FAILURE
;
3287 rv
= history
->GetIndex(¤t
);
3288 NS_ENSURE_SUCCESS(rv
, rv
);
3290 if (current
== -1) {
3291 // This tab has no history! Just return.
3295 nsCOMPtr
<nsISHEntry
> entry
;
3296 rv
= history
->GetEntryAtIndex(current
, getter_AddRefs(entry
));
3297 NS_ENSURE_SUCCESS(rv
, rv
);
3299 nsCOMPtr
<nsIURI
> currentURI
= entry
->GetURI();
3300 if (!currentURI
->SchemeIs("http") && !currentURI
->SchemeIs("https") &&
3301 !currentURI
->SchemeIs("file")) {
3302 // Only cancel content JS for http(s) and file URIs. Other URIs are probably
3303 // internal and we should just let them run to completion.
3307 if (aNavigationType
== nsIRemoteTab::NAVIGATE_BACK
) {
3308 aNavigationIndex
= current
- 1;
3309 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_FORWARD
) {
3310 aNavigationIndex
= current
+ 1;
3311 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_URL
) {
3312 if (!aNavigationURI
) {
3313 return NS_ERROR_FAILURE
;
3316 if (aNavigationURI
->SchemeIs("javascript")) {
3317 // "javascript:" URIs don't (necessarily) trigger navigation to a
3318 // different page, so don't allow the current page's JS to terminate.
3322 // If navigating directly to a URL (e.g. via hitting Enter in the location
3323 // bar), then we can cancel anytime the next URL is different from the
3324 // current, *excluding* the ref ("#").
3326 rv
= currentURI
->EqualsExceptRef(aNavigationURI
, &equals
);
3327 NS_ENSURE_SUCCESS(rv
, rv
);
3328 *aCanCancel
= !equals
;
3331 // Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't
3332 // need to do anything special.
3334 int32_t delta
= aNavigationIndex
> current
? 1 : -1;
3335 for (int32_t i
= current
+ delta
; i
!= aNavigationIndex
+ delta
; i
+= delta
) {
3336 nsCOMPtr
<nsISHEntry
> nextEntry
;
3337 // If `i` happens to be negative, this call will fail (which is what we
3338 // would want to happen).
3339 rv
= history
->GetEntryAtIndex(i
, getter_AddRefs(nextEntry
));
3340 NS_ENSURE_SUCCESS(rv
, rv
);
3342 nsCOMPtr
<nsISHEntry
> laterEntry
= delta
== 1 ? nextEntry
: entry
;
3343 nsCOMPtr
<nsIURI
> thisURI
= entry
->GetURI();
3344 nsCOMPtr
<nsIURI
> nextURI
= nextEntry
->GetURI();
3346 // If we changed origin and the load wasn't in a subframe, we know it was
3347 // a full document load, so we can cancel the content JS safely.
3348 if (!laterEntry
->GetIsSubFrame()) {
3349 nsAutoCString thisHost
;
3350 rv
= thisURI
->GetPrePath(thisHost
);
3351 NS_ENSURE_SUCCESS(rv
, rv
);
3353 nsAutoCString nextHost
;
3354 rv
= nextURI
->GetPrePath(nextHost
);
3355 NS_ENSURE_SUCCESS(rv
, rv
);
3357 if (!thisHost
.Equals(nextHost
)) {
3369 NS_IMETHODIMP
BrowserChild::OnStateChange(nsIWebProgress
* aWebProgress
,
3370 nsIRequest
* aRequest
,
3371 uint32_t aStateFlags
,
3373 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3377 // We shouldn't need to notify the parent of redirect state changes, since
3378 // with DocumentChannel that only happens when we switch to the real channel,
3379 // and that's an implementation detail that we can hide.
3380 if (aStateFlags
& nsIWebProgressListener::STATE_IS_REDIRECTED_DOCUMENT
) {
3384 // Our OnStateChange call must have provided the nsIDocShell which the source
3385 // comes from. We'll use this to locate the corresponding BrowsingContext in
3386 // the parent process.
3387 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3389 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3390 return NS_ERROR_UNEXPECTED
;
3393 WebProgressData webProgressData
;
3394 Maybe
<WebProgressStateChangeData
> stateChangeData
;
3395 RequestData requestData
;
3397 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3400 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3401 if (browsingContext
->IsTopContent()) {
3402 stateChangeData
.emplace();
3404 stateChangeData
->isNavigating() = docShell
->GetIsNavigating();
3405 stateChangeData
->mayEnableCharacterEncodingMenu() =
3406 docShell
->GetMayEnableCharacterEncodingMenu();
3408 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3409 if (document
&& aStateFlags
& nsIWebProgressListener::STATE_STOP
) {
3410 document
->GetContentType(stateChangeData
->contentType());
3411 document
->GetCharacterSet(stateChangeData
->charset());
3412 stateChangeData
->documentURI() = document
->GetDocumentURIObject();
3414 stateChangeData
->contentType().SetIsVoid(true);
3415 stateChangeData
->charset().SetIsVoid(true);
3419 Unused
<< SendOnStateChange(webProgressData
, requestData
, aStateFlags
,
3420 aStatus
, stateChangeData
);
3425 NS_IMETHODIMP
BrowserChild::OnProgressChange(nsIWebProgress
* aWebProgress
,
3426 nsIRequest
* aRequest
,
3427 int32_t aCurSelfProgress
,
3428 int32_t aMaxSelfProgress
,
3429 int32_t aCurTotalProgress
,
3430 int32_t aMaxTotalProgress
) {
3431 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3435 // FIXME: We currently ignore ProgressChange events from out-of-process
3436 // subframes both here and in BrowserParent. We may want to change this
3437 // behaviour in the future.
3438 if (!GetBrowsingContext()->IsTopContent()) {
3442 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3443 // nullptr or 0 for all arguments other than aCurTotalProgress and
3444 // aMaxTotalProgress. Don't bother sending them.
3445 MOZ_ASSERT(!aWebProgress
);
3446 MOZ_ASSERT(!aRequest
);
3447 MOZ_ASSERT(aCurSelfProgress
== 0);
3448 MOZ_ASSERT(aMaxSelfProgress
== 0);
3450 Unused
<< SendOnProgressChange(aCurTotalProgress
, aMaxTotalProgress
);
3455 NS_IMETHODIMP
BrowserChild::OnLocationChange(nsIWebProgress
* aWebProgress
,
3456 nsIRequest
* aRequest
,
3459 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3463 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3465 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3466 return NS_ERROR_UNEXPECTED
;
3469 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3470 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3475 WebProgressData webProgressData
;
3476 RequestData requestData
;
3478 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3481 Maybe
<WebProgressLocationChangeData
> locationChangeData
;
3483 bool canGoBack
= false;
3484 bool canGoForward
= false;
3485 if (!mozilla::SessionHistoryInParent()) {
3486 MOZ_TRY(WebNavigation()->GetCanGoBack(&canGoBack
));
3487 MOZ_TRY(WebNavigation()->GetCanGoForward(&canGoForward
));
3490 if (browsingContext
->IsTopContent()) {
3492 browsingContext
== GetBrowsingContext(),
3493 "Toplevel content BrowsingContext which isn't GetBrowsingContext()?");
3495 locationChangeData
.emplace();
3497 document
->GetContentType(locationChangeData
->contentType());
3498 locationChangeData
->isNavigating() = docShell
->GetIsNavigating();
3499 locationChangeData
->documentURI() = document
->GetDocumentURIObject();
3500 document
->GetTitle(locationChangeData
->title());
3501 document
->GetCharacterSet(locationChangeData
->charset());
3503 locationChangeData
->mayEnableCharacterEncodingMenu() =
3504 docShell
->GetMayEnableCharacterEncodingMenu();
3506 locationChangeData
->contentPrincipal() = document
->NodePrincipal();
3507 locationChangeData
->contentPartitionedPrincipal() =
3508 document
->PartitionedPrincipal();
3509 locationChangeData
->csp() = document
->GetCsp();
3510 locationChangeData
->referrerInfo() = document
->ReferrerInfo();
3511 locationChangeData
->isSyntheticDocument() = document
->IsSyntheticDocument();
3513 if (nsCOMPtr
<nsILoadGroup
> loadGroup
= document
->GetDocumentLoadGroup()) {
3514 uint64_t requestContextID
= 0;
3515 MOZ_TRY(loadGroup
->GetRequestContextID(&requestContextID
));
3516 locationChangeData
->requestContextID() = Some(requestContextID
);
3519 #ifdef MOZ_CRASHREPORTER
3520 if (CrashReporter::GetEnabled()) {
3521 nsCOMPtr
<nsIURI
> annotationURI
;
3524 NS_MutateURI(aLocation
).SetUserPass(""_ns
).Finalize(annotationURI
);
3526 if (NS_FAILED(rv
)) {
3527 // Ignore failures on about: URIs.
3528 annotationURI
= aLocation
;
3531 CrashReporter::RecordAnnotationNSCString(
3532 CrashReporter::Annotation::URL
, annotationURI
->GetSpecOrDefault());
3537 Unused
<< SendOnLocationChange(webProgressData
, requestData
, aLocation
,
3538 aFlags
, canGoBack
, canGoForward
,
3539 locationChangeData
);
3544 NS_IMETHODIMP
BrowserChild::OnStatusChange(nsIWebProgress
* aWebProgress
,
3545 nsIRequest
* aRequest
,
3547 const char16_t
* aMessage
) {
3548 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3552 // FIXME: We currently ignore StatusChange from out-of-process subframes both
3553 // here and in BrowserParent. We may want to change this behaviour in the
3555 if (!GetBrowsingContext()->IsTopContent()) {
3559 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3560 // nullptr or NS_OK for all arguments other than aMessage. Don't bother
3562 MOZ_ASSERT(!aWebProgress
);
3563 MOZ_ASSERT(!aRequest
);
3564 MOZ_ASSERT(aStatus
== NS_OK
);
3566 Unused
<< SendOnStatusChange(nsDependentString(aMessage
));
3571 NS_IMETHODIMP
BrowserChild::OnSecurityChange(nsIWebProgress
* aWebProgress
,
3572 nsIRequest
* aRequest
,
3574 // Security changes are now handled entirely in the parent process
3575 // so we don't need to worry about forwarding them (and we shouldn't
3576 // be receiving any to forward).
3580 NS_IMETHODIMP
BrowserChild::OnContentBlockingEvent(nsIWebProgress
* aWebProgress
,
3581 nsIRequest
* aRequest
,
3583 // The OnContentBlockingEvent only happenes in the parent process. It should
3584 // not be seen in the content process.
3585 MOZ_DIAGNOSTIC_ASSERT(
3586 false, "OnContentBlockingEvent should not be seen in content process.");
3587 return NS_ERROR_NOT_IMPLEMENTED
;
3590 NS_IMETHODIMP
BrowserChild::OnProgressChange64(nsIWebProgress
* aWebProgress
,
3591 nsIRequest
* aRequest
,
3592 int64_t aCurSelfProgress
,
3593 int64_t aMaxSelfProgress
,
3594 int64_t aCurTotalProgress
,
3595 int64_t aMaxTotalProgress
) {
3596 // All the events we receive are filtered through an nsBrowserStatusFilter,
3597 // which accepts ProgressChange64 events, but truncates the progress values to
3598 // uint32_t and calls OnProgressChange.
3599 return NS_ERROR_NOT_IMPLEMENTED
;
3602 NS_IMETHODIMP
BrowserChild::OnRefreshAttempted(nsIWebProgress
* aWebProgress
,
3603 nsIURI
* aRefreshURI
,
3604 uint32_t aMillis
, bool aSameURI
,
3606 NS_ENSURE_ARG_POINTER(aOut
);
3612 NS_IMETHODIMP
BrowserChild::NotifyNavigationFinished() {
3613 Unused
<< SendNavigationFinished();
3617 nsresult
BrowserChild::PrepareRequestData(nsIRequest
* aRequest
,
3618 RequestData
& aRequestData
) {
3619 nsCOMPtr
<nsIChannel
> channel
= do_QueryInterface(aRequest
);
3621 aRequestData
.requestURI() = nullptr;
3625 nsresult rv
= channel
->GetURI(getter_AddRefs(aRequestData
.requestURI()));
3626 NS_ENSURE_SUCCESS(rv
, rv
);
3628 rv
= channel
->GetOriginalURI(
3629 getter_AddRefs(aRequestData
.originalRequestURI()));
3630 NS_ENSURE_SUCCESS(rv
, rv
);
3632 nsCOMPtr
<nsIClassifiedChannel
> classifiedChannel
= do_QueryInterface(channel
);
3633 if (classifiedChannel
) {
3634 rv
= classifiedChannel
->GetMatchedList(aRequestData
.matchedList());
3635 NS_ENSURE_SUCCESS(rv
, rv
);
3640 nsresult
BrowserChild::PrepareProgressListenerData(
3641 nsIWebProgress
* aWebProgress
, nsIRequest
* aRequest
,
3642 WebProgressData
& aWebProgressData
, RequestData
& aRequestData
) {
3643 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3645 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3646 return NS_ERROR_UNEXPECTED
;
3649 aWebProgressData
.browsingContext() = docShell
->GetBrowsingContext();
3650 nsresult rv
= aWebProgress
->GetLoadType(&aWebProgressData
.loadType());
3651 NS_ENSURE_SUCCESS(rv
, rv
);
3653 return PrepareRequestData(aRequest
, aRequestData
);
3656 void BrowserChild::UpdateSessionStore() {
3657 if (mSessionStoreChild
) {
3658 mSessionStoreChild
->UpdateSessionStore();
3663 RefPtr
<PBrowserChild::IsWindowSupportingProtectedMediaPromise
>
3664 BrowserChild::DoesWindowSupportProtectedMedia() {
3667 "Protected media support check should be done on main thread only.");
3668 if (mWindowSupportsProtectedMedia
) {
3669 // If we've already checked and have a cached result, resolve with that.
3670 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3671 mWindowSupportsProtectedMedia
.value(), __func__
);
3673 RefPtr
<BrowserChild
> self
= this;
3674 // We chain off the promise rather than passing it directly so we can cache
3675 // the result and use that for future calls.
3676 return SendIsWindowSupportingProtectedMedia(ChromeOuterWindowID())
3678 GetCurrentSerialEventTarget(), __func__
,
3679 [self
](bool isSupported
) {
3680 // If a result was cached while this check was inflight, ensure the
3683 self
->mWindowSupportsProtectedMedia
,
3684 self
->mWindowSupportsProtectedMedia
.value() == isSupported
);
3685 // Cache the response as it will not change during the lifetime
3687 self
->mWindowSupportsProtectedMedia
= Some(isSupported
);
3688 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3689 self
->mWindowSupportsProtectedMedia
.value(), __func__
);
3691 [](ResponseRejectReason reason
) {
3692 return IsWindowSupportingProtectedMediaPromise::CreateAndReject(
3698 void BrowserChild::NotifyContentBlockingEvent(
3699 uint32_t aEvent
, nsIChannel
* aChannel
, bool aBlocked
,
3700 const nsACString
& aTrackingOrigin
,
3701 const nsTArray
<nsCString
>& aTrackingFullHashes
,
3703 mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
3705 const Maybe
<ContentBlockingNotifier::CanvasFingerprinter
>&
3706 aCanvasFingerprinter
,
3707 const Maybe
<bool> aCanvasFingerprinterKnownText
) {
3712 RequestData requestData
;
3713 if (NS_SUCCEEDED(PrepareRequestData(aChannel
, requestData
))) {
3714 Unused
<< SendNotifyContentBlockingEvent(
3715 aEvent
, requestData
, aBlocked
, PromiseFlatCString(aTrackingOrigin
),
3716 aTrackingFullHashes
, aReason
, aCanvasFingerprinter
,
3717 aCanvasFingerprinterKnownText
);
3722 BrowserChild::ContentTransformsReceived(JSContext
* aCx
,
3723 dom::Promise
** aPromise
) {
3724 auto* globalObject
= xpc::CurrentNativeGlobal(aCx
);
3726 if (mChildToParentConversionMatrix
) {
3727 // Already received content transforms
3728 RefPtr
<Promise
> promise
=
3729 Promise::CreateResolvedWithUndefined(globalObject
, rv
);
3730 promise
.forget(aPromise
);
3731 return rv
.StealNSResult();
3734 if (!mContentTransformPromise
) {
3735 mContentTransformPromise
= Promise::Create(globalObject
, rv
);
3738 MOZ_ASSERT(globalObject
== mContentTransformPromise
->GetGlobalObject());
3739 NS_IF_ADDREF(*aPromise
= mContentTransformPromise
);
3740 return rv
.StealNSResult();
3743 BrowserChildMessageManager::BrowserChildMessageManager(
3744 BrowserChild
* aBrowserChild
)
3745 : ContentFrameMessageManager(new nsFrameMessageManager(aBrowserChild
)),
3746 mBrowserChild(aBrowserChild
) {}
3748 BrowserChildMessageManager::~BrowserChildMessageManager() = default;
3750 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChildMessageManager
)
3752 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BrowserChildMessageManager
,
3753 DOMEventTargetHelper
)
3754 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager
);
3755 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild
);
3756 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
3757 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
3759 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BrowserChildMessageManager
,
3760 DOMEventTargetHelper
)
3761 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager
)
3762 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild
)
3763 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
3765 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChildMessageManager
)
3766 NS_INTERFACE_MAP_ENTRY(nsIMessageSender
)
3767 NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentFrameMessageManager
)
3768 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
3769 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
3771 NS_IMPL_ADDREF_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3772 NS_IMPL_RELEASE_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3774 JSObject
* BrowserChildMessageManager::WrapObject(
3775 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
3776 return ContentFrameMessageManager_Binding::Wrap(aCx
, this, aGivenProto
);
3779 void BrowserChildMessageManager::MarkForCC() {
3780 if (mBrowserChild
) {
3781 mBrowserChild
->MarkScopesForCC();
3783 EventListenerManager
* elm
= GetExistingListenerManager();
3787 MessageManagerGlobal::MarkForCC();
3790 Nullable
<WindowProxyHolder
> BrowserChildMessageManager::GetContent(
3791 ErrorResult
& aError
) {
3792 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell(aError
);
3796 return WindowProxyHolder(docShell
->GetBrowsingContext());
3799 already_AddRefed
<nsIDocShell
> BrowserChildMessageManager::GetDocShell(
3800 ErrorResult
& aError
) {
3801 if (!mBrowserChild
) {
3802 aError
.Throw(NS_ERROR_NULL_POINTER
);
3805 nsCOMPtr
<nsIDocShell
> window
=
3806 do_GetInterface(mBrowserChild
->WebNavigation());
3807 return window
.forget();
3810 already_AddRefed
<nsIEventTarget
>
3811 BrowserChildMessageManager::GetTabEventTarget() {
3812 return do_AddRef(GetMainThreadSerialEventTarget());
3815 nsresult
BrowserChildMessageManager::Dispatch(
3816 already_AddRefed
<nsIRunnable
>&& aRunnable
) const {
3817 return SchedulerGroup::Dispatch(std::move(aRunnable
));