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 (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) {
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::AnnotateCrashReport(CrashReporter::Annotation::URL
, spec
);
821 mozilla::ipc::IPCResult
BrowserChild::RecvCreateAboutBlankDocumentViewer(
822 nsIPrincipal
* aPrincipal
, nsIPrincipal
* aPartitionedPrincipal
) {
823 if (aPrincipal
->GetIsExpandedPrincipal() ||
824 aPartitionedPrincipal
->GetIsExpandedPrincipal()) {
825 return IPC_FAIL(this, "Cannot create document with an expanded principal");
827 if (aPrincipal
->IsSystemPrincipal() ||
828 aPartitionedPrincipal
->IsSystemPrincipal()) {
829 MOZ_ASSERT_UNREACHABLE(
830 "Cannot use CreateAboutBlankDocumentViewer to create system principal "
831 "document in content");
835 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
837 MOZ_ASSERT_UNREACHABLE("WebNavigation does not have a docshell");
841 nsCOMPtr
<nsIURI
> currentURI
;
843 WebNavigation()->GetCurrentURI(getter_AddRefs(currentURI
)));
844 if (!currentURI
|| !NS_IsAboutBlank(currentURI
)) {
845 NS_WARNING("Can't create a ContentViewer unless on about:blank");
849 docShell
->CreateAboutBlankDocumentViewer(aPrincipal
, aPartitionedPrincipal
,
854 mozilla::ipc::IPCResult
BrowserChild::RecvResumeLoad(
855 const uint64_t& aPendingSwitchID
, const ParentShowInfo
& aInfo
) {
856 if (!mDidLoadURLInit
) {
857 mDidLoadURLInit
= true;
858 if (!InitBrowserChildMessageManager()) {
859 return IPC_FAIL_NO_REASON(this);
862 ApplyParentShowInfo(aInfo
);
865 nsresult rv
= WebNavigation()->ResumeRedirectedLoad(aPendingSwitchID
, -1);
867 NS_WARNING("WebNavigation()->ResumeRedirectedLoad failed");
873 nsresult
BrowserChild::CloneDocumentTreeIntoSelf(
874 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
875 const embedding::PrintData
& aPrintData
) {
877 if (NS_WARN_IF(aSourceBC
.IsNullOrDiscarded())) {
878 return NS_ERROR_FAILURE
;
880 nsCOMPtr
<Document
> sourceDocument
= aSourceBC
.get()->GetDocument();
881 if (NS_WARN_IF(!sourceDocument
)) {
882 return NS_ERROR_FAILURE
;
885 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
886 if (NS_WARN_IF(!ourDocShell
)) {
887 return NS_ERROR_FAILURE
;
890 nsCOMPtr
<nsIDocumentViewer
> viewer
;
891 ourDocShell
->GetDocViewer(getter_AddRefs(viewer
));
892 if (NS_WARN_IF(!viewer
)) {
893 return NS_ERROR_FAILURE
;
896 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
897 do_GetService("@mozilla.org/gfx/printsettings-service;1");
898 if (NS_WARN_IF(!printSettingsSvc
)) {
899 return NS_ERROR_FAILURE
;
902 nsCOMPtr
<nsIPrintSettings
> printSettings
;
904 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
905 if (NS_WARN_IF(NS_FAILED(rv
))) {
909 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
911 RefPtr
<Document
> clone
;
913 AutoPrintEventDispatcher
dispatcher(*sourceDocument
);
914 nsAutoScriptBlocker scriptBlocker
;
915 bool hasInProcessCallbacks
= false;
916 clone
= sourceDocument
->CreateStaticClone(
917 ourDocShell
, viewer
, printSettings
, &hasInProcessCallbacks
);
918 if (NS_WARN_IF(!clone
)) {
919 return NS_ERROR_FAILURE
;
923 rv
= UpdateRemotePrintSettings(aPrintData
);
932 mozilla::ipc::IPCResult
BrowserChild::RecvCloneDocumentTreeIntoSelf(
933 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
934 const embedding::PrintData
& aPrintData
,
935 CloneDocumentTreeIntoSelfResolver
&& aResolve
) {
939 rv
= CloneDocumentTreeIntoSelf(aSourceBC
, aPrintData
);
942 aResolve(NS_SUCCEEDED(rv
));
946 nsresult
BrowserChild::UpdateRemotePrintSettings(
947 const embedding::PrintData
& aPrintData
) {
949 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
950 if (NS_WARN_IF(!ourDocShell
)) {
951 return NS_ERROR_FAILURE
;
954 RefPtr
<Document
> doc
= ourDocShell
->GetExtantDocument();
955 if (NS_WARN_IF(!doc
) || NS_WARN_IF(!doc
->IsStaticDocument())) {
956 return NS_ERROR_FAILURE
;
959 RefPtr
<BrowsingContext
> bc
= ourDocShell
->GetBrowsingContext();
960 if (NS_WARN_IF(!bc
)) {
961 return NS_ERROR_FAILURE
;
964 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
965 do_GetService("@mozilla.org/gfx/printsettings-service;1");
966 if (NS_WARN_IF(!printSettingsSvc
)) {
967 return NS_ERROR_FAILURE
;
970 nsCOMPtr
<nsIPrintSettings
> printSettings
;
972 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
973 if (NS_WARN_IF(NS_FAILED(rv
))) {
977 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
979 bc
->PreOrderWalk([&](BrowsingContext
* aBc
) {
980 if (nsCOMPtr
<nsIDocShell
> inProcess
= aBc
->GetDocShell()) {
981 nsCOMPtr
<nsIDocumentViewer
> viewer
;
982 inProcess
->GetDocViewer(getter_AddRefs(viewer
));
983 if (NS_WARN_IF(!viewer
)) {
984 return BrowsingContext::WalkFlag::Skip
;
986 // The CanRunScript analysis is not smart enough to see across
987 // the std::function PreOrderWalk uses, so we cheat a bit here, but it is
988 // fine because PreOrderWalk does deal with arbitrary script changing the
989 // BC tree, and our code above is simple enough and keeps strong refs to
991 ([&]() MOZ_CAN_RUN_SCRIPT_BOUNDARY
{
992 RefPtr
<RemotePrintJobChild
> printJob
=
993 static_cast<RemotePrintJobChild
*>(
994 aPrintData
.remotePrintJob().AsChild());
995 viewer
->SetPrintSettingsForSubdocument(printSettings
, printJob
);
997 } else if (RefPtr
<BrowserBridgeChild
> remoteChild
=
998 BrowserBridgeChild::GetFrom(aBc
->GetEmbedderElement())) {
999 Unused
<< remoteChild
->SendUpdateRemotePrintSettings(aPrintData
);
1000 return BrowsingContext::WalkFlag::Skip
;
1002 return BrowsingContext::WalkFlag::Next
;
1009 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemotePrintSettings(
1010 const embedding::PrintData
& aPrintData
) {
1012 UpdateRemotePrintSettings(aPrintData
);
1018 void BrowserChild::DoFakeShow(const ParentShowInfo
& aParentShowInfo
) {
1019 OwnerShowInfo ownerInfo
{ScreenIntSize(), ScrollbarPreference::Auto
,
1021 RecvShow(aParentShowInfo
, ownerInfo
);
1022 mDidFakeShow
= true;
1025 void BrowserChild::ApplyParentShowInfo(const ParentShowInfo
& aInfo
) {
1026 // Even if we already set real show info, the dpi / rounding & scale may still
1027 // be invalid (if BrowserParent wasn't able to get widget it would just send
1028 // 0). So better to always set up-to-date values here.
1029 if (aInfo
.dpi() > 0) {
1030 mPuppetWidget
->UpdateBackingScaleCache(aInfo
.dpi(), aInfo
.widgetRounding(),
1031 aInfo
.defaultScale());
1034 if (mDidSetRealShowInfo
) {
1038 if (!aInfo
.fakeShowInfo()) {
1039 // Once we've got one ShowInfo from parent, no need to update the values
1041 mDidSetRealShowInfo
= true;
1044 mIsTransparent
= aInfo
.isTransparent();
1047 mozilla::ipc::IPCResult
BrowserChild::RecvShow(
1048 const ParentShowInfo
& aParentInfo
, const OwnerShowInfo
& aOwnerInfo
) {
1051 mPuppetWidget
->SetSizeMode(aOwnerInfo
.sizeMode());
1052 if (!mDidFakeShow
) {
1053 nsCOMPtr
<nsIBaseWindow
> baseWindow
= do_QueryInterface(WebNavigation());
1055 NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
1056 return IPC_FAIL_NO_REASON(this);
1059 baseWindow
->SetVisibility(true);
1060 res
= InitBrowserChildMessageManager();
1063 ApplyParentShowInfo(aParentInfo
);
1066 RecvScrollbarPreferenceChanged(aOwnerInfo
.scrollbarPreference());
1070 return IPC_FAIL_NO_REASON(this);
1078 mozilla::ipc::IPCResult
BrowserChild::RecvInitRendering(
1079 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
1080 const layers::LayersId
& aLayersId
,
1081 const CompositorOptions
& aCompositorOptions
, const bool& aLayersConnected
) {
1082 mLayersConnected
= Some(aLayersConnected
);
1083 mLayersConnectRequested
= Some(aLayersConnected
);
1084 InitRenderingState(aTextureFactoryIdentifier
, aLayersId
, aCompositorOptions
);
1088 mozilla::ipc::IPCResult
BrowserChild::RecvScrollbarPreferenceChanged(
1089 ScrollbarPreference aPreference
) {
1090 MOZ_ASSERT(!mIsTopLevel
,
1091 "Scrollbar visibility should be derived from chrome flags for "
1092 "top-level windows");
1093 if (nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation())) {
1094 nsDocShell::Cast(docShell
)->SetScrollbarPreference(aPreference
);
1099 mozilla::ipc::IPCResult
BrowserChild::RecvCompositorOptionsChanged(
1100 const CompositorOptions
& aNewOptions
) {
1101 MOZ_ASSERT(mCompositorOptions
);
1103 // The only compositor option we currently support changing is APZ
1104 // enablement. Even that is only partially supported for now:
1105 // * Going from APZ to non-APZ is fine - we just flip the stored flag.
1106 // Note that we keep the actors (mApzcTreeManager, and the APZChild
1107 // created in InitAPZState()) around (read on for why).
1108 // * Going from non-APZ to APZ is only supported if we were using
1109 // APZ initially (at InitRendering() time) and we are transitioning
1110 // back. In this case, we just reuse the actors which we kept around.
1111 // Fully supporting a non-APZ to APZ transition (i.e. even in cases
1112 // where we initialized as non-APZ) would require setting up the actors
1113 // here. (In that case, we would also have the options of destroying
1114 // the actors in the APZ --> non-APZ case, and always re-creating them
1115 // during a non-APZ --> APZ transition).
1116 mCompositorOptions
->SetUseAPZ(aNewOptions
.UseAPZ());
1120 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateDimensions(
1121 const DimensionInfo
& aDimensionInfo
) {
1122 if (mLayersConnected
.isNothing()) {
1126 mUnscaledOuterRect
= aDimensionInfo
.rect();
1127 mClientOffset
= aDimensionInfo
.clientOffset();
1128 mChromeOffset
= aDimensionInfo
.chromeOffset();
1129 MOZ_ASSERT_IF(!IsTopLevel(), mChromeOffset
== LayoutDeviceIntPoint());
1131 SetUnscaledInnerSize(aDimensionInfo
.size());
1132 if (!mHasValidInnerSize
&& aDimensionInfo
.size().width
!= 0 &&
1133 aDimensionInfo
.size().height
!= 0) {
1134 mHasValidInnerSize
= true;
1137 ScreenIntSize screenSize
= GetInnerSize();
1138 ScreenIntRect screenRect
= GetOuterRect();
1140 // Make sure to set the size on the document viewer first. The
1141 // MobileViewportManager needs the content viewer size to be updated before
1142 // the reflow, otherwise it gets a stale size when it computes a new CSS
1144 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
1145 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
1146 nsIBaseWindow::eRepaint
);
1148 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
1149 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
1150 screenSize
.width
, screenSize
.height
, true);
1152 RecvSafeAreaInsetsChanged(mPuppetWidget
->GetSafeAreaInsets());
1157 mozilla::ipc::IPCResult
BrowserChild::RecvSizeModeChanged(
1158 const nsSizeMode
& aSizeMode
) {
1159 mPuppetWidget
->SetSizeMode(aSizeMode
);
1160 if (!mPuppetWidget
->IsVisible()) {
1163 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1167 nsPresContext
* presContext
= document
->GetPresContext();
1169 presContext
->SizeModeChanged(aSizeMode
);
1174 mozilla::ipc::IPCResult
BrowserChild::RecvChildToParentMatrix(
1175 const Maybe
<gfx::Matrix4x4
>& aMatrix
,
1176 const ScreenRect
& aTopLevelViewportVisibleRectInBrowserCoords
) {
1177 mChildToParentConversionMatrix
=
1178 LayoutDeviceToLayoutDeviceMatrix4x4::FromUnknownMatrix(aMatrix
);
1179 mTopLevelViewportVisibleRectInBrowserCoords
=
1180 aTopLevelViewportVisibleRectInBrowserCoords
;
1182 if (mContentTransformPromise
) {
1183 mContentTransformPromise
->MaybeResolveWithUndefined();
1184 mContentTransformPromise
= nullptr;
1187 // Trigger an intersection observation update since ancestor viewports
1189 if (RefPtr
<Document
> toplevelDoc
= GetTopLevelDocument()) {
1190 if (nsPresContext
* pc
= toplevelDoc
->GetPresContext()) {
1191 pc
->RefreshDriver()->EnsureIntersectionObservationsUpdateHappens();
1198 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemoteStyle(
1199 const StyleImageRendering
& aImageRendering
) {
1200 BrowsingContext
* context
= GetBrowsingContext();
1205 Document
* document
= context
->GetDocument();
1210 if (document
->IsImageDocument()) {
1211 document
->AsImageDocument()->UpdateRemoteStyle(aImageRendering
);
1217 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarMaxHeightChanged(
1218 const ScreenIntCoord
& aHeight
) {
1219 #if defined(MOZ_WIDGET_ANDROID)
1220 mDynamicToolbarMaxHeight
= aHeight
;
1222 RefPtr
<Document
> document
= GetTopLevelDocument();
1227 if (RefPtr
<nsPresContext
> presContext
= document
->GetPresContext()) {
1228 presContext
->SetDynamicToolbarMaxHeight(aHeight
);
1234 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarOffsetChanged(
1235 const ScreenIntCoord
& aOffset
) {
1236 #if defined(MOZ_WIDGET_ANDROID)
1237 RefPtr
<Document
> document
= GetTopLevelDocument();
1242 if (nsPresContext
* presContext
= document
->GetPresContext()) {
1243 presContext
->UpdateDynamicToolbarOffset(aOffset
);
1249 mozilla::ipc::IPCResult
BrowserChild::RecvSuppressDisplayport(
1250 const bool& aEnabled
) {
1251 if (RefPtr
<PresShell
> presShell
= GetTopLevelPresShell()) {
1252 presShell
->SuppressDisplayport(aEnabled
);
1257 void BrowserChild::HandleDoubleTap(const CSSPoint
& aPoint
,
1258 const Modifiers
& aModifiers
,
1259 const ScrollableLayerGuid
& aGuid
,
1260 const DoubleTapToZoomMetrics
& aMetrics
) {
1262 sApzChildLog
, LogLevel::Debug
,
1263 ("Handling double tap at %s with %p %p\n", ToString(aPoint
).c_str(),
1264 mBrowserChildMessageManager
? mBrowserChildMessageManager
->GetWrapper()
1266 mBrowserChildMessageManager
.get()));
1268 if (!mBrowserChildMessageManager
) {
1272 // Note: there is nothing to do with the modifiers here, as we are not
1273 // synthesizing any sort of mouse event.
1274 RefPtr
<Document
> document
= GetTopLevelDocument();
1275 ZoomTarget zoomTarget
= CalculateRectToZoomTo(document
, aPoint
, aMetrics
);
1276 // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
1277 // the guid of any scroll frame), but the zoom-to-rect operation must be
1278 // performed by the root content scroll frame, so query its identifiers
1279 // for the SendZoomToRect() call rather than using the ones from |aGuid|.
1280 uint32_t presShellId
;
1282 if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
1283 document
->GetDocumentElement(), &presShellId
, &viewId
) &&
1285 ScrollableLayerGuid
guid(mLayersId
, presShellId
, viewId
);
1287 mApzcTreeManager
->ZoomToRect(guid
, zoomTarget
,
1288 ZoomToRectBehavior::DEFAULT_BEHAVIOR
);
1292 mozilla::ipc::IPCResult
BrowserChild::RecvHandleTap(
1293 const GeckoContentController::TapType
& aType
,
1294 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1295 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
,
1296 const Maybe
<DoubleTapToZoomMetrics
>& aDoubleTapToZoomMetrics
) {
1297 // IPDL doesn't hold a strong reference to protocols as they're not required
1298 // to be refcounted. This function can run script, which may trigger a nested
1299 // event loop, which may release this, so we hold a strong reference here.
1300 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1301 RefPtr
<PresShell
> presShell
= GetTopLevelPresShell();
1302 if (!presShell
|| !presShell
->GetPresContext() || !mAPZEventState
) {
1305 CSSToLayoutDeviceScale
scale(
1306 presShell
->GetPresContext()->CSSToDevPixelScale());
1307 CSSPoint point
= aPoint
/ scale
;
1309 // Stash the guid in InputAPZContext so that when the visual-to-layout
1310 // transform is applied to the event's coordinates, we use the right transform
1311 // based on the scroll frame being targeted.
1312 // The other values don't really matter.
1313 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1316 case GeckoContentController::TapType::eSingleTap
:
1317 if (mBrowserChildMessageManager
) {
1318 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1319 eventState
->ProcessSingleTap(point
, scale
, aModifiers
, 1,
1323 case GeckoContentController::TapType::eDoubleTap
:
1324 HandleDoubleTap(point
, aModifiers
, aGuid
, *aDoubleTapToZoomMetrics
);
1326 case GeckoContentController::TapType::eSecondTap
:
1327 if (mBrowserChildMessageManager
) {
1328 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1329 eventState
->ProcessSingleTap(point
, scale
, aModifiers
, 2,
1333 case GeckoContentController::TapType::eLongTap
:
1334 if (mBrowserChildMessageManager
) {
1335 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1336 eventState
->ProcessLongTap(presShell
, point
, scale
, aModifiers
,
1340 case GeckoContentController::TapType::eLongTapUp
:
1341 if (mBrowserChildMessageManager
) {
1342 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1343 eventState
->ProcessLongTapUp(presShell
, point
, scale
, aModifiers
);
1350 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityHandleTap(
1351 const GeckoContentController::TapType
& aType
,
1352 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1353 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
,
1354 const Maybe
<DoubleTapToZoomMetrics
>& aDoubleTapToZoomMetrics
) {
1355 // IPDL doesn't hold a strong reference to protocols as they're not required
1356 // to be refcounted. This function can run script, which may trigger a nested
1357 // event loop, which may release this, so we hold a strong reference here.
1358 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1359 return RecvHandleTap(aType
, aPoint
, aModifiers
, aGuid
, aInputBlockId
,
1360 aDoubleTapToZoomMetrics
);
1363 void BrowserChild::NotifyAPZStateChange(
1364 const ViewID
& aViewId
,
1365 const layers::GeckoContentController::APZStateChange
& aChange
,
1366 const int& aArg
, Maybe
<uint64_t> aInputBlockId
) {
1367 if (mAPZEventState
) {
1368 mAPZEventState
->ProcessAPZStateChange(aViewId
, aChange
, aArg
,
1371 nsCOMPtr
<nsIObserverService
> observerService
=
1372 mozilla::services::GetObserverService();
1374 layers::GeckoContentController::APZStateChange::eTransformEnd
) {
1375 // This is used by tests to determine when the APZ is done doing whatever
1376 // it's doing. XXX generify this as needed when writing additional tests.
1377 observerService
->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
1378 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1380 } else if (aChange
==
1381 layers::GeckoContentController::APZStateChange::eTransformBegin
) {
1382 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1387 void BrowserChild::StartScrollbarDrag(
1388 const layers::AsyncDragMetrics
& aDragMetrics
) {
1389 ScrollableLayerGuid
guid(mLayersId
, aDragMetrics
.mPresShellId
,
1390 aDragMetrics
.mViewId
);
1392 if (mApzcTreeManager
) {
1393 mApzcTreeManager
->StartScrollbarDrag(guid
, aDragMetrics
);
1397 void BrowserChild::ZoomToRect(const uint32_t& aPresShellId
,
1398 const ScrollableLayerGuid::ViewID
& aViewId
,
1399 const CSSRect
& aRect
, const uint32_t& aFlags
) {
1400 ScrollableLayerGuid
guid(mLayersId
, aPresShellId
, aViewId
);
1402 if (mApzcTreeManager
) {
1403 mApzcTreeManager
->ZoomToRect(guid
, ZoomTarget
{aRect
}, aFlags
);
1407 mozilla::ipc::IPCResult
BrowserChild::RecvActivate(uint64_t aActionId
) {
1408 MOZ_ASSERT(mWebBrowser
);
1409 mWebBrowser
->FocusActivate(aActionId
);
1413 mozilla::ipc::IPCResult
BrowserChild::RecvDeactivate(uint64_t aActionId
) {
1414 MOZ_ASSERT(mWebBrowser
);
1415 mWebBrowser
->FocusDeactivate(aActionId
);
1419 mozilla::ipc::IPCResult
BrowserChild::RecvStopIMEStateManagement() {
1420 IMEStateManager::StopIMEStateManagement();
1424 void BrowserChild::ProcessPendingCoalescedTouchData() {
1425 MOZ_ASSERT(StaticPrefs::dom_events_coalesce_touchmove());
1427 if (mCoalescedTouchData
.IsEmpty()) {
1431 if (mCoalescedTouchMoveEventFlusher
) {
1432 mCoalescedTouchMoveEventFlusher
->RemoveObserver();
1435 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1436 mCoalescedTouchData
.TakeCoalescedEvent();
1437 Unused
<< RecvRealTouchEvent(*touchMoveEvent
,
1438 mCoalescedTouchData
.GetScrollableLayerGuid(),
1439 mCoalescedTouchData
.GetInputBlockId(),
1440 mCoalescedTouchData
.GetApzResponse());
1443 void BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() {
1444 if (!mCoalesceMouseMoveEvents
|| !mCoalescedMouseEventFlusher
) {
1445 // We don't enable mouse coalescing or we are destroying BrowserChild.
1449 // We may reentry the event loop and push more data to
1450 // mToBeDispatchedMouseData while dispatching an event.
1452 // We may have some pending coalesced data while dispatch an event and reentry
1453 // the event loop. In that case we don't have chance to consume the remainding
1454 // pending data until we get new mouse events. Get some helps from
1455 // mCoalescedMouseEventFlusher to trigger it.
1456 mCoalescedMouseEventFlusher
->StartObserver();
1458 while (mToBeDispatchedMouseData
.GetSize() > 0) {
1459 UniquePtr
<CoalescedMouseData
> data(
1460 static_cast<CoalescedMouseData
*>(mToBeDispatchedMouseData
.PopFront()));
1462 UniquePtr
<WidgetMouseEvent
> event
= data
->TakeCoalescedEvent();
1464 // Dispatch the pending events. Using HandleRealMouseButtonEvent
1465 // to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
1466 // RecvRealMouseButtonEvent because we may also put some mouse events
1467 // other than mousemove.
1468 HandleRealMouseButtonEvent(*event
, data
->GetScrollableLayerGuid(),
1469 data
->GetInputBlockId());
1472 // mCoalescedMouseEventFlusher may be destroyed when reentrying the event
1474 if (mCoalescedMouseEventFlusher
) {
1475 mCoalescedMouseEventFlusher
->RemoveObserver();
1479 LayoutDeviceToLayoutDeviceMatrix4x4
1480 BrowserChild::GetChildToParentConversionMatrix() const {
1481 if (mChildToParentConversionMatrix
) {
1482 return *mChildToParentConversionMatrix
;
1484 LayoutDevicePoint
offset(GetChromeOffset());
1485 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset
);
1488 Maybe
<ScreenRect
> BrowserChild::GetTopLevelViewportVisibleRectInBrowserCoords()
1490 if (!mChildToParentConversionMatrix
) {
1493 return Some(mTopLevelViewportVisibleRectInBrowserCoords
);
1496 void BrowserChild::FlushAllCoalescedMouseData() {
1497 MOZ_ASSERT(mCoalesceMouseMoveEvents
);
1499 // Move all entries from mCoalescedMouseData to mToBeDispatchedMouseData.
1500 for (const auto& data
: mCoalescedMouseData
.Values()) {
1501 if (!data
|| data
->IsEmpty()) {
1504 UniquePtr
<CoalescedMouseData
> dispatchData
=
1505 MakeUnique
<CoalescedMouseData
>();
1507 dispatchData
->RetrieveDataFrom(*data
);
1508 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1510 mCoalescedMouseData
.Clear();
1513 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEvent(
1514 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1515 const uint64_t& aInputBlockId
) {
1516 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
) {
1517 CoalescedMouseData
* data
=
1518 mCoalescedMouseData
.GetOrInsertNew(aEvent
.pointerId
);
1520 if (data
->CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1521 data
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1522 mCoalescedMouseEventFlusher
->StartObserver();
1525 // Can't coalesce current mousemove event. Put the coalesced mousemove data
1526 // with the same pointer id to mToBeDispatchedMouseData, coalesce the
1527 // current one, and process all pending data in mToBeDispatchedMouseData.
1528 UniquePtr
<CoalescedMouseData
> dispatchData
=
1529 MakeUnique
<CoalescedMouseData
>();
1531 dispatchData
->RetrieveDataFrom(*data
);
1532 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1534 // Put new data to replace the old one in the hash table.
1535 CoalescedMouseData
* newData
=
1537 .InsertOrUpdate(aEvent
.pointerId
, MakeUnique
<CoalescedMouseData
>())
1539 newData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1541 // Dispatch all pending mouse events.
1542 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1543 mCoalescedMouseEventFlusher
->StartObserver();
1544 } else if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1545 return IPC_FAIL_NO_REASON(this);
1550 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEventForTests(
1551 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1552 const uint64_t& aInputBlockId
) {
1553 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1556 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseMoveEvent(
1557 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1558 const uint64_t& aInputBlockId
) {
1559 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1562 mozilla::ipc::IPCResult
1563 BrowserChild::RecvNormalPriorityRealMouseMoveEventForTests(
1564 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1565 const uint64_t& aInputBlockId
) {
1566 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1569 mozilla::ipc::IPCResult
BrowserChild::RecvSynthMouseMoveEvent(
1570 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1571 const uint64_t& aInputBlockId
) {
1572 if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1573 return IPC_FAIL_NO_REASON(this);
1578 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySynthMouseMoveEvent(
1579 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1580 const uint64_t& aInputBlockId
) {
1581 return RecvSynthMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1584 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseButtonEvent(
1585 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1586 const uint64_t& aInputBlockId
) {
1587 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
&&
1588 aEvent
.mMessage
!= eMouseMove
) {
1589 // When receiving a mouse event other than mousemove, we have to dispatch
1590 // all coalesced events before it. However, we can't dispatch all pending
1591 // coalesced events directly because we may reentry the event loop while
1592 // dispatching. To make sure we won't dispatch disorder events, we move all
1593 // coalesced mousemove events and current event to a deque to dispatch them.
1594 // When reentrying the event loop and dispatching more events, we put new
1595 // events in the end of the nsQueue and dispatch events from the beginning.
1596 FlushAllCoalescedMouseData();
1598 UniquePtr
<CoalescedMouseData
> dispatchData
=
1599 MakeUnique
<CoalescedMouseData
>();
1601 dispatchData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1602 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1604 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1607 HandleRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1611 void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent
& aEvent
,
1612 const ScrollableLayerGuid
& aGuid
,
1613 const uint64_t& aInputBlockId
) {
1614 WidgetMouseEvent
localEvent(aEvent
);
1615 localEvent
.mWidget
= mPuppetWidget
;
1617 // We need one InputAPZContext here to propagate |aGuid| to places in
1618 // SendSetTargetAPZCNotification() which apply the visual-to-layout transform,
1619 // and another below to propagate the |postLayerization| flag (whose value
1620 // we don't know until SendSetTargetAPZCNotification() returns) into
1621 // the event dispatch code.
1622 InputAPZContext
context1(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1624 // Mouse events like eMouseEnterIntoWidget, that are created in the parent
1625 // process EventStateManager code, have an input block id which they get from
1626 // the InputAPZContext in the parent process stack. However, they did not
1627 // actually go through the APZ code and so their mHandledByAPZ flag is false.
1628 // Since thos events didn't go through APZ, we don't need to send
1629 // notifications for them.
1630 RefPtr
<DisplayportSetListener
> postLayerization
;
1631 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
) {
1632 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1633 postLayerization
= APZCCallbackHelper::SendSetTargetAPZCNotification(
1634 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
, aInputBlockId
);
1637 InputAPZContext
context2(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
,
1638 postLayerization
!= nullptr);
1640 DispatchWidgetEventViaAPZ(localEvent
);
1642 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
&& mAPZEventState
) {
1643 mAPZEventState
->ProcessMouseEvent(localEvent
, aInputBlockId
);
1646 // Do this after the DispatchWidgetEventViaAPZ call above, so that if the
1647 // mouse event triggered a post-refresh AsyncDragMetrics message to be sent
1648 // to APZ (from scrollbar dragging in nsSliderFrame), then that will reach
1649 // APZ before the SetTargetAPZC message. This ensures the drag input block
1650 // gets the drag metrics before handling the input events.
1651 if (postLayerization
) {
1652 postLayerization
->Register();
1656 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseButtonEvent(
1657 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1658 const uint64_t& aInputBlockId
) {
1659 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1662 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseEnterExitWidgetEvent(
1663 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1664 const uint64_t& aInputBlockId
) {
1665 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1668 mozilla::ipc::IPCResult
1669 BrowserChild::RecvNormalPriorityRealMouseEnterExitWidgetEvent(
1670 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1671 const uint64_t& aInputBlockId
) {
1672 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1675 nsEventStatus
BrowserChild::DispatchWidgetEventViaAPZ(WidgetGUIEvent
& aEvent
) {
1676 aEvent
.ResetWaitingReplyFromRemoteProcessState();
1677 return APZCCallbackHelper::DispatchWidgetEvent(aEvent
);
1680 void BrowserChild::DispatchCoalescedWheelEvent() {
1681 UniquePtr
<WidgetWheelEvent
> wheelEvent
=
1682 mCoalescedWheelData
.TakeCoalescedEvent();
1683 MOZ_ASSERT(wheelEvent
);
1684 DispatchWheelEvent(*wheelEvent
, mCoalescedWheelData
.GetScrollableLayerGuid(),
1685 mCoalescedWheelData
.GetInputBlockId());
1688 void BrowserChild::DispatchWheelEvent(const WidgetWheelEvent
& aEvent
,
1689 const ScrollableLayerGuid
& aGuid
,
1690 const uint64_t& aInputBlockId
) {
1691 WidgetWheelEvent
localEvent(aEvent
);
1692 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
) {
1693 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1694 RefPtr
<DisplayportSetListener
> postLayerization
=
1695 APZCCallbackHelper::SendSetTargetAPZCNotification(
1696 mPuppetWidget
, document
, aEvent
, aGuid
.mLayersId
, aInputBlockId
);
1697 if (postLayerization
) {
1698 postLayerization
->Register();
1702 localEvent
.mWidget
= mPuppetWidget
;
1704 // Stash the guid in InputAPZContext so that when the visual-to-layout
1705 // transform is applied to the event's coordinates, we use the right transform
1706 // based on the scroll frame being targeted.
1707 // The other values don't really matter.
1708 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1710 DispatchWidgetEventViaAPZ(localEvent
);
1712 if (localEvent
.mCanTriggerSwipe
) {
1713 SendRespondStartSwipeEvent(aInputBlockId
, localEvent
.TriggersSwipe());
1716 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
&& mAPZEventState
) {
1717 mAPZEventState
->ProcessWheelEvent(localEvent
, aInputBlockId
);
1721 mozilla::ipc::IPCResult
BrowserChild::RecvMouseWheelEvent(
1722 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1723 const uint64_t& aInputBlockId
) {
1724 bool isNextWheelEvent
= false;
1725 // We only coalesce the current event when
1726 // 1. It's eWheel (we don't coalesce eOperationStart and eWheelOperationEnd)
1727 // 2. It has same attributes as the coalesced wheel event which is not yet
1729 if (aEvent
.mMessage
== eWheel
) {
1730 GetIPCChannel()->PeekMessages(
1731 [&isNextWheelEvent
](const IPC::Message
& aMsg
) -> bool {
1732 if (aMsg
.type() == mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID
) {
1733 isNextWheelEvent
= true;
1735 return false; // Stop peeking.
1738 if (!mCoalescedWheelData
.IsEmpty() &&
1739 !mCoalescedWheelData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1740 DispatchCoalescedWheelEvent();
1741 MOZ_ASSERT(mCoalescedWheelData
.IsEmpty());
1743 mCoalescedWheelData
.Coalesce(aEvent
, aGuid
, aInputBlockId
);
1745 MOZ_ASSERT(!mCoalescedWheelData
.IsEmpty());
1746 // If the next event isn't a wheel event, make sure we dispatch.
1747 if (!isNextWheelEvent
) {
1748 DispatchCoalescedWheelEvent();
1751 DispatchWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1757 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityMouseWheelEvent(
1758 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1759 const uint64_t& aInputBlockId
) {
1760 return RecvMouseWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1763 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchEvent(
1764 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1765 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1766 MOZ_LOG(sApzChildLog
, LogLevel::Debug
,
1767 ("Receiving touch event of type %d\n", aEvent
.mMessage
));
1769 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1770 if (aEvent
.mMessage
== eTouchEnd
|| aEvent
.mMessage
== eTouchStart
) {
1771 ProcessPendingCoalescedTouchData();
1774 if (aEvent
.mMessage
!= eTouchMove
) {
1775 sConsecutiveTouchMoveCount
= 0;
1779 WidgetTouchEvent
localEvent(aEvent
);
1780 localEvent
.mWidget
= mPuppetWidget
;
1782 // Stash the guid in InputAPZContext so that when the visual-to-layout
1783 // transform is applied to the event's coordinates, we use the right transform
1784 // based on the scroll frame being targeted.
1785 // The other values don't really matter.
1786 InputAPZContext
context(aGuid
, aInputBlockId
, aApzResponse
);
1788 nsTArray
<TouchBehaviorFlags
> allowedTouchBehaviors
;
1789 if (localEvent
.mMessage
== eTouchStart
&& AsyncPanZoomEnabled()) {
1790 nsCOMPtr
<Document
> document
= GetTopLevelDocument();
1791 allowedTouchBehaviors
= TouchActionHelper::GetAllowedTouchBehavior(
1792 mPuppetWidget
, document
, localEvent
);
1793 if (!allowedTouchBehaviors
.IsEmpty() && mApzcTreeManager
) {
1794 mApzcTreeManager
->SetAllowedTouchBehavior(aInputBlockId
,
1795 allowedTouchBehaviors
);
1797 RefPtr
<DisplayportSetListener
> postLayerization
=
1798 APZCCallbackHelper::SendSetTargetAPZCNotification(
1799 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
,
1801 if (postLayerization
) {
1802 postLayerization
->Register();
1806 // Dispatch event to content (potentially a long-running operation)
1807 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
1809 if (!AsyncPanZoomEnabled()) {
1810 // We shouldn't have any e10s platforms that have touch events enabled
1816 if (mAPZEventState
) {
1817 mAPZEventState
->ProcessTouchEvent(localEvent
, aGuid
, aInputBlockId
,
1818 aApzResponse
, status
,
1819 std::move(allowedTouchBehaviors
));
1824 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchEvent(
1825 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1826 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1827 return RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
1830 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchMoveEvent(
1831 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1832 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1833 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1834 ++sConsecutiveTouchMoveCount
;
1835 if (mCoalescedTouchMoveEventFlusher
) {
1836 MOZ_ASSERT(aEvent
.mMessage
== eTouchMove
);
1837 if (mCoalescedTouchData
.IsEmpty() ||
1838 mCoalescedTouchData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
,
1840 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1843 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1844 mCoalescedTouchData
.TakeCoalescedEvent();
1846 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1849 if (!RecvRealTouchEvent(*touchMoveEvent
,
1850 mCoalescedTouchData
.GetScrollableLayerGuid(),
1851 mCoalescedTouchData
.GetInputBlockId(),
1852 mCoalescedTouchData
.GetApzResponse())) {
1853 return IPC_FAIL_NO_REASON(this);
1857 if (sConsecutiveTouchMoveCount
> 1) {
1858 mCoalescedTouchMoveEventFlusher
->StartObserver();
1860 // Flush the pending coalesced touch in order to avoid the first
1861 // touchmove be overridden by the second one.
1862 ProcessPendingCoalescedTouchData();
1868 if (!RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
)) {
1869 return IPC_FAIL_NO_REASON(this);
1874 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchMoveEvent(
1875 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1876 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1877 return RecvRealTouchMoveEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
1880 mozilla::ipc::IPCResult
BrowserChild::RecvRealDragEvent(
1881 const WidgetDragEvent
& aEvent
, const uint32_t& aDragAction
,
1882 const uint32_t& aDropEffect
, nsIPrincipal
* aPrincipal
,
1883 nsIContentSecurityPolicy
* aCsp
) {
1884 WidgetDragEvent
localEvent(aEvent
);
1885 localEvent
.mWidget
= mPuppetWidget
;
1887 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
1889 dragSession
->SetDragAction(aDragAction
);
1890 dragSession
->SetTriggeringPrincipal(aPrincipal
);
1891 dragSession
->SetCsp(aCsp
);
1892 RefPtr
<DataTransfer
> initialDataTransfer
= dragSession
->GetDataTransfer();
1893 if (initialDataTransfer
) {
1894 initialDataTransfer
->SetDropEffectInt(aDropEffect
);
1898 if (aEvent
.mMessage
== eDrop
) {
1899 bool canDrop
= true;
1900 if (!dragSession
|| NS_FAILED(dragSession
->GetCanDrop(&canDrop
)) ||
1902 localEvent
.mMessage
= eDragExit
;
1904 } else if (aEvent
.mMessage
== eDragOver
) {
1905 nsCOMPtr
<nsIDragService
> dragService
=
1906 do_GetService("@mozilla.org/widget/dragservice;1");
1908 // This will dispatch 'drag' event at the source if the
1909 // drag transaction started in this process.
1910 dragService
->FireDragEventAtSource(eDrag
, aEvent
.mModifiers
);
1914 DispatchWidgetEventViaAPZ(localEvent
);
1918 void BrowserChild::RequestEditCommands(NativeKeyBindingsType aType
,
1919 const WidgetKeyboardEvent
& aEvent
,
1920 nsTArray
<CommandInt
>& aCommands
) {
1921 MOZ_ASSERT(aCommands
.IsEmpty());
1923 if (NS_WARN_IF(aEvent
.IsEditCommandsInitialized(aType
))) {
1924 aCommands
= aEvent
.EditCommandsConstRef(aType
).Clone();
1929 case NativeKeyBindingsType::SingleLineEditor
:
1930 case NativeKeyBindingsType::MultiLineEditor
:
1931 case NativeKeyBindingsType::RichTextEditor
:
1934 MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type");
1937 // Don't send aEvent to the parent process directly because it'll be marked
1938 // as posted to remote process.
1939 WidgetKeyboardEvent
localEvent(aEvent
);
1940 SendRequestNativeKeyBindings(static_cast<uint32_t>(aType
), localEvent
,
1944 mozilla::ipc::IPCResult
BrowserChild::RecvNativeSynthesisResponse(
1945 const uint64_t& aObserverId
, const nsCString
& aResponse
) {
1946 mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId
,
1951 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateSHistory() {
1952 if (mSessionStoreChild
) {
1953 mSessionStoreChild
->UpdateSHistoryChanges();
1958 // In case handling repeated keys takes much time, we skip firing new ones.
1959 bool BrowserChild::SkipRepeatedKeyEvent(const WidgetKeyboardEvent
& aEvent
) {
1960 if (mRepeatedKeyEventTime
.IsNull() || !aEvent
.CanSkipInRemoteProcess() ||
1961 (aEvent
.mMessage
!= eKeyDown
&& aEvent
.mMessage
!= eKeyPress
)) {
1962 mRepeatedKeyEventTime
= TimeStamp();
1963 mSkipKeyPress
= false;
1967 if ((aEvent
.mMessage
== eKeyDown
&&
1968 (mRepeatedKeyEventTime
> aEvent
.mTimeStamp
)) ||
1969 (mSkipKeyPress
&& (aEvent
.mMessage
== eKeyPress
))) {
1970 // If we skip a keydown event, also the following keypress events should be
1972 mSkipKeyPress
|= aEvent
.mMessage
== eKeyDown
;
1976 if (aEvent
.mMessage
== eKeyDown
) {
1977 // If keydown wasn't skipped, nor should the possible following keypress.
1978 mRepeatedKeyEventTime
= TimeStamp();
1979 mSkipKeyPress
= false;
1984 void BrowserChild::UpdateRepeatedKeyEventEndTime(
1985 const WidgetKeyboardEvent
& aEvent
) {
1986 if (aEvent
.mIsRepeat
&&
1987 (aEvent
.mMessage
== eKeyDown
|| aEvent
.mMessage
== eKeyPress
)) {
1988 mRepeatedKeyEventTime
= TimeStamp::Now();
1992 mozilla::ipc::IPCResult
BrowserChild::RecvRealKeyEvent(
1993 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
1994 MOZ_ASSERT_IF(aEvent
.mMessage
== eKeyPress
,
1995 aEvent
.AreAllEditCommandsInitialized());
1997 // If content code called preventDefault() on a keydown event, then we don't
1998 // want to process any following keypress events.
1999 const bool isPrecedingKeyDownEventConsumed
=
2000 aEvent
.mMessage
== eKeyPress
&& mIgnoreKeyPressEvent
;
2002 WidgetKeyboardEvent
localEvent(aEvent
);
2003 localEvent
.mWidget
= mPuppetWidget
;
2004 localEvent
.mUniqueId
= aEvent
.mUniqueId
;
2006 if (!SkipRepeatedKeyEvent(aEvent
) && !isPrecedingKeyDownEventConsumed
) {
2007 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
2009 // Update the end time of the possible repeated event so that we can skip
2010 // some incoming events in case event handling took long time.
2011 UpdateRepeatedKeyEventEndTime(localEvent
);
2013 if (aEvent
.mMessage
== eKeyDown
) {
2014 mIgnoreKeyPressEvent
= status
== nsEventStatus_eConsumeNoDefault
;
2017 if (localEvent
.mFlags
.mIsSuppressedOrDelayed
) {
2018 localEvent
.PreventDefault();
2021 // If the event's default isn't prevented but the status is no default,
2022 // That means that the event was consumed by EventStateManager or something
2023 // which is not a usual event handler. In such case, prevent its default
2024 // as a default handler. For example, when an eKeyPress event matches
2025 // with a content accesskey, and it's executed, preventDefault() of the
2026 // event won't be called but the status is set to "no default". Then,
2027 // the event shouldn't be handled by nsMenuBarListener in the main process.
2028 if (!localEvent
.DefaultPrevented() &&
2029 status
== nsEventStatus_eConsumeNoDefault
) {
2030 localEvent
.PreventDefault();
2033 MOZ_DIAGNOSTIC_ASSERT(!localEvent
.PropagationStopped());
2035 // The keyboard event which we ignore should not be handled in the main
2036 // process for shortcut key handling. For notifying if we skipped it, we can
2037 // use "stop propagation" flag here because it must be cleared by
2038 // `EventTargetChainItem` if we've dispatched it.
2040 localEvent
.StopPropagation();
2043 // If we don't need to send a rely for the given keyboard event, we do nothing
2045 if (!aEvent
.WantReplyFromContentProcess()) {
2049 // This is an ugly hack, mNoRemoteProcessDispatch is set to true when the
2050 // event's PreventDefault() or StopScrollProcessForwarding() is called.
2051 // And then, it'll be checked by ParamTraits<mozilla::WidgetEvent>::Write()
2052 // whether the event is being sent to remote process unexpectedly.
2053 // However, unfortunately, it cannot check the destination. Therefore,
2054 // we need to clear the flag explicitly here because ParamTraits should
2055 // keep checking the flag for avoiding regression.
2056 localEvent
.mFlags
.mNoRemoteProcessDispatch
= false;
2057 SendReplyKeyEvent(localEvent
, aUUID
);
2062 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealKeyEvent(
2063 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
2064 return RecvRealKeyEvent(aEvent
, aUUID
);
2067 mozilla::ipc::IPCResult
BrowserChild::RecvCompositionEvent(
2068 const WidgetCompositionEvent
& aEvent
) {
2069 WidgetCompositionEvent
localEvent(aEvent
);
2070 localEvent
.mWidget
= mPuppetWidget
;
2071 DispatchWidgetEventViaAPZ(localEvent
);
2072 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
,
2073 localEvent
.mCompositionId
);
2077 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityCompositionEvent(
2078 const WidgetCompositionEvent
& aEvent
) {
2079 return RecvCompositionEvent(aEvent
);
2082 mozilla::ipc::IPCResult
BrowserChild::RecvSelectionEvent(
2083 const WidgetSelectionEvent
& aEvent
) {
2084 WidgetSelectionEvent
localEvent(aEvent
);
2085 localEvent
.mWidget
= mPuppetWidget
;
2086 DispatchWidgetEventViaAPZ(localEvent
);
2087 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
, 0u);
2091 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySelectionEvent(
2092 const WidgetSelectionEvent
& aEvent
) {
2093 return RecvSelectionEvent(aEvent
);
2096 mozilla::ipc::IPCResult
BrowserChild::RecvInsertText(
2097 const nsAString
& aStringToInsert
) {
2098 // Use normal event path to reach focused document.
2099 WidgetContentCommandEvent
localEvent(true, eContentCommandInsertText
,
2101 localEvent
.mString
= Some(nsString(aStringToInsert
));
2102 DispatchWidgetEventViaAPZ(localEvent
);
2106 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityInsertText(
2107 const nsAString
& aStringToInsert
) {
2108 return RecvInsertText(aStringToInsert
);
2111 mozilla::ipc::IPCResult
BrowserChild::RecvPasteTransferable(
2112 const IPCTransferable
& aTransferable
) {
2114 nsCOMPtr
<nsITransferable
> trans
=
2115 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
2116 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2117 trans
->Init(nullptr);
2119 rv
= nsContentUtils::IPCTransferableToTransferable(
2120 aTransferable
, true /* aAddDataFlavor */, trans
,
2121 false /* aFilterUnknownFlavors */);
2122 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2124 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2125 if (NS_WARN_IF(!ourDocShell
)) {
2129 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
2130 rv
= params
->SetISupports("transferable", trans
);
2131 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2133 ourDocShell
->DoCommandWithParams("cmd_pasteTransferable", params
);
2137 #ifdef ACCESSIBILITY
2138 a11y::PDocAccessibleChild
* BrowserChild::AllocPDocAccessibleChild(
2139 PDocAccessibleChild
*, const uint64_t&,
2140 const MaybeDiscardedBrowsingContext
&) {
2141 MOZ_ASSERT(false, "should never call this!");
2145 bool BrowserChild::DeallocPDocAccessibleChild(
2146 a11y::PDocAccessibleChild
* aChild
) {
2147 delete static_cast<mozilla::a11y::DocAccessibleChild
*>(aChild
);
2152 RefPtr
<VsyncMainChild
> BrowserChild::GetVsyncChild() {
2153 // Initializing mVsyncChild here turns on per-BrowserChild Vsync for a
2154 // given platform. Note: this only makes sense if nsWindow returns a
2155 // window-specific VsyncSource.
2156 #if defined(MOZ_WAYLAND)
2157 if (IsWaylandEnabled() && !mVsyncChild
) {
2158 mVsyncChild
= MakeRefPtr
<VsyncMainChild
>();
2159 if (!SendPVsyncConstructor(mVsyncChild
)) {
2160 mVsyncChild
= nullptr;
2167 mozilla::ipc::IPCResult
BrowserChild::RecvLoadRemoteScript(
2168 const nsAString
& aURL
, const bool& aRunInGlobalScope
) {
2169 if (!InitBrowserChildMessageManager())
2170 // This can happen if we're half-destroyed. It's not a fatal
2174 JS::Rooted
<JSObject
*> mm(RootingCx(),
2175 mBrowserChildMessageManager
->GetOrCreateWrapper());
2177 // This can happen if we're half-destroyed. It's not a fatal error.
2181 LoadScriptInternal(mm
, aURL
, !aRunInGlobalScope
);
2185 mozilla::ipc::IPCResult
BrowserChild::RecvAsyncMessage(
2186 const nsAString
& aMessage
, const ClonedMessageData
& aData
) {
2187 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserChild::RecvAsyncMessage",
2189 MMPrinter::Print("BrowserChild::RecvAsyncMessage", aMessage
, aData
);
2191 if (!mBrowserChildMessageManager
) {
2195 RefPtr
<nsFrameMessageManager
> mm
=
2196 mBrowserChildMessageManager
->GetMessageManager();
2198 // We should have a message manager if the global is alive, but it
2199 // seems sometimes we don't. Assert in aurora/nightly, but don't
2200 // crash in release builds.
2201 MOZ_DIAGNOSTIC_ASSERT(mm
);
2206 JS::Rooted
<JSObject
*> kungFuDeathGrip(
2207 dom::RootingCx(), mBrowserChildMessageManager
->GetWrapper());
2208 StructuredCloneData data
;
2209 UnpackClonedMessageData(aData
, data
);
2210 mm
->ReceiveMessage(static_cast<EventTarget
*>(mBrowserChildMessageManager
),
2211 nullptr, aMessage
, false, &data
, nullptr, IgnoreErrors());
2215 mozilla::ipc::IPCResult
BrowserChild::RecvSwappedWithOtherRemoteLoader(
2216 const IPCTabContext
& aContext
) {
2217 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2218 if (NS_WARN_IF(!ourDocShell
)) {
2222 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= ourDocShell
->GetWindow();
2223 if (NS_WARN_IF(!ourWindow
)) {
2227 RefPtr
<nsDocShell
> docShell
= static_cast<nsDocShell
*>(ourDocShell
.get());
2229 nsCOMPtr
<EventTarget
> ourEventTarget
= nsGlobalWindowOuter::Cast(ourWindow
);
2231 docShell
->SetInFrameSwap(true);
2233 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2234 ourDocShell
, ourEventTarget
, false, true);
2235 nsContentUtils::FirePageHideEventForFrameLoaderSwap(ourDocShell
,
2236 ourEventTarget
, true);
2238 // Owner content type may have changed, so store the possibly updated context
2239 // and notify others.
2240 MaybeInvalidTabContext
maybeContext(aContext
);
2241 if (!maybeContext
.IsValid()) {
2242 NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
2243 "the parent process. (%s)",
2244 maybeContext
.GetInvalidReason())
2246 MOZ_CRASH("Invalid TabContext received from the parent process.");
2249 if (!UpdateTabContextAfterSwap(maybeContext
.GetTabContext())) {
2250 MOZ_CRASH("Update to TabContext after swap was denied.");
2253 // Ignore previous value of mTriedBrowserInit since owner content has changed.
2254 mTriedBrowserInit
= true;
2256 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2257 ourDocShell
, ourEventTarget
, true, true);
2259 docShell
->SetInFrameSwap(false);
2261 // This is needed to get visibility state right in cases when we swapped a
2262 // visible tab (foreground in visible window) with a non-visible tab.
2263 if (RefPtr
<Document
> doc
= docShell
->GetDocument()) {
2264 doc
->UpdateVisibilityState();
2270 mozilla::ipc::IPCResult
BrowserChild::RecvHandleAccessKey(
2271 const WidgetKeyboardEvent
& aEvent
, nsTArray
<uint32_t>&& aCharCodes
) {
2272 nsCOMPtr
<Document
> document(GetTopLevelDocument());
2273 RefPtr
<nsPresContext
> pc
= document
->GetPresContext();
2275 if (!pc
->EventStateManager()->HandleAccessKey(
2276 &(const_cast<WidgetKeyboardEvent
&>(aEvent
)), pc
, aCharCodes
)) {
2277 // If no accesskey was found, inform the parent so that accesskeys on
2278 // menus can be handled.
2279 WidgetKeyboardEvent
localEvent(aEvent
);
2280 localEvent
.mWidget
= mPuppetWidget
;
2281 SendAccessKeyNotHandled(localEvent
);
2288 mozilla::ipc::IPCResult
BrowserChild::RecvPrintPreview(
2289 const PrintData
& aPrintData
, const MaybeDiscardedBrowsingContext
& aSourceBC
,
2290 PrintPreviewResolver
&& aCallback
) {
2292 // If we didn't succeed in passing off ownership of aCallback, then something
2294 auto sendCallbackError
= MakeScopeExit([&] {
2297 aCallback(PrintPreviewResultInfo(0, 0, false, false, false, {}, {}, {}));
2301 if (NS_WARN_IF(aSourceBC
.IsDiscarded())) {
2305 RefPtr
<nsGlobalWindowOuter
> sourceWindow
;
2306 if (!aSourceBC
.IsNull()) {
2307 sourceWindow
= nsGlobalWindowOuter::Cast(aSourceBC
.get()->GetDOMWindow());
2308 if (NS_WARN_IF(!sourceWindow
)) {
2312 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= do_GetInterface(WebNavigation());
2313 if (NS_WARN_IF(!ourWindow
)) {
2316 sourceWindow
= nsGlobalWindowOuter::Cast(ourWindow
);
2319 RefPtr
<nsIPrintSettings
> printSettings
;
2320 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2321 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2322 if (NS_WARN_IF(!printSettingsSvc
)) {
2325 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2326 if (NS_WARN_IF(!printSettings
)) {
2329 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2331 nsCOMPtr
<nsIDocShell
> docShellToCloneInto
;
2332 if (!aSourceBC
.IsNull()) {
2333 docShellToCloneInto
= do_GetInterface(WebNavigation());
2334 if (NS_WARN_IF(!docShellToCloneInto
)) {
2339 sourceWindow
->Print(printSettings
,
2340 /* aRemotePrintJob = */ nullptr,
2341 /* aListener = */ nullptr, docShellToCloneInto
,
2342 nsGlobalWindowOuter::IsPreview::Yes
,
2343 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2344 std::move(aCallback
), IgnoreErrors());
2349 mozilla::ipc::IPCResult
BrowserChild::RecvExitPrintPreview() {
2351 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
=
2352 do_GetInterface(ToSupports(WebNavigation()));
2353 if (NS_WARN_IF(!webBrowserPrint
)) {
2356 webBrowserPrint
->ExitPrintPreview();
2361 mozilla::ipc::IPCResult
BrowserChild::RecvPrint(
2362 const MaybeDiscardedBrowsingContext
& aBc
, const PrintData
& aPrintData
) {
2364 if (NS_WARN_IF(aBc
.IsNullOrDiscarded())) {
2367 RefPtr
<nsGlobalWindowOuter
> outerWindow
=
2368 nsGlobalWindowOuter::Cast(aBc
.get()->GetDOMWindow());
2369 if (NS_WARN_IF(!outerWindow
)) {
2373 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2374 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2375 if (NS_WARN_IF(!printSettingsSvc
)) {
2379 nsCOMPtr
<nsIPrintSettings
> printSettings
;
2381 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2382 if (NS_WARN_IF(NS_FAILED(rv
))) {
2386 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2388 IgnoredErrorResult rv
;
2389 RefPtr printJob
= static_cast<RemotePrintJobChild
*>(
2390 aPrintData
.remotePrintJob().AsChild());
2391 outerWindow
->Print(printSettings
, printJob
,
2392 /* aListener = */ nullptr,
2393 /* aWindowToCloneInto = */ nullptr,
2394 nsGlobalWindowOuter::IsPreview::No
,
2395 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2396 /* aPrintPreviewCallback = */ nullptr, rv
);
2397 if (NS_WARN_IF(rv
.Failed())) {
2405 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateNativeWindowHandle(
2406 const uintptr_t& aNewHandle
) {
2407 #if defined(XP_WIN) && defined(ACCESSIBILITY)
2408 mNativeWindowHandle
= aNewHandle
;
2411 return IPC_FAIL_NO_REASON(this);
2415 mozilla::ipc::IPCResult
BrowserChild::RecvDestroy() {
2416 MOZ_ASSERT(!mDestroyed
);
2419 nsTArray
<PContentPermissionRequestChild
*> childArray
=
2420 nsContentPermissionUtils::GetContentPermissionRequestChildById(
2423 // Need to close undeleted ContentPermissionRequestChilds before tab is
2425 for (auto& permissionRequestChild
: childArray
) {
2426 auto* child
= static_cast<RemotePermissionRequest
*>(permissionRequestChild
);
2430 if (mBrowserChildMessageManager
) {
2431 // Message handlers are called from the event loop, so it better be safe to
2433 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
2434 mBrowserChildMessageManager
->DispatchTrustedEvent(u
"unload"_ns
);
2437 nsCOMPtr
<nsIObserverService
> observerService
=
2438 mozilla::services::GetObserverService();
2440 observerService
->RemoveObserver(this, BEFORE_FIRST_PAINT
);
2442 // XXX what other code in ~BrowserChild() should we be running here?
2445 // Bounce through the event loop once to allow any delayed teardown runnables
2446 // that were just generated to have a chance to run.
2447 nsCOMPtr
<nsIRunnable
> deleteRunnable
= new DelayedDeleteRunnable(this);
2448 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable
));
2453 mozilla::ipc::IPCResult
BrowserChild::RecvRenderLayers(const bool& aEnabled
) {
2454 auto clearPaintWhileInterruptingJS
= MakeScopeExit([&] {
2455 // We might force a paint, or we might already have painted and this is a
2456 // no-op. In either case, once we exit this scope, we need to alert the
2457 // ProcessHangMonitor that we've finished responding to what might have
2458 // been a request to force paint. This is so that the BackgroundHangMonitor
2459 // for force painting can be made to wait again.
2461 ProcessHangMonitor::ClearPaintWhileInterruptingJS();
2466 ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS();
2469 mRenderLayers
= aEnabled
;
2470 const bool wasVisible
= IsVisible();
2474 // If we just became visible, try to trigger a paint as soon as possible.
2475 const bool becameVisible
= !wasVisible
&& IsVisible();
2476 if (!becameVisible
) {
2480 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2485 // We don't use BrowserChildBase::GetPresShell() here because that would
2486 // create a content viewer if one doesn't exist yet. Creating a content
2487 // viewer can cause JS to run, which we want to avoid.
2488 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2489 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2494 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2495 root
->SchedulePaint();
2498 Telemetry::AutoTimer
<Telemetry::TABCHILD_PAINT_TIME
> timer
;
2499 // If we need to repaint, let's do that right away. No sense waiting until
2500 // we get back to the event loop again. We suppress the display port so
2501 // that we only paint what's visible. This ensures that the tab we're
2502 // switching to paints as quickly as possible.
2503 presShell
->SuppressDisplayport(true);
2504 if (nsContentUtils::IsSafeToRunScript()) {
2505 WebWidget()->PaintNowIfNeeded();
2507 RefPtr
<nsViewManager
> vm
= presShell
->GetViewManager();
2508 if (nsView
* view
= vm
->GetRootView()) {
2509 presShell
->PaintAndRequestComposite(view
, PaintFlags::None
);
2512 presShell
->SuppressDisplayport(false);
2516 mozilla::ipc::IPCResult
BrowserChild::RecvNavigateByKey(
2517 const bool& aForward
, const bool& aForDocumentNavigation
) {
2518 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2523 RefPtr
<Element
> result
;
2524 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2526 // Move to the first or last document.
2530 ? (aForDocumentNavigation
2531 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC
)
2532 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT
))
2533 : (aForDocumentNavigation
2534 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC
)
2535 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LAST
));
2536 uint32_t flags
= nsIFocusManager::FLAG_BYKEY
;
2537 if (aForward
|| aForDocumentNavigation
) {
2538 flags
|= nsIFocusManager::FLAG_NOSCROLL
;
2540 fm
->MoveFocus(window
, nullptr, type
, flags
, getter_AddRefs(result
));
2543 // No valid root element was found, so move to the first focusable element.
2544 if (!result
&& aForward
&& !aForDocumentNavigation
) {
2545 fm
->MoveFocus(window
, nullptr, nsIFocusManager::MOVEFOCUS_FIRST
,
2546 nsIFocusManager::FLAG_BYKEY
, getter_AddRefs(result
));
2549 SendRequestFocus(false, CallerType::System
);
2553 bool BrowserChild::InitBrowserChildMessageManager() {
2554 mShouldSendWebProgressEventsToParent
= true;
2556 if (!mBrowserChildMessageManager
) {
2557 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2558 NS_ENSURE_TRUE(window
, false);
2559 nsCOMPtr
<EventTarget
> chromeHandler
= window
->GetChromeEventHandler();
2560 NS_ENSURE_TRUE(chromeHandler
, false);
2562 RefPtr
<BrowserChildMessageManager
> scope
= mBrowserChildMessageManager
=
2563 new BrowserChildMessageManager(this);
2565 MOZ_ALWAYS_TRUE(nsMessageManagerScriptExecutor::Init());
2567 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(chromeHandler
);
2568 if (NS_WARN_IF(!root
)) {
2569 mBrowserChildMessageManager
= nullptr;
2572 root
->SetParentTarget(scope
);
2575 if (!mTriedBrowserInit
) {
2576 mTriedBrowserInit
= true;
2582 void BrowserChild::InitRenderingState(
2583 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
2584 const layers::LayersId
& aLayersId
,
2585 const CompositorOptions
& aCompositorOptions
) {
2586 mPuppetWidget
->InitIMEState();
2588 MOZ_ASSERT(aLayersId
.IsValid());
2589 mTextureFactoryIdentifier
= aTextureFactoryIdentifier
;
2591 // Pushing layers transactions directly to a separate
2592 // compositor context.
2593 PCompositorBridgeChild
* compositorChild
= CompositorBridgeChild::Get();
2594 if (!compositorChild
) {
2595 mLayersConnected
= Some(false);
2596 NS_WARNING("failed to get CompositorBridgeChild instance");
2600 mCompositorOptions
= Some(aCompositorOptions
);
2602 if (aLayersId
.IsValid()) {
2603 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2605 if (!sBrowserChildren
) {
2606 sBrowserChildren
= new BrowserChildMap
;
2608 MOZ_ASSERT(!sBrowserChildren
->Contains(uint64_t(aLayersId
)));
2609 sBrowserChildren
->InsertOrUpdate(uint64_t(aLayersId
), this);
2610 mLayersId
= aLayersId
;
2613 // Depending on timing, we might paint too early and fall back to basic
2614 // layers. CreateRemoteLayerManager will destroy us if we manage to get a
2615 // remote layer manager though, so that's fine.
2616 MOZ_ASSERT(!mPuppetWidget
->HasWindowRenderer() ||
2617 mPuppetWidget
->GetWindowRenderer()->GetBackendType() ==
2618 layers::LayersBackend::LAYERS_NONE
);
2619 bool success
= false;
2620 if (mLayersConnected
== Some(true)) {
2621 success
= CreateRemoteLayerManager(compositorChild
);
2625 MOZ_ASSERT(mLayersConnected
== Some(true));
2626 // Succeeded to create "remote" layer manager
2627 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
2628 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
2631 NS_WARNING("Fallback to FallbackRenderer");
2632 mLayersConnected
= Some(false);
2635 nsCOMPtr
<nsIObserverService
> observerService
=
2636 mozilla::services::GetObserverService();
2638 if (observerService
) {
2639 observerService
->AddObserver(this, BEFORE_FIRST_PAINT
, false);
2643 bool BrowserChild::CreateRemoteLayerManager(
2644 mozilla::layers::PCompositorBridgeChild
* aCompositorChild
) {
2645 MOZ_ASSERT(aCompositorChild
);
2647 return mPuppetWidget
->CreateRemoteLayerManager(
2648 [&](WebRenderLayerManager
* aLayerManager
) -> bool {
2650 return aLayerManager
->Initialize(aCompositorChild
,
2651 wr::AsPipelineId(mLayersId
),
2652 &mTextureFactoryIdentifier
, error
);
2656 void BrowserChild::InitAPZState() {
2657 if (!mCompositorOptions
->UseAPZ()) {
2660 auto* cbc
= CompositorBridgeChild::Get();
2662 // Initialize the ApzcTreeManager. This takes multiple casts because of ugly
2663 // multiple inheritance.
2664 PAPZCTreeManagerChild
* baseProtocol
=
2665 cbc
->SendPAPZCTreeManagerConstructor(mLayersId
);
2666 if (!baseProtocol
) {
2668 "Allocating a TreeManager should not fail with APZ enabled");
2671 APZCTreeManagerChild
* derivedProtocol
=
2672 static_cast<APZCTreeManagerChild
*>(baseProtocol
);
2674 mApzcTreeManager
= RefPtr
<IAPZCTreeManager
>(derivedProtocol
);
2676 // Initialize the GeckoContentController for this tab. We don't hold a
2677 // reference because we don't need it. The ContentProcessController will hold
2678 // a reference to the tab, and will be destroyed by the compositor or ipdl
2679 // during destruction.
2680 RefPtr
<GeckoContentController
> contentController
=
2681 new ContentProcessController(this);
2682 APZChild
* apzChild
= new APZChild(contentController
);
2683 cbc
->SendPAPZConstructor(apzChild
, mLayersId
);
2686 IPCResult
BrowserChild::RecvUpdateEffects(const EffectsInfo
& aEffects
) {
2687 bool needInvalidate
= false;
2688 if (mEffectsInfo
.IsVisible() && aEffects
.IsVisible() &&
2689 mEffectsInfo
!= aEffects
) {
2690 // If we are staying visible and either the visrect or scale changed we need
2692 needInvalidate
= true;
2695 mEffectsInfo
= aEffects
;
2698 if (needInvalidate
) {
2699 if (nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation())) {
2700 // We don't use BrowserChildBase::GetPresShell() here because that would
2701 // create a content viewer if one doesn't exist yet. Creating a content
2702 // viewer can cause JS to run, which we want to avoid.
2703 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2704 if (RefPtr
<PresShell
> presShell
= docShell
->GetPresShell()) {
2705 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2706 root
->InvalidateFrame();
2715 bool BrowserChild::IsVisible() {
2716 return mPuppetWidget
&& mPuppetWidget
->IsVisible();
2719 void BrowserChild::UpdateVisibility() {
2720 const bool shouldBeVisible
= [&] {
2721 // If we're known to be visibility: hidden / display: none, just return
2722 // false here, we're pretty sure we don't want to be considered visible
2724 if (mBrowsingContext
&& mBrowsingContext
->IsUnderHiddenEmbedderElement()) {
2727 // For OOP iframes, include viewport visibility. For top-level <browser>
2728 // elements we don't use this, because the front-end relies on using
2729 // `mRenderLayers` when invisible for tab warming purposes.
2731 // An alternative, maybe more consistent approach would be to add an opt-in
2732 // into this behavior for top-level tabs managed by the tab-switcher
2734 if (!mIsTopLevel
&& !mEffectsInfo
.IsVisible()) {
2737 // If we're explicitly told not to render layers, we're also invisible.
2738 if (!mRenderLayers
) {
2744 const bool isVisible
= IsVisible();
2745 if (shouldBeVisible
== isVisible
) {
2748 if (shouldBeVisible
) {
2755 void BrowserChild::MakeVisible() {
2760 if (mPuppetWidget
) {
2761 mPuppetWidget
->Show(true);
2764 PresShellActivenessMaybeChanged();
2767 void BrowserChild::MakeHidden() {
2772 // Due to the nested event loop in ContentChild::ProvideWindowCommon,
2773 // it's possible to be told to become hidden before we're finished
2774 // setting up a layer manager. We should skip clearing cached layers
2775 // in that case, since doing so might accidentally put is into
2776 // BasicLayers mode.
2777 if (mPuppetWidget
) {
2778 if (mPuppetWidget
->HasWindowRenderer()) {
2779 ClearCachedResources();
2781 mPuppetWidget
->Show(false);
2784 PresShellActivenessMaybeChanged();
2787 IPCResult
BrowserChild::RecvPreserveLayers(bool aPreserve
) {
2788 mIsPreservingLayers
= aPreserve
;
2790 PresShellActivenessMaybeChanged();
2795 void BrowserChild::PresShellActivenessMaybeChanged() {
2796 // We don't use BrowserChildBase::GetPresShell() here because that would
2797 // create a content viewer if one doesn't exist yet. Creating a content
2798 // viewer can cause JS to run, which we want to avoid.
2799 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2801 // When this method is called we don't want to go through the browsing context
2802 // because we don't want to change the visibility state of the document, which
2803 // has side effects like firing events to content, unblocking media playback,
2804 // unthrottling timeouts... PresShell activeness has a lot less side effects.
2805 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2809 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2813 presShell
->ActivenessMaybeChanged();
2817 BrowserChild::GetMessageManager(ContentFrameMessageManager
** aResult
) {
2818 RefPtr
<ContentFrameMessageManager
> mm(mBrowserChildMessageManager
);
2820 return *aResult
? NS_OK
: NS_ERROR_FAILURE
;
2823 void BrowserChild::SendRequestFocus(bool aCanFocus
, CallerType aCallerType
) {
2824 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2829 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2834 BrowsingContext
* focusedBC
= fm
->GetFocusedBrowsingContext();
2835 if (focusedBC
== window
->GetBrowsingContext()) {
2836 // BrowsingContext has the focus already, do not request again.
2840 PBrowserChild::SendRequestFocus(aCanFocus
, aCallerType
);
2844 BrowserChild::GetTabId(uint64_t* aId
) {
2850 BrowserChild::GetChromeOuterWindowID(uint64_t* aId
) {
2851 *aId
= ChromeOuterWindowID();
2855 bool BrowserChild::DoSendBlockingMessage(
2856 const nsAString
& aMessage
, StructuredCloneData
& aData
,
2857 nsTArray
<StructuredCloneData
>* aRetVal
) {
2858 ClonedMessageData data
;
2859 if (!BuildClonedMessageData(aData
, data
)) {
2862 return SendSyncMessage(PromiseFlatString(aMessage
), data
, aRetVal
);
2865 nsresult
BrowserChild::DoSendAsyncMessage(const nsAString
& aMessage
,
2866 StructuredCloneData
& aData
) {
2867 ClonedMessageData data
;
2868 if (!BuildClonedMessageData(aData
, data
)) {
2869 return NS_ERROR_DOM_DATA_CLONE_ERR
;
2871 if (!SendAsyncMessage(PromiseFlatString(aMessage
), data
)) {
2872 return NS_ERROR_UNEXPECTED
;
2878 nsTArray
<RefPtr
<BrowserChild
>> BrowserChild::GetAll() {
2879 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2881 if (!sBrowserChildren
) {
2885 return ToTArray
<nsTArray
<RefPtr
<BrowserChild
>>>(sBrowserChildren
->Values());
2888 BrowserChild
* BrowserChild::GetFrom(PresShell
* aPresShell
) {
2889 Document
* doc
= aPresShell
->GetDocument();
2893 nsCOMPtr
<nsIDocShell
> docShell(doc
->GetDocShell());
2894 return GetFrom(docShell
);
2897 BrowserChild
* BrowserChild::GetFrom(layers::LayersId aLayersId
) {
2898 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2899 if (!sBrowserChildren
) {
2902 return sBrowserChildren
->Get(uint64_t(aLayersId
));
2905 void BrowserChild::DidComposite(mozilla::layers::TransactionId aTransactionId
,
2906 const TimeStamp
& aCompositeStart
,
2907 const TimeStamp
& aCompositeEnd
) {
2908 MOZ_ASSERT(mPuppetWidget
);
2909 RefPtr
<WebRenderLayerManager
> lm
=
2910 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2914 lm
->DidComposite(aTransactionId
, aCompositeStart
, aCompositeEnd
);
2918 void BrowserChild::ClearCachedResources() {
2919 MOZ_ASSERT(mPuppetWidget
);
2920 RefPtr
<WebRenderLayerManager
> lm
=
2921 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2923 lm
->ClearCachedResources();
2926 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
2927 nsPresContext
* presContext
= document
->GetPresContext();
2929 presContext
->NotifyPaintStatusReset();
2934 void BrowserChild::SchedulePaint() {
2935 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2940 // We don't use BrowserChildBase::GetPresShell() here because that would
2941 // create a content viewer if one doesn't exist yet. Creating a content viewer
2942 // can cause JS to run, which we want to avoid. nsIDocShell::GetPresShell
2943 // returns null if no content viewer exists yet.
2944 if (RefPtr
<PresShell
> presShell
= docShell
->GetPresShell()) {
2945 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2946 root
->SchedulePaint();
2951 void BrowserChild::ReinitRendering() {
2952 MOZ_ASSERT(mLayersId
.IsValid());
2954 // In some cases, like when we create a windowless browser,
2955 // RemoteLayerTreeOwner/BrowserChild is not connected to a compositor.
2956 if (mLayersConnectRequested
.isNothing() ||
2957 mLayersConnectRequested
== Some(false)) {
2961 // Before we establish a new PLayerTransaction, we must connect our layer tree
2962 // id, CompositorBridge, and the widget compositor all together again.
2963 // Normally this happens in BrowserParent before BrowserChild is given
2964 // rendering information.
2966 // In this case, we will send a sync message to our BrowserParent, which in
2967 // turn will send a sync message to the Compositor of the widget owning this
2968 // tab. This guarantees the correct association is in place before our
2969 // PLayerTransaction constructor message arrives on the cross-process
2970 // compositor bridge.
2971 CompositorOptions options
;
2972 SendEnsureLayersConnected(&options
);
2973 mCompositorOptions
= Some(options
);
2975 bool success
= false;
2976 RefPtr
<CompositorBridgeChild
> cb
= CompositorBridgeChild::Get();
2979 success
= CreateRemoteLayerManager(cb
);
2983 NS_WARNING("failed to recreate layer manager");
2987 mLayersConnected
= Some(true);
2988 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
2989 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
2992 if (nsCOMPtr
<Document
> doc
= GetTopLevelDocument()) {
2993 doc
->NotifyLayerManagerRecreated();
2996 if (mRenderLayers
) {
3001 void BrowserChild::ReinitRenderingForDeviceReset() {
3002 RefPtr
<WebRenderLayerManager
> lm
=
3003 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3005 lm
->DoDestroy(/* aIsSync */ true);
3008 // Proceed with destroying and recreating the layer manager.
3013 BrowserChild::OnShowTooltip(int32_t aXCoords
, int32_t aYCoords
,
3014 const nsAString
& aTipText
,
3015 const nsAString
& aTipDir
) {
3016 nsString
str(aTipText
);
3017 nsString
dir(aTipDir
);
3018 SendShowTooltip(aXCoords
, aYCoords
, str
, dir
);
3023 BrowserChild::OnHideTooltip() {
3028 void BrowserChild::NotifyJankedAnimations(
3029 const nsTArray
<uint64_t>& aJankedAnimations
) {
3030 MOZ_ASSERT(mPuppetWidget
);
3031 RefPtr
<WebRenderLayerManager
> lm
=
3032 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3034 lm
->UpdatePartialPrerenderedAnimations(aJankedAnimations
);
3038 mozilla::ipc::IPCResult
BrowserChild::RecvUIResolutionChanged(
3039 const float& aDpi
, const int32_t& aRounding
, const double& aScale
) {
3040 ScreenIntSize oldScreenSize
= GetInnerSize();
3042 mPuppetWidget
->UpdateBackingScaleCache(aDpi
, aRounding
, aScale
);
3045 ScreenIntSize screenSize
= GetInnerSize();
3046 if (mHasValidInnerSize
&& oldScreenSize
!= screenSize
) {
3047 ScreenIntRect screenRect
= GetOuterRect();
3049 // See RecvUpdateDimensions for the order of these operations.
3050 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
3051 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
3052 nsIBaseWindow::eRepaint
);
3054 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3055 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
3056 screenSize
.width
, screenSize
.height
, true);
3059 nsCOMPtr
<Document
> document(GetTopLevelDocument());
3060 RefPtr
<nsPresContext
> presContext
=
3061 document
? document
->GetPresContext() : nullptr;
3063 presContext
->UIResolutionChangedSync();
3069 mozilla::ipc::IPCResult
BrowserChild::RecvSafeAreaInsetsChanged(
3070 const mozilla::ScreenIntMargin
& aSafeAreaInsets
) {
3071 mPuppetWidget
->UpdateSafeAreaInsets(aSafeAreaInsets
);
3073 nsCOMPtr
<nsIScreenManager
> screenMgr
=
3074 do_GetService("@mozilla.org/gfx/screenmanager;1");
3075 ScreenIntMargin currentSafeAreaInsets
;
3077 // aSafeAreaInsets is for current screen. But we have to calculate
3078 // safe insets for content window.
3079 int32_t x
, y
, cx
, cy
;
3080 GetDimensions(DimensionKind::Outer
, &x
, &y
, &cx
, &cy
);
3081 nsCOMPtr
<nsIScreen
> screen
;
3082 screenMgr
->ScreenForRect(x
, y
, cx
, cy
, getter_AddRefs(screen
));
3085 LayoutDeviceIntRect
windowRect(x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3086 y
+ mClientOffset
.y
+ mChromeOffset
.y
, cx
,
3088 currentSafeAreaInsets
= nsContentUtils::GetWindowSafeAreaInsets(
3089 screen
, aSafeAreaInsets
, windowRect
);
3093 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
3094 nsPresContext
* presContext
= document
->GetPresContext();
3096 presContext
->SetSafeAreaInsets(currentSafeAreaInsets
);
3100 // https://github.com/w3c/csswg-drafts/issues/4670
3101 // Actually we don't set this value on sub document. This behaviour is
3102 // same as Blink that safe area insets isn't set on sub document.
3107 mozilla::ipc::IPCResult
BrowserChild::RecvAllowScriptsToClose() {
3108 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
3110 nsGlobalWindowOuter::Cast(window
)->AllowScriptsToClose();
3115 mozilla::ipc::IPCResult
BrowserChild::RecvReleaseAllPointerCapture() {
3116 PointerEventHandler::ReleaseAllPointerCapture();
3120 PPaymentRequestChild
* BrowserChild::AllocPPaymentRequestChild() {
3122 "We should never be manually allocating PPaymentRequestChild actors");
3126 bool BrowserChild::DeallocPPaymentRequestChild(PPaymentRequestChild
* actor
) {
3131 ScreenIntSize
BrowserChild::GetInnerSize() {
3132 LayoutDeviceIntSize innerSize
=
3133 RoundedToInt(mUnscaledInnerSize
* mPuppetWidget
->GetDefaultScale());
3134 return ViewAs
<ScreenPixel
>(
3135 innerSize
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3138 Maybe
<nsRect
> BrowserChild::GetVisibleRect() const {
3140 // We are conservative about visible rects for top-level browsers to avoid
3141 // artifacts when resizing
3144 return mEffectsInfo
.mVisibleRect
;
3147 Maybe
<LayoutDeviceRect
>
3148 BrowserChild::GetTopLevelViewportVisibleRectInSelfCoords() const {
3153 if (!mChildToParentConversionMatrix
) {
3154 // We have no way to tell this remote document visible rect right now.
3158 Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
> inverse
=
3159 mChildToParentConversionMatrix
->MaybeInverse();
3164 // Convert the remote document visible rect to the coordinate system of the
3166 Maybe
<LayoutDeviceRect
> rect
= UntransformBy(
3168 ViewAs
<LayoutDevicePixel
>(
3169 mTopLevelViewportVisibleRectInBrowserCoords
,
3170 PixelCastJustification::ContentProcessIsLayerInUiProcess
),
3171 LayoutDeviceRect::MaxIntRect());
3179 ScreenIntRect
BrowserChild::GetOuterRect() {
3180 LayoutDeviceIntRect outerRect
=
3181 RoundedToInt(mUnscaledOuterRect
* mPuppetWidget
->GetDefaultScale());
3182 return ViewAs
<ScreenPixel
>(
3183 outerRect
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3186 void BrowserChild::PaintWhileInterruptingJS() {
3187 if (!IPCOpen() || !mPuppetWidget
|| !mPuppetWidget
->HasWindowRenderer()) {
3188 // Don't bother doing anything now. Better to wait until we receive the
3189 // message on the PContent channel.
3193 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
3194 nsAutoScriptBlocker scriptBlocker
;
3195 RecvRenderLayers(/* aEnabled = */ true);
3198 void BrowserChild::UnloadLayersWhileInterruptingJS() {
3199 if (!IPCOpen() || !mPuppetWidget
|| !mPuppetWidget
->HasWindowRenderer()) {
3200 // Don't bother doing anything now. Better to wait until we receive the
3201 // message on the PContent channel.
3205 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
3206 nsAutoScriptBlocker scriptBlocker
;
3207 RecvRenderLayers(/* aEnabled = */ false);
3210 nsresult
BrowserChild::CanCancelContentJS(
3211 nsIRemoteTab::NavigationType aNavigationType
, int32_t aNavigationIndex
,
3212 nsIURI
* aNavigationURI
, int32_t aEpoch
, bool* aCanCancel
) {
3214 *aCanCancel
= false;
3216 if (aEpoch
<= mCancelContentJSEpoch
) {
3217 // The next page loaded before we got here, so we shouldn't try to cancel
3222 // If we have session history in the parent we've already performed
3223 // the checks following, so we can return early.
3224 if (mozilla::SessionHistoryInParent()) {
3229 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
3230 nsCOMPtr
<nsISHistory
> history
;
3232 history
= nsDocShell::Cast(docShell
)->GetSessionHistory()->LegacySHistory();
3236 return NS_ERROR_FAILURE
;
3240 rv
= history
->GetIndex(¤t
);
3241 NS_ENSURE_SUCCESS(rv
, rv
);
3243 if (current
== -1) {
3244 // This tab has no history! Just return.
3248 nsCOMPtr
<nsISHEntry
> entry
;
3249 rv
= history
->GetEntryAtIndex(current
, getter_AddRefs(entry
));
3250 NS_ENSURE_SUCCESS(rv
, rv
);
3252 nsCOMPtr
<nsIURI
> currentURI
= entry
->GetURI();
3253 if (!currentURI
->SchemeIs("http") && !currentURI
->SchemeIs("https") &&
3254 !currentURI
->SchemeIs("file")) {
3255 // Only cancel content JS for http(s) and file URIs. Other URIs are probably
3256 // internal and we should just let them run to completion.
3260 if (aNavigationType
== nsIRemoteTab::NAVIGATE_BACK
) {
3261 aNavigationIndex
= current
- 1;
3262 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_FORWARD
) {
3263 aNavigationIndex
= current
+ 1;
3264 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_URL
) {
3265 if (!aNavigationURI
) {
3266 return NS_ERROR_FAILURE
;
3269 if (aNavigationURI
->SchemeIs("javascript")) {
3270 // "javascript:" URIs don't (necessarily) trigger navigation to a
3271 // different page, so don't allow the current page's JS to terminate.
3275 // If navigating directly to a URL (e.g. via hitting Enter in the location
3276 // bar), then we can cancel anytime the next URL is different from the
3277 // current, *excluding* the ref ("#").
3279 rv
= currentURI
->EqualsExceptRef(aNavigationURI
, &equals
);
3280 NS_ENSURE_SUCCESS(rv
, rv
);
3281 *aCanCancel
= !equals
;
3284 // Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't
3285 // need to do anything special.
3287 int32_t delta
= aNavigationIndex
> current
? 1 : -1;
3288 for (int32_t i
= current
+ delta
; i
!= aNavigationIndex
+ delta
; i
+= delta
) {
3289 nsCOMPtr
<nsISHEntry
> nextEntry
;
3290 // If `i` happens to be negative, this call will fail (which is what we
3291 // would want to happen).
3292 rv
= history
->GetEntryAtIndex(i
, getter_AddRefs(nextEntry
));
3293 NS_ENSURE_SUCCESS(rv
, rv
);
3295 nsCOMPtr
<nsISHEntry
> laterEntry
= delta
== 1 ? nextEntry
: entry
;
3296 nsCOMPtr
<nsIURI
> thisURI
= entry
->GetURI();
3297 nsCOMPtr
<nsIURI
> nextURI
= nextEntry
->GetURI();
3299 // If we changed origin and the load wasn't in a subframe, we know it was
3300 // a full document load, so we can cancel the content JS safely.
3301 if (!laterEntry
->GetIsSubFrame()) {
3302 nsAutoCString thisHost
;
3303 rv
= thisURI
->GetPrePath(thisHost
);
3304 NS_ENSURE_SUCCESS(rv
, rv
);
3306 nsAutoCString nextHost
;
3307 rv
= nextURI
->GetPrePath(nextHost
);
3308 NS_ENSURE_SUCCESS(rv
, rv
);
3310 if (!thisHost
.Equals(nextHost
)) {
3322 NS_IMETHODIMP
BrowserChild::OnStateChange(nsIWebProgress
* aWebProgress
,
3323 nsIRequest
* aRequest
,
3324 uint32_t aStateFlags
,
3326 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3330 // We shouldn't need to notify the parent of redirect state changes, since
3331 // with DocumentChannel that only happens when we switch to the real channel,
3332 // and that's an implementation detail that we can hide.
3333 if (aStateFlags
& nsIWebProgressListener::STATE_IS_REDIRECTED_DOCUMENT
) {
3337 // Our OnStateChange call must have provided the nsIDocShell which the source
3338 // comes from. We'll use this to locate the corresponding BrowsingContext in
3339 // the parent process.
3340 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3342 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3343 return NS_ERROR_UNEXPECTED
;
3346 WebProgressData webProgressData
;
3347 Maybe
<WebProgressStateChangeData
> stateChangeData
;
3348 RequestData requestData
;
3350 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3353 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3354 if (browsingContext
->IsTopContent()) {
3355 stateChangeData
.emplace();
3357 stateChangeData
->isNavigating() = docShell
->GetIsNavigating();
3358 stateChangeData
->mayEnableCharacterEncodingMenu() =
3359 docShell
->GetMayEnableCharacterEncodingMenu();
3361 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3362 if (document
&& aStateFlags
& nsIWebProgressListener::STATE_STOP
) {
3363 document
->GetContentType(stateChangeData
->contentType());
3364 document
->GetCharacterSet(stateChangeData
->charset());
3365 stateChangeData
->documentURI() = document
->GetDocumentURIObject();
3367 stateChangeData
->contentType().SetIsVoid(true);
3368 stateChangeData
->charset().SetIsVoid(true);
3372 Unused
<< SendOnStateChange(webProgressData
, requestData
, aStateFlags
,
3373 aStatus
, stateChangeData
);
3378 NS_IMETHODIMP
BrowserChild::OnProgressChange(nsIWebProgress
* aWebProgress
,
3379 nsIRequest
* aRequest
,
3380 int32_t aCurSelfProgress
,
3381 int32_t aMaxSelfProgress
,
3382 int32_t aCurTotalProgress
,
3383 int32_t aMaxTotalProgress
) {
3384 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3388 // FIXME: We currently ignore ProgressChange events from out-of-process
3389 // subframes both here and in BrowserParent. We may want to change this
3390 // behaviour in the future.
3391 if (!GetBrowsingContext()->IsTopContent()) {
3395 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3396 // nullptr or 0 for all arguments other than aCurTotalProgress and
3397 // aMaxTotalProgress. Don't bother sending them.
3398 MOZ_ASSERT(!aWebProgress
);
3399 MOZ_ASSERT(!aRequest
);
3400 MOZ_ASSERT(aCurSelfProgress
== 0);
3401 MOZ_ASSERT(aMaxSelfProgress
== 0);
3403 Unused
<< SendOnProgressChange(aCurTotalProgress
, aMaxTotalProgress
);
3408 NS_IMETHODIMP
BrowserChild::OnLocationChange(nsIWebProgress
* aWebProgress
,
3409 nsIRequest
* aRequest
,
3412 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3416 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3418 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3419 return NS_ERROR_UNEXPECTED
;
3422 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3423 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3428 WebProgressData webProgressData
;
3429 RequestData requestData
;
3431 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3434 Maybe
<WebProgressLocationChangeData
> locationChangeData
;
3436 bool canGoBack
= false;
3437 bool canGoForward
= false;
3438 if (!mozilla::SessionHistoryInParent()) {
3439 MOZ_TRY(WebNavigation()->GetCanGoBack(&canGoBack
));
3440 MOZ_TRY(WebNavigation()->GetCanGoForward(&canGoForward
));
3443 if (browsingContext
->IsTopContent()) {
3445 browsingContext
== GetBrowsingContext(),
3446 "Toplevel content BrowsingContext which isn't GetBrowsingContext()?");
3448 locationChangeData
.emplace();
3450 document
->GetContentType(locationChangeData
->contentType());
3451 locationChangeData
->isNavigating() = docShell
->GetIsNavigating();
3452 locationChangeData
->documentURI() = document
->GetDocumentURIObject();
3453 document
->GetTitle(locationChangeData
->title());
3454 document
->GetCharacterSet(locationChangeData
->charset());
3456 locationChangeData
->mayEnableCharacterEncodingMenu() =
3457 docShell
->GetMayEnableCharacterEncodingMenu();
3459 locationChangeData
->contentPrincipal() = document
->NodePrincipal();
3460 locationChangeData
->contentPartitionedPrincipal() =
3461 document
->PartitionedPrincipal();
3462 locationChangeData
->csp() = document
->GetCsp();
3463 locationChangeData
->referrerInfo() = document
->ReferrerInfo();
3464 locationChangeData
->isSyntheticDocument() = document
->IsSyntheticDocument();
3466 if (nsCOMPtr
<nsILoadGroup
> loadGroup
= document
->GetDocumentLoadGroup()) {
3467 uint64_t requestContextID
= 0;
3468 MOZ_TRY(loadGroup
->GetRequestContextID(&requestContextID
));
3469 locationChangeData
->requestContextID() = Some(requestContextID
);
3472 #ifdef MOZ_CRASHREPORTER
3473 if (CrashReporter::GetEnabled()) {
3474 nsCOMPtr
<nsIURI
> annotationURI
;
3477 NS_MutateURI(aLocation
).SetUserPass(""_ns
).Finalize(annotationURI
);
3479 if (NS_FAILED(rv
)) {
3480 // Ignore failures on about: URIs.
3481 annotationURI
= aLocation
;
3484 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL
,
3485 annotationURI
->GetSpecOrDefault());
3490 Unused
<< SendOnLocationChange(webProgressData
, requestData
, aLocation
,
3491 aFlags
, canGoBack
, canGoForward
,
3492 locationChangeData
);
3497 NS_IMETHODIMP
BrowserChild::OnStatusChange(nsIWebProgress
* aWebProgress
,
3498 nsIRequest
* aRequest
,
3500 const char16_t
* aMessage
) {
3501 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3505 // FIXME: We currently ignore StatusChange from out-of-process subframes both
3506 // here and in BrowserParent. We may want to change this behaviour in the
3508 if (!GetBrowsingContext()->IsTopContent()) {
3512 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3513 // nullptr or NS_OK for all arguments other than aMessage. Don't bother
3515 MOZ_ASSERT(!aWebProgress
);
3516 MOZ_ASSERT(!aRequest
);
3517 MOZ_ASSERT(aStatus
== NS_OK
);
3519 Unused
<< SendOnStatusChange(nsDependentString(aMessage
));
3524 NS_IMETHODIMP
BrowserChild::OnSecurityChange(nsIWebProgress
* aWebProgress
,
3525 nsIRequest
* aRequest
,
3527 // Security changes are now handled entirely in the parent process
3528 // so we don't need to worry about forwarding them (and we shouldn't
3529 // be receiving any to forward).
3533 NS_IMETHODIMP
BrowserChild::OnContentBlockingEvent(nsIWebProgress
* aWebProgress
,
3534 nsIRequest
* aRequest
,
3536 // The OnContentBlockingEvent only happenes in the parent process. It should
3537 // not be seen in the content process.
3538 MOZ_DIAGNOSTIC_ASSERT(
3539 false, "OnContentBlockingEvent should not be seen in content process.");
3540 return NS_ERROR_NOT_IMPLEMENTED
;
3543 NS_IMETHODIMP
BrowserChild::OnProgressChange64(nsIWebProgress
* aWebProgress
,
3544 nsIRequest
* aRequest
,
3545 int64_t aCurSelfProgress
,
3546 int64_t aMaxSelfProgress
,
3547 int64_t aCurTotalProgress
,
3548 int64_t aMaxTotalProgress
) {
3549 // All the events we receive are filtered through an nsBrowserStatusFilter,
3550 // which accepts ProgressChange64 events, but truncates the progress values to
3551 // uint32_t and calls OnProgressChange.
3552 return NS_ERROR_NOT_IMPLEMENTED
;
3555 NS_IMETHODIMP
BrowserChild::OnRefreshAttempted(nsIWebProgress
* aWebProgress
,
3556 nsIURI
* aRefreshURI
,
3557 uint32_t aMillis
, bool aSameURI
,
3559 NS_ENSURE_ARG_POINTER(aOut
);
3565 NS_IMETHODIMP
BrowserChild::NotifyNavigationFinished() {
3566 Unused
<< SendNavigationFinished();
3570 nsresult
BrowserChild::PrepareRequestData(nsIRequest
* aRequest
,
3571 RequestData
& aRequestData
) {
3572 nsCOMPtr
<nsIChannel
> channel
= do_QueryInterface(aRequest
);
3574 aRequestData
.requestURI() = nullptr;
3578 nsresult rv
= channel
->GetURI(getter_AddRefs(aRequestData
.requestURI()));
3579 NS_ENSURE_SUCCESS(rv
, rv
);
3581 rv
= channel
->GetOriginalURI(
3582 getter_AddRefs(aRequestData
.originalRequestURI()));
3583 NS_ENSURE_SUCCESS(rv
, rv
);
3585 nsCOMPtr
<nsIClassifiedChannel
> classifiedChannel
= do_QueryInterface(channel
);
3586 if (classifiedChannel
) {
3587 rv
= classifiedChannel
->GetMatchedList(aRequestData
.matchedList());
3588 NS_ENSURE_SUCCESS(rv
, rv
);
3593 nsresult
BrowserChild::PrepareProgressListenerData(
3594 nsIWebProgress
* aWebProgress
, nsIRequest
* aRequest
,
3595 WebProgressData
& aWebProgressData
, RequestData
& aRequestData
) {
3596 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3598 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3599 return NS_ERROR_UNEXPECTED
;
3602 aWebProgressData
.browsingContext() = docShell
->GetBrowsingContext();
3603 nsresult rv
= aWebProgress
->GetLoadType(&aWebProgressData
.loadType());
3604 NS_ENSURE_SUCCESS(rv
, rv
);
3606 return PrepareRequestData(aRequest
, aRequestData
);
3609 void BrowserChild::UpdateSessionStore() {
3610 if (mSessionStoreChild
) {
3611 mSessionStoreChild
->UpdateSessionStore();
3616 RefPtr
<PBrowserChild::IsWindowSupportingProtectedMediaPromise
>
3617 BrowserChild::DoesWindowSupportProtectedMedia() {
3620 "Protected media support check should be done on main thread only.");
3621 if (mWindowSupportsProtectedMedia
) {
3622 // If we've already checked and have a cached result, resolve with that.
3623 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3624 mWindowSupportsProtectedMedia
.value(), __func__
);
3626 RefPtr
<BrowserChild
> self
= this;
3627 // We chain off the promise rather than passing it directly so we can cache
3628 // the result and use that for future calls.
3629 return SendIsWindowSupportingProtectedMedia(ChromeOuterWindowID())
3631 GetCurrentSerialEventTarget(), __func__
,
3632 [self
](bool isSupported
) {
3633 // If a result was cached while this check was inflight, ensure the
3636 self
->mWindowSupportsProtectedMedia
,
3637 self
->mWindowSupportsProtectedMedia
.value() == isSupported
);
3638 // Cache the response as it will not change during the lifetime
3640 self
->mWindowSupportsProtectedMedia
= Some(isSupported
);
3641 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3642 self
->mWindowSupportsProtectedMedia
.value(), __func__
);
3644 [](ResponseRejectReason reason
) {
3645 return IsWindowSupportingProtectedMediaPromise::CreateAndReject(
3651 void BrowserChild::NotifyContentBlockingEvent(
3652 uint32_t aEvent
, nsIChannel
* aChannel
, bool aBlocked
,
3653 const nsACString
& aTrackingOrigin
,
3654 const nsTArray
<nsCString
>& aTrackingFullHashes
,
3656 mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
3658 const Maybe
<ContentBlockingNotifier::CanvasFingerprinter
>&
3659 aCanvasFingerprinter
,
3660 const Maybe
<bool> aCanvasFingerprinterKnownText
) {
3665 RequestData requestData
;
3666 if (NS_SUCCEEDED(PrepareRequestData(aChannel
, requestData
))) {
3667 Unused
<< SendNotifyContentBlockingEvent(
3668 aEvent
, requestData
, aBlocked
, PromiseFlatCString(aTrackingOrigin
),
3669 aTrackingFullHashes
, aReason
, aCanvasFingerprinter
,
3670 aCanvasFingerprinterKnownText
);
3675 BrowserChild::ContentTransformsReceived(JSContext
* aCx
,
3676 dom::Promise
** aPromise
) {
3677 auto* globalObject
= xpc::CurrentNativeGlobal(aCx
);
3679 if (mChildToParentConversionMatrix
) {
3680 // Already received content transforms
3681 RefPtr
<Promise
> promise
=
3682 Promise::CreateResolvedWithUndefined(globalObject
, rv
);
3683 promise
.forget(aPromise
);
3684 return rv
.StealNSResult();
3687 if (!mContentTransformPromise
) {
3688 mContentTransformPromise
= Promise::Create(globalObject
, rv
);
3691 MOZ_ASSERT(globalObject
== mContentTransformPromise
->GetGlobalObject());
3692 NS_IF_ADDREF(*aPromise
= mContentTransformPromise
);
3693 return rv
.StealNSResult();
3696 BrowserChildMessageManager::BrowserChildMessageManager(
3697 BrowserChild
* aBrowserChild
)
3698 : ContentFrameMessageManager(new nsFrameMessageManager(aBrowserChild
)),
3699 mBrowserChild(aBrowserChild
) {}
3701 BrowserChildMessageManager::~BrowserChildMessageManager() = default;
3703 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChildMessageManager
)
3705 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BrowserChildMessageManager
,
3706 DOMEventTargetHelper
)
3707 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager
);
3708 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild
);
3709 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
3710 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
3712 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BrowserChildMessageManager
,
3713 DOMEventTargetHelper
)
3714 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager
)
3715 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild
)
3716 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
3718 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChildMessageManager
)
3719 NS_INTERFACE_MAP_ENTRY(nsIMessageSender
)
3720 NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentFrameMessageManager
)
3721 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
3722 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
3724 NS_IMPL_ADDREF_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3725 NS_IMPL_RELEASE_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3727 JSObject
* BrowserChildMessageManager::WrapObject(
3728 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
3729 return ContentFrameMessageManager_Binding::Wrap(aCx
, this, aGivenProto
);
3732 void BrowserChildMessageManager::MarkForCC() {
3733 if (mBrowserChild
) {
3734 mBrowserChild
->MarkScopesForCC();
3736 EventListenerManager
* elm
= GetExistingListenerManager();
3740 MessageManagerGlobal::MarkForCC();
3743 Nullable
<WindowProxyHolder
> BrowserChildMessageManager::GetContent(
3744 ErrorResult
& aError
) {
3745 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell(aError
);
3749 return WindowProxyHolder(docShell
->GetBrowsingContext());
3752 already_AddRefed
<nsIDocShell
> BrowserChildMessageManager::GetDocShell(
3753 ErrorResult
& aError
) {
3754 if (!mBrowserChild
) {
3755 aError
.Throw(NS_ERROR_NULL_POINTER
);
3758 nsCOMPtr
<nsIDocShell
> window
=
3759 do_GetInterface(mBrowserChild
->WebNavigation());
3760 return window
.forget();
3763 already_AddRefed
<nsIEventTarget
>
3764 BrowserChildMessageManager::GetTabEventTarget() {
3765 return do_AddRef(GetMainThreadSerialEventTarget());
3768 nsresult
BrowserChildMessageManager::Dispatch(
3769 already_AddRefed
<nsIRunnable
>&& aRunnable
) const {
3770 return SchedulerGroup::Dispatch(std::move(aRunnable
));