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 "base/basictypes.h"
9 #include "BrowserChild.h"
12 # include "mozilla/a11y/DocAccessibleChild.h"
17 #include "BrowserParent.h"
18 #include "ContentChild.h"
19 #include "DocumentInlines.h"
20 #include "EventStateManager.h"
22 #include "MMPrinter.h"
23 #include "PermissionMessageUtils.h"
24 #include "PuppetWidget.h"
25 #include "StructuredCloneData.h"
26 #include "UnitTransforms.h"
28 #include "VRManagerChild.h"
29 #include "ipc/nsGUIEventIPC.h"
31 #include "mozilla/Assertions.h"
32 #include "mozilla/AsyncEventDispatcher.h"
33 #include "mozilla/BasePrincipal.h"
34 #include "mozilla/ClearOnShutdown.h"
35 #include "mozilla/EventForwards.h"
36 #include "mozilla/EventListenerManager.h"
37 #include "mozilla/HoldDropJSObjects.h"
38 #include "mozilla/IMEStateManager.h"
39 #include "mozilla/LookAndFeel.h"
40 #include "mozilla/MouseEvents.h"
41 #include "mozilla/NativeKeyBindingsType.h"
42 #include "mozilla/NullPrincipal.h"
43 #include "mozilla/Preferences.h"
44 #include "mozilla/PresShell.h"
45 #include "mozilla/ProcessHangMonitor.h"
46 #include "mozilla/ProfilerLabels.h"
47 #include "mozilla/ResultExtensions.h"
48 #include "mozilla/ScopeExit.h"
49 #include "mozilla/Services.h"
50 #include "mozilla/StaticPrefs_dom.h"
51 #include "mozilla/StaticPrefs_fission.h"
52 #include "mozilla/StaticPtr.h"
53 #include "mozilla/Telemetry.h"
54 #include "mozilla/TextEvents.h"
55 #include "mozilla/TouchEvents.h"
56 #include "mozilla/ToString.h"
57 #include "mozilla/Unused.h"
58 #include "mozilla/dom/AutoPrintEventDispatcher.h"
59 #include "mozilla/dom/BrowserBridgeChild.h"
60 #include "mozilla/dom/DataTransfer.h"
61 #include "mozilla/dom/DocGroup.h"
62 #include "mozilla/dom/Element.h"
63 #include "mozilla/dom/Event.h"
64 #include "mozilla/dom/JSWindowActorChild.h"
65 #include "mozilla/dom/ImageDocument.h"
66 #include "mozilla/dom/LoadURIOptionsBinding.h"
67 #include "mozilla/dom/MediaDocument.h"
68 #include "mozilla/dom/MessageManagerBinding.h"
69 #include "mozilla/dom/MouseEventBinding.h"
70 #include "mozilla/dom/Nullable.h"
71 #include "mozilla/dom/PBrowser.h"
72 #include "mozilla/dom/PaymentRequestChild.h"
73 #include "mozilla/dom/PointerEventHandler.h"
74 #include "mozilla/dom/SessionStoreUtils.h"
75 #include "mozilla/dom/SessionStoreChild.h"
76 #include "mozilla/dom/WindowGlobalChild.h"
77 #include "mozilla/dom/WindowProxyHolder.h"
78 #include "mozilla/gfx/CrossProcessPaint.h"
79 #include "mozilla/gfx/Matrix.h"
80 #include "mozilla/gfx/gfxVars.h"
81 #include "mozilla/ipc/BackgroundChild.h"
82 #include "mozilla/ipc/BackgroundUtils.h"
83 #include "mozilla/ipc/PBackgroundChild.h"
84 #include "mozilla/ipc/URIUtils.h"
85 #include "mozilla/layers/APZCCallbackHelper.h"
86 #include "mozilla/layers/TouchActionHelper.h"
87 #include "mozilla/layers/APZCTreeManagerChild.h"
88 #include "mozilla/layers/APZChild.h"
89 #include "mozilla/layers/APZEventState.h"
90 #include "mozilla/layers/CompositorBridgeChild.h"
91 #include "mozilla/layers/ContentProcessController.h"
92 #include "mozilla/layers/DoubleTapToZoom.h"
93 #include "mozilla/layers/IAPZCTreeManager.h"
94 #include "mozilla/layers/ImageBridgeChild.h"
95 #include "mozilla/layers/InputAPZContext.h"
96 #include "mozilla/layers/WebRenderLayerManager.h"
97 #include "nsBrowserStatusFilter.h"
98 #include "nsColorPickerProxy.h"
99 #include "nsCommandParams.h"
100 #include "nsContentPermissionHelper.h"
101 #include "nsContentUtils.h"
102 #include "nsDeviceContext.h"
103 #include "nsDocShell.h"
104 #include "nsDocShellLoadState.h"
105 #include "nsEmbedCID.h"
106 #include "nsExceptionHandler.h"
107 #include "nsFilePickerProxy.h"
108 #include "nsFocusManager.h"
109 #include "nsGlobalWindow.h"
110 #include "nsIBaseWindow.h"
111 #include "nsIBrowserDOMWindow.h"
112 #include "nsIClassifiedChannel.h"
113 #include "nsIDocShell.h"
114 #include "nsIFrame.h"
115 #include "nsILoadContext.h"
116 #include "nsISHEntry.h"
117 #include "nsISHistory.h"
118 #include "nsIScreenManager.h"
119 #include "nsIScriptError.h"
120 #include "nsISecureBrowserUI.h"
122 #include "nsIURIMutator.h"
123 #include "nsIWeakReferenceUtils.h"
124 #include "nsIWebBrowser.h"
125 #include "nsIWebProgress.h"
126 #include "nsLayoutUtils.h"
127 #include "nsNetUtil.h"
128 #include "nsIOpenWindowInfo.h"
129 #include "nsPIDOMWindow.h"
130 #include "nsPIWindowRoot.h"
131 #include "nsPointerHashKeys.h"
132 #include "nsPrintfCString.h"
133 #include "nsQueryActor.h"
134 #include "nsQueryObject.h"
135 #include "nsRefreshDriver.h"
136 #include "nsSandboxFlags.h"
137 #include "nsString.h"
138 #include "nsTHashtable.h"
139 #include "nsThreadManager.h"
140 #include "nsThreadUtils.h"
141 #include "nsViewManager.h"
142 #include "nsViewportInfo.h"
143 #include "nsWebBrowser.h"
144 #include "nsWindowWatcher.h"
145 #include "nsIXULRuntime.h"
148 # include "nsAppRunner.h"
152 # include "mozilla/layout/RemotePrintJobChild.h"
153 # include "nsIPrintSettings.h"
154 # include "nsIPrintSettingsService.h"
155 # include "nsIWebBrowserPrint.h"
158 static mozilla::LazyLogModule
sApzChildLog("apz.child");
160 using namespace mozilla
;
161 using namespace mozilla::dom
;
162 using namespace mozilla::dom::ipc
;
163 using namespace mozilla::ipc
;
164 using namespace mozilla::layers
;
165 using namespace mozilla::layout
;
166 using namespace mozilla::widget
;
167 using mozilla::layers::GeckoContentController
;
169 static const char BEFORE_FIRST_PAINT
[] = "before-first-paint";
171 static uint32_t sConsecutiveTouchMoveCount
= 0;
173 using BrowserChildMap
= nsTHashMap
<nsUint64HashKey
, BrowserChild
*>;
174 static BrowserChildMap
* sBrowserChildren
;
175 StaticMutex sBrowserChildrenMutex
;
177 already_AddRefed
<Document
> BrowserChild::GetTopLevelDocument() const {
178 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
179 nsCOMPtr
<Document
> doc
= docShell
? docShell
->GetExtantDocument() : nullptr;
183 PresShell
* BrowserChild::GetTopLevelPresShell() const {
184 if (RefPtr
<Document
> doc
= GetTopLevelDocument()) {
185 return doc
->GetPresShell();
190 bool BrowserChild::UpdateFrame(const RepaintRequest
& aRequest
) {
191 MOZ_ASSERT(aRequest
.GetScrollId() != ScrollableLayerGuid::NULL_SCROLL_ID
);
193 if (aRequest
.IsRootContent()) {
194 if (PresShell
* presShell
= GetTopLevelPresShell()) {
195 // Guard against stale updates (updates meant for a pres shell which
196 // has since been torn down and destroyed).
197 if (aRequest
.GetPresShellId() == presShell
->GetPresShellId()) {
198 APZCCallbackHelper::UpdateRootFrame(aRequest
);
203 // aRequest.mIsRoot is false, so we are trying to update a subframe.
204 // This requires special handling.
205 APZCCallbackHelper::UpdateSubFrame(aRequest
);
211 class BrowserChild::DelayedDeleteRunnable final
: public Runnable
,
212 public nsIRunnablePriority
{
213 RefPtr
<BrowserChild
> mBrowserChild
;
215 // In order to try that this runnable runs after everything that could
216 // possibly touch this tab, we send it through the event queue twice.
217 bool mReadyToDelete
= false;
220 explicit DelayedDeleteRunnable(BrowserChild
* aBrowserChild
)
221 : Runnable("BrowserChild::DelayedDeleteRunnable"),
222 mBrowserChild(aBrowserChild
) {
223 MOZ_ASSERT(NS_IsMainThread());
224 MOZ_ASSERT(aBrowserChild
);
227 NS_DECL_ISUPPORTS_INHERITED
230 ~DelayedDeleteRunnable() {
231 MOZ_ASSERT(NS_IsMainThread());
232 MOZ_ASSERT(!mBrowserChild
);
235 NS_IMETHOD
GetPriority(uint32_t* aPriority
) override
{
236 *aPriority
= nsIRunnablePriority::PRIORITY_NORMAL
;
242 MOZ_ASSERT(NS_IsMainThread());
243 MOZ_ASSERT(mBrowserChild
);
245 if (!mReadyToDelete
) {
246 // This time run this runnable at input priority.
247 mReadyToDelete
= true;
248 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(this));
252 // Check in case ActorDestroy was called after RecvDestroy message.
253 if (mBrowserChild
->IPCOpen()) {
254 Unused
<< PBrowserChild::Send__delete__(mBrowserChild
);
257 mBrowserChild
= nullptr;
262 NS_IMPL_ISUPPORTS_INHERITED(BrowserChild::DelayedDeleteRunnable
, Runnable
,
266 std::map
<TabId
, RefPtr
<BrowserChild
>>& NestedBrowserChildMap() {
267 MOZ_ASSERT(NS_IsMainThread());
268 static std::map
<TabId
, RefPtr
<BrowserChild
>> sNestedBrowserChildMap
;
269 return sNestedBrowserChildMap
;
273 already_AddRefed
<BrowserChild
> BrowserChild::FindBrowserChild(
274 const TabId
& aTabId
) {
275 auto iter
= NestedBrowserChildMap().find(aTabId
);
276 if (iter
== NestedBrowserChildMap().end()) {
279 RefPtr
<BrowserChild
> browserChild
= iter
->second
;
280 return browserChild
.forget();
284 already_AddRefed
<BrowserChild
> BrowserChild::Create(
285 ContentChild
* aManager
, const TabId
& aTabId
, const TabContext
& aContext
,
286 BrowsingContext
* aBrowsingContext
, uint32_t aChromeFlags
,
288 RefPtr
<BrowserChild
> iframe
= new BrowserChild(
289 aManager
, aTabId
, aContext
, aBrowsingContext
, aChromeFlags
, aIsTopLevel
);
290 return iframe
.forget();
293 BrowserChild::BrowserChild(ContentChild
* aManager
, const TabId
& aTabId
,
294 const TabContext
& aContext
,
295 BrowsingContext
* aBrowsingContext
,
296 uint32_t aChromeFlags
, bool aIsTopLevel
)
297 : TabContext(aContext
),
298 mBrowserChildMessageManager(nullptr),
300 mBrowsingContext(aBrowsingContext
),
301 mChromeFlags(aChromeFlags
),
304 mEffectsInfo
{EffectsInfo::FullyHidden()},
305 mDynamicToolbarMaxHeight(0),
308 mTriedBrowserInit(false),
309 mIgnoreKeyPressEvent(false),
310 mHasValidInnerSize(false),
312 mIsTopLevel(aIsTopLevel
),
314 mIsTransparent(false),
316 mDidSetRealShowInfo(false),
317 mDidLoadURLInit(false),
318 mSkipKeyPress(false),
319 mDidSetEffectsInfo(false),
320 mShouldSendWebProgressEventsToParent(false),
322 mIsPreservingLayers(false),
323 mPendingDocShellIsActive(false),
324 mPendingDocShellReceivedMessage(false),
325 mPendingRenderLayers(false),
326 mPendingRenderLayersReceivedMessage(false),
327 mLayersObserverEpoch
{1},
328 #if defined(XP_WIN) && defined(ACCESSIBILITY)
329 mNativeWindowHandle(0),
331 #if defined(ACCESSIBILITY)
332 mTopLevelDocAccessibleChild(nullptr),
334 mPendingLayersObserverEpoch
{0},
335 mPendingDocShellBlockers(0),
336 mCancelContentJSEpoch(0) {
337 mozilla::HoldJSObjects(this);
339 // preloaded BrowserChild should not be added to child map
341 MOZ_ASSERT(NestedBrowserChildMap().find(mUniqueId
) ==
342 NestedBrowserChildMap().end());
343 NestedBrowserChildMap()[mUniqueId
] = this;
345 mCoalesceMouseMoveEvents
= StaticPrefs::dom_events_coalesce_mousemove();
346 if (mCoalesceMouseMoveEvents
) {
347 mCoalescedMouseEventFlusher
= new CoalescedMouseMoveFlusher(this);
350 if (StaticPrefs::dom_events_coalesce_touchmove()) {
351 mCoalescedTouchMoveEventFlusher
= new CoalescedTouchMoveFlusher(this);
355 const CompositorOptions
& BrowserChild::GetCompositorOptions() const {
356 // If you're calling this before mCompositorOptions is set, well.. don't.
357 MOZ_ASSERT(mCompositorOptions
);
358 return mCompositorOptions
.ref();
361 bool BrowserChild::AsyncPanZoomEnabled() const {
362 // This might get called by the TouchEvent::PrefEnabled code before we have
363 // mCompositorOptions populated (bug 1370089). In that case we just assume
364 // APZ is enabled because we're in a content process (because BrowserChild)
365 // and APZ is probably going to be enabled here since e10s is enabled.
366 return mCompositorOptions
? mCompositorOptions
->UseAPZ() : true;
370 BrowserChild::Observe(nsISupports
* aSubject
, const char* aTopic
,
371 const char16_t
* aData
) {
372 if (!strcmp(aTopic
, BEFORE_FIRST_PAINT
)) {
373 if (AsyncPanZoomEnabled()) {
374 nsCOMPtr
<Document
> subject(do_QueryInterface(aSubject
));
375 nsCOMPtr
<Document
> doc(GetTopLevelDocument());
377 if (subject
== doc
) {
378 RefPtr
<PresShell
> presShell
= doc
->GetPresShell();
380 presShell
->SetIsFirstPaint(true);
383 APZCCallbackHelper::InitializeRootDisplayport(presShell
);
391 void BrowserChild::ContentReceivedInputBlock(uint64_t aInputBlockId
,
392 bool aPreventDefault
) const {
393 if (mApzcTreeManager
) {
394 mApzcTreeManager
->ContentReceivedInputBlock(aInputBlockId
, aPreventDefault
);
398 void BrowserChild::SetTargetAPZC(
399 uint64_t aInputBlockId
,
400 const nsTArray
<ScrollableLayerGuid
>& aTargets
) const {
401 if (mApzcTreeManager
) {
402 mApzcTreeManager
->SetTargetAPZC(aInputBlockId
, aTargets
);
406 bool BrowserChild::DoUpdateZoomConstraints(
407 const uint32_t& aPresShellId
, const ViewID
& aViewId
,
408 const Maybe
<ZoomConstraints
>& aConstraints
) {
409 if (!mApzcTreeManager
|| mDestroyed
) {
413 ScrollableLayerGuid guid
=
414 ScrollableLayerGuid(mLayersId
, aPresShellId
, aViewId
);
416 mApzcTreeManager
->UpdateZoomConstraints(guid
, aConstraints
);
420 nsresult
BrowserChild::Init(mozIDOMWindowProxy
* aParent
,
421 WindowGlobalChild
* aInitialWindowChild
) {
422 MOZ_ASSERT_IF(aInitialWindowChild
,
423 aInitialWindowChild
->BrowsingContext() == mBrowsingContext
);
425 nsCOMPtr
<nsIWidget
> widget
= nsIWidget::CreatePuppetWidget(this);
426 mPuppetWidget
= static_cast<PuppetWidget
*>(widget
.get());
427 if (!mPuppetWidget
) {
428 NS_ERROR("couldn't create fake widget");
429 return NS_ERROR_FAILURE
;
431 mPuppetWidget
->InfallibleCreate(nullptr,
432 nullptr, // no parents
433 LayoutDeviceIntRect(0, 0, 0, 0),
434 nullptr); // HandleWidgetEvent
436 mWebBrowser
= nsWebBrowser::Create(this, mPuppetWidget
, mBrowsingContext
,
437 aInitialWindowChild
);
438 nsIWebBrowser
* webBrowser
= mWebBrowser
;
440 mWebNav
= do_QueryInterface(webBrowser
);
441 NS_ASSERTION(mWebNav
, "nsWebBrowser doesn't implement nsIWebNavigation?");
443 // IPC uses a WebBrowser object for which DNS prefetching is turned off
444 // by default. But here we really want it, so enable it explicitly
445 mWebBrowser
->SetAllowDNSPrefetch(true);
447 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
448 MOZ_ASSERT(docShell
);
450 mStatusFilter
= new nsBrowserStatusFilter();
453 mStatusFilter
->AddProgressListener(this, nsIWebProgress::NOTIFY_ALL
);
454 NS_ENSURE_SUCCESS(rv
, rv
);
457 nsCOMPtr
<nsIWebProgress
> webProgress
= do_QueryInterface(docShell
);
458 rv
= webProgress
->AddProgressListener(mStatusFilter
,
459 nsIWebProgress::NOTIFY_ALL
);
460 NS_ENSURE_SUCCESS(rv
, rv
);
464 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(WebNavigation());
465 MOZ_ASSERT(loadContext
);
466 MOZ_ASSERT(loadContext
->UseRemoteTabs() ==
467 !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
));
468 MOZ_ASSERT(loadContext
->UseRemoteSubframes() ==
469 !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
));
470 #endif // defined(DEBUG)
472 // Few lines before, baseWindow->Create() will end up creating a new
473 // window root in nsGlobalWindow::SetDocShell.
474 // Then this chrome event handler, will be inherited to inner windows.
475 // We want to also set it to the docshell so that inner windows
476 // and any code that has access to the docshell
477 // can all listen to the same chrome event handler.
478 // XXX: ideally, we would set a chrome event handler earlier,
479 // and all windows, even the root one, will use the docshell one.
480 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
481 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
482 nsCOMPtr
<EventTarget
> chromeHandler
= window
->GetChromeEventHandler();
483 docShell
->SetChromeEventHandler(chromeHandler
);
485 if (window
->GetCurrentInnerWindow()) {
486 window
->SetKeyboardIndicators(ShowFocusRings());
488 // Skip ShouldShowFocusRing check if no inner window is available
489 window
->SetInitialKeyboardIndicators(ShowFocusRings());
492 // Window scrollbar flags only affect top level remote frames, not fission
495 nsContentUtils::SetScrollbarsVisibility(
496 docShell
, !!(mChromeFlags
& nsIWebBrowserChrome::CHROME_SCROLLBARS
));
499 nsWeakPtr weakPtrThis
= do_GetWeakReference(
500 static_cast<nsIBrowserChild
*>(this)); // for capture by the lambda
501 ContentReceivedInputBlockCallback
callback(
502 [weakPtrThis
](uint64_t aInputBlockId
, bool aPreventDefault
) {
503 if (nsCOMPtr
<nsIBrowserChild
> browserChild
=
504 do_QueryReferent(weakPtrThis
)) {
505 static_cast<BrowserChild
*>(browserChild
.get())
506 ->ContentReceivedInputBlock(aInputBlockId
, aPreventDefault
);
509 mAPZEventState
= new APZEventState(mPuppetWidget
, std::move(callback
));
513 if (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) {
514 mSessionStoreChild
= SessionStoreChild::GetOrCreate(mBrowsingContext
);
517 // We've all set up, make sure our visibility state is consistent. This is
518 // important for OOP iframes, which start off as hidden.
524 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChild
)
526 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild
)
527 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChildMessageManager
)
528 tmp
->nsMessageManagerScriptExecutor::Unlink();
529 NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter
)
530 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav
)
531 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext
)
532 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChild
)
533 NS_IMPL_CYCLE_COLLECTION_UNLINK(mContentTransformPromise
)
534 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
535 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
537 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild
)
538 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChildMessageManager
)
539 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter
)
540 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav
)
541 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext
)
542 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChild
)
543 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentTransformPromise
)
544 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
546 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild
)
547 tmp
->nsMessageManagerScriptExecutor::Trace(aCallbacks
, aClosure
);
548 NS_IMPL_CYCLE_COLLECTION_TRACE_END
550 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild
)
551 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome
)
552 NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow
)
553 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus
)
554 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
555 NS_INTERFACE_MAP_ENTRY(nsIWindowProvider
)
556 NS_INTERFACE_MAP_ENTRY(nsIBrowserChild
)
557 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
558 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
559 NS_INTERFACE_MAP_ENTRY(nsITooltipListener
)
560 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener
)
561 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener2
)
562 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIBrowserChild
)
565 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserChild
)
566 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserChild
)
569 BrowserChild::GetChromeFlags(uint32_t* aChromeFlags
) {
570 *aChromeFlags
= mChromeFlags
;
575 BrowserChild::SetChromeFlags(uint32_t aChromeFlags
) {
576 NS_WARNING("trying to SetChromeFlags from content process?");
578 return NS_ERROR_NOT_IMPLEMENTED
;
582 BrowserChild::RemoteSizeShellTo(int32_t aWidth
, int32_t aHeight
,
583 int32_t aShellItemWidth
,
584 int32_t aShellItemHeight
) {
585 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
586 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(ourDocShell
));
587 NS_ENSURE_STATE(docShellAsWin
);
589 int32_t width
, height
;
590 docShellAsWin
->GetSize(&width
, &height
);
593 if (width
== aWidth
) {
594 flags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX
;
597 if (height
== aHeight
) {
598 flags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY
;
601 bool sent
= SendSizeShellTo(flags
, aWidth
, aHeight
, aShellItemWidth
,
604 return sent
? NS_OK
: NS_ERROR_FAILURE
;
608 BrowserChild::RemoteDropLinks(
609 const nsTArray
<RefPtr
<nsIDroppedLinkItem
>>& aLinks
) {
610 nsTArray
<nsString
> linksArray
;
612 for (nsIDroppedLinkItem
* link
: aLinks
) {
614 rv
= link
->GetUrl(tmp
);
618 linksArray
.AppendElement(tmp
);
620 rv
= link
->GetName(tmp
);
624 linksArray
.AppendElement(tmp
);
626 rv
= link
->GetType(tmp
);
630 linksArray
.AppendElement(tmp
);
632 bool sent
= SendDropLinks(linksArray
);
634 return sent
? NS_OK
: NS_ERROR_FAILURE
;
638 BrowserChild::ShowAsModal() {
639 NS_WARNING("BrowserChild::ShowAsModal not supported in BrowserChild");
641 return NS_ERROR_NOT_IMPLEMENTED
;
645 BrowserChild::IsWindowModal(bool* aRetVal
) {
651 BrowserChild::SetLinkStatus(const nsAString
& aStatusText
) {
652 // We can only send the status after the ipc machinery is set up
654 SendSetLinkStatus(aStatusText
);
660 BrowserChild::SetDimensions(uint32_t aFlags
, int32_t aX
, int32_t aY
,
661 int32_t aCx
, int32_t aCy
) {
662 // The parent is in charge of the dimension changes. If JS code wants to
663 // change the dimensions (moveTo, screenX, etc.) we send a message to the
664 // parent about the new requested dimension, the parent does the resize/move
665 // then send a message to the child to update itself. For APIs like screenX
666 // this function is called with the current value for the non-changed values.
667 // In a series of calls like window.screenX = 10; window.screenY = 10; for
668 // the second call, since screenX is not yet updated we might accidentally
669 // reset back screenX to it's old value. To avoid this if a parameter did not
670 // change we want the parent to ignore its value.
671 int32_t x
, y
, cx
, cy
;
672 GetDimensions(aFlags
, &x
, &y
, &cx
, &cy
);
675 aFlags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X
;
679 aFlags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y
;
683 aFlags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX
;
687 aFlags
|= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY
;
690 double scale
= mPuppetWidget
? mPuppetWidget
->GetDefaultScale().scale
: 1.0;
692 Unused
<< SendSetDimensions(aFlags
, aX
, aY
, aCx
, aCy
, scale
);
698 BrowserChild::GetDimensions(uint32_t aFlags
, int32_t* aX
, int32_t* aY
,
699 int32_t* aCx
, int32_t* aCy
) {
700 ScreenIntRect rect
= GetOuterRect();
718 BrowserChild::GetVisibility(bool* aVisibility
) {
724 BrowserChild::SetVisibility(bool aVisibility
) {
725 // should the platform support this? Bug 666365
730 BrowserChild::GetTitle(nsAString
& aTitle
) {
731 NS_WARNING("BrowserChild::GetTitle not supported in BrowserChild");
733 return NS_ERROR_NOT_IMPLEMENTED
;
737 BrowserChild::SetTitle(const nsAString
& aTitle
) {
738 // JavaScript sends the "DOMTitleChanged" event to the parent
739 // via the message manager.
744 BrowserChild::GetSiteWindow(void** aSiteWindow
) {
745 NS_WARNING("BrowserChild::GetSiteWindow not supported in BrowserChild");
747 return NS_ERROR_NOT_IMPLEMENTED
;
751 BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED
; }
754 BrowserChild::FocusNextElement(bool aForDocumentNavigation
) {
755 SendMoveFocus(true, aForDocumentNavigation
);
760 BrowserChild::FocusPrevElement(bool aForDocumentNavigation
) {
761 SendMoveFocus(false, aForDocumentNavigation
);
766 BrowserChild::GetInterface(const nsIID
& aIID
, void** aSink
) {
767 // XXXbz should we restrict the set of interfaces we hand out here?
769 return QueryInterface(aIID
, aSink
);
773 BrowserChild::ProvideWindow(nsIOpenWindowInfo
* aOpenWindowInfo
,
774 uint32_t aChromeFlags
, bool aCalledFromJS
,
775 nsIURI
* aURI
, const nsAString
& aName
,
776 const nsACString
& aFeatures
, bool aForceNoOpener
,
777 bool aForceNoReferrer
, bool aIsPopupRequested
,
778 nsDocShellLoadState
* aLoadState
, bool* aWindowIsNew
,
779 BrowsingContext
** aReturn
) {
782 RefPtr
<BrowsingContext
> parent
= aOpenWindowInfo
->GetParent();
784 int32_t openLocation
= nsWindowWatcher::GetWindowOpenLocation(
785 parent
->GetDOMWindow(), aChromeFlags
, aCalledFromJS
,
786 aOpenWindowInfo
->GetIsForPrinting());
788 // If it turns out we're opening in the current browser, just hand over the
789 // current browser's docshell.
790 if (openLocation
== nsIBrowserDOMWindow::OPEN_CURRENTWINDOW
) {
791 nsCOMPtr
<nsIWebBrowser
> browser
= do_GetInterface(WebNavigation());
792 *aWindowIsNew
= false;
794 nsCOMPtr
<mozIDOMWindowProxy
> win
;
795 MOZ_TRY(browser
->GetContentDOMWindow(getter_AddRefs(win
)));
797 RefPtr
<BrowsingContext
> bc(
798 nsPIDOMWindowOuter::From(win
)->GetBrowsingContext());
803 // Note that ProvideWindowCommon may return NS_ERROR_ABORT if the
804 // open window call was canceled. It's important that we pass this error
805 // code back to our caller.
806 ContentChild
* cc
= ContentChild::GetSingleton();
807 return cc
->ProvideWindowCommon(
808 this, aOpenWindowInfo
, aChromeFlags
, aCalledFromJS
, aURI
, aName
,
809 aFeatures
, aForceNoOpener
, aForceNoReferrer
, aIsPopupRequested
,
810 aLoadState
, aWindowIsNew
, aReturn
);
813 void BrowserChild::DestroyWindow() {
814 mBrowsingContext
= nullptr;
817 if (nsCOMPtr
<nsIWebProgress
> webProgress
=
818 do_QueryInterface(WebNavigation())) {
819 webProgress
->RemoveProgressListener(mStatusFilter
);
822 mStatusFilter
->RemoveProgressListener(this);
823 mStatusFilter
= nullptr;
826 if (mCoalescedMouseEventFlusher
) {
827 mCoalescedMouseEventFlusher
->RemoveObserver();
828 mCoalescedMouseEventFlusher
= nullptr;
831 if (mCoalescedTouchMoveEventFlusher
) {
832 mCoalescedTouchMoveEventFlusher
->RemoveObserver();
833 mCoalescedTouchMoveEventFlusher
= nullptr;
836 if (mSessionStoreChild
) {
837 mSessionStoreChild
->Stop();
838 mSessionStoreChild
= nullptr;
841 // In case we don't have chance to process all entries, clean all data in
843 while (mToBeDispatchedMouseData
.GetSize() > 0) {
844 UniquePtr
<CoalescedMouseData
> data(
845 static_cast<CoalescedMouseData
*>(mToBeDispatchedMouseData
.PopFront()));
849 nsCOMPtr
<nsIBaseWindow
> baseWindow
= do_QueryInterface(WebNavigation());
850 if (baseWindow
) baseWindow
->Destroy();
853 mPuppetWidget
->Destroy();
856 mLayersConnected
= Nothing();
858 if (mLayersId
.IsValid()) {
859 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
861 MOZ_ASSERT(sBrowserChildren
);
862 sBrowserChildren
->Remove(uint64_t(mLayersId
));
863 if (!sBrowserChildren
->Count()) {
864 delete sBrowserChildren
;
865 sBrowserChildren
= nullptr;
867 mLayersId
= layers::LayersId
{0};
871 void BrowserChild::ActorDestroy(ActorDestroyReason why
) {
876 if (mBrowserChildMessageManager
) {
877 // We should have a message manager if the global is alive, but it
878 // seems sometimes we don't. Assert in aurora/nightly, but don't
879 // crash in release builds.
880 MOZ_DIAGNOSTIC_ASSERT(mBrowserChildMessageManager
->GetMessageManager());
881 if (mBrowserChildMessageManager
->GetMessageManager()) {
882 // The messageManager relays messages via the BrowserChild which
884 mBrowserChildMessageManager
->DisconnectMessageManager();
888 if (GetTabId() != 0) {
889 NestedBrowserChildMap().erase(GetTabId());
893 BrowserChild::~BrowserChild() {
894 mAnonymousGlobalScopes
.Clear();
898 nsCOMPtr
<nsIWebBrowser
> webBrowser
= do_QueryInterface(WebNavigation());
900 webBrowser
->SetContainerWindow(nullptr);
903 mozilla::DropJSObjects(this);
906 mozilla::ipc::IPCResult
BrowserChild::RecvWillChangeProcess() {
908 mWebBrowser
->SetWillChangeProcess();
913 mozilla::ipc::IPCResult
BrowserChild::RecvLoadURL(
914 nsDocShellLoadState
* aLoadState
, const ParentShowInfo
& aInfo
) {
915 if (!mDidLoadURLInit
) {
916 mDidLoadURLInit
= true;
917 if (!InitBrowserChildMessageManager()) {
918 return IPC_FAIL_NO_REASON(this);
921 ApplyParentShowInfo(aInfo
);
924 aLoadState
->URI()->GetSpec(spec
);
926 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
928 NS_WARNING("WebNavigation does not have a docshell");
931 docShell
->LoadURI(aLoadState
, true);
933 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL
, spec
);
937 mozilla::ipc::IPCResult
BrowserChild::RecvCreateAboutBlankContentViewer(
938 nsIPrincipal
* aPrincipal
, nsIPrincipal
* aPartitionedPrincipal
) {
939 if (aPrincipal
->GetIsExpandedPrincipal() ||
940 aPartitionedPrincipal
->GetIsExpandedPrincipal()) {
941 return IPC_FAIL(this, "Cannot create document with an expanded principal");
943 if (aPrincipal
->IsSystemPrincipal() ||
944 aPartitionedPrincipal
->IsSystemPrincipal()) {
945 MOZ_ASSERT_UNREACHABLE(
946 "Cannot use CreateAboutBlankContentViewer to create system principal "
947 "document in content");
951 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
953 MOZ_ASSERT_UNREACHABLE("WebNavigation does not have a docshell");
957 nsCOMPtr
<nsIURI
> currentURI
;
959 WebNavigation()->GetCurrentURI(getter_AddRefs(currentURI
)));
960 if (!currentURI
|| !NS_IsAboutBlank(currentURI
)) {
961 NS_WARNING("Can't create a ContentViewer unless on about:blank");
965 docShell
->CreateAboutBlankContentViewer(aPrincipal
, aPartitionedPrincipal
,
970 mozilla::ipc::IPCResult
BrowserChild::RecvResumeLoad(
971 const uint64_t& aPendingSwitchID
, const ParentShowInfo
& aInfo
) {
972 if (!mDidLoadURLInit
) {
973 mDidLoadURLInit
= true;
974 if (!InitBrowserChildMessageManager()) {
975 return IPC_FAIL_NO_REASON(this);
978 ApplyParentShowInfo(aInfo
);
981 nsresult rv
= WebNavigation()->ResumeRedirectedLoad(aPendingSwitchID
, -1);
983 NS_WARNING("WebNavigation()->ResumeRedirectedLoad failed");
989 nsresult
BrowserChild::CloneDocumentTreeIntoSelf(
990 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
991 const embedding::PrintData
& aPrintData
) {
993 if (NS_WARN_IF(aSourceBC
.IsNullOrDiscarded())) {
994 return NS_ERROR_FAILURE
;
996 nsCOMPtr
<Document
> sourceDocument
= aSourceBC
.get()->GetDocument();
997 if (NS_WARN_IF(!sourceDocument
)) {
998 return NS_ERROR_FAILURE
;
1001 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
1002 if (NS_WARN_IF(!ourDocShell
)) {
1003 return NS_ERROR_FAILURE
;
1006 nsCOMPtr
<nsIContentViewer
> cv
;
1007 ourDocShell
->GetContentViewer(getter_AddRefs(cv
));
1008 if (NS_WARN_IF(!cv
)) {
1009 return NS_ERROR_FAILURE
;
1012 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
1013 do_GetService("@mozilla.org/gfx/printsettings-service;1");
1014 if (NS_WARN_IF(!printSettingsSvc
)) {
1015 return NS_ERROR_FAILURE
;
1018 nsCOMPtr
<nsIPrintSettings
> printSettings
;
1020 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
1021 if (NS_WARN_IF(NS_FAILED(rv
))) {
1025 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
1027 RefPtr
<Document
> clone
;
1029 AutoPrintEventDispatcher
dispatcher(*sourceDocument
, printSettings
,
1030 /* aIsTop = */ false);
1031 nsAutoScriptBlocker scriptBlocker
;
1032 bool hasInProcessCallbacks
= false;
1033 clone
= sourceDocument
->CreateStaticClone(ourDocShell
, cv
, printSettings
,
1034 &hasInProcessCallbacks
);
1035 if (NS_WARN_IF(!clone
)) {
1036 return NS_ERROR_FAILURE
;
1040 rv
= UpdateRemotePrintSettings(aPrintData
);
1041 if (NS_FAILED(rv
)) {
1049 mozilla::ipc::IPCResult
BrowserChild::RecvCloneDocumentTreeIntoSelf(
1050 const MaybeDiscarded
<BrowsingContext
>& aSourceBC
,
1051 const embedding::PrintData
& aPrintData
,
1052 CloneDocumentTreeIntoSelfResolver
&& aResolve
) {
1053 nsresult rv
= NS_OK
;
1056 rv
= CloneDocumentTreeIntoSelf(aSourceBC
, aPrintData
);
1059 aResolve(NS_SUCCEEDED(rv
));
1063 nsresult
BrowserChild::UpdateRemotePrintSettings(
1064 const embedding::PrintData
& aPrintData
) {
1066 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
1067 if (NS_WARN_IF(!ourDocShell
)) {
1068 return NS_ERROR_FAILURE
;
1071 RefPtr
<Document
> doc
= ourDocShell
->GetExtantDocument();
1072 if (NS_WARN_IF(!doc
) || NS_WARN_IF(!doc
->IsStaticDocument())) {
1073 return NS_ERROR_FAILURE
;
1076 RefPtr
<BrowsingContext
> bc
= ourDocShell
->GetBrowsingContext();
1077 if (NS_WARN_IF(!bc
)) {
1078 return NS_ERROR_FAILURE
;
1081 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
1082 do_GetService("@mozilla.org/gfx/printsettings-service;1");
1083 if (NS_WARN_IF(!printSettingsSvc
)) {
1084 return NS_ERROR_FAILURE
;
1087 nsCOMPtr
<nsIPrintSettings
> printSettings
;
1089 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
1090 if (NS_WARN_IF(NS_FAILED(rv
))) {
1094 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
1096 bc
->PreOrderWalk([&](BrowsingContext
* aBc
) {
1097 if (nsCOMPtr
<nsIDocShell
> inProcess
= aBc
->GetDocShell()) {
1098 nsCOMPtr
<nsIContentViewer
> cv
;
1099 inProcess
->GetContentViewer(getter_AddRefs(cv
));
1100 if (NS_WARN_IF(!cv
)) {
1101 return BrowsingContext::WalkFlag::Skip
;
1103 // The CanRunScript analysis is not smart enough to see across
1104 // the std::function PreOrderWalk uses, so we cheat a bit here, but it is
1105 // fine because PreOrderWalk does deal with arbitrary script changing the
1106 // BC tree, and our code above is simple enough and keeps strong refs to
1108 ([&]() MOZ_CAN_RUN_SCRIPT_BOUNDARY
{
1109 RefPtr
<RemotePrintJobChild
> printJob
=
1110 static_cast<RemotePrintJobChild
*>(aPrintData
.remotePrintJobChild());
1111 cv
->SetPrintSettingsForSubdocument(printSettings
, printJob
);
1113 } else if (RefPtr
<BrowserBridgeChild
> remoteChild
=
1114 BrowserBridgeChild::GetFrom(aBc
->GetEmbedderElement())) {
1115 Unused
<< remoteChild
->SendUpdateRemotePrintSettings(aPrintData
);
1116 return BrowsingContext::WalkFlag::Skip
;
1118 return BrowsingContext::WalkFlag::Next
;
1125 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemotePrintSettings(
1126 const embedding::PrintData
& aPrintData
) {
1128 UpdateRemotePrintSettings(aPrintData
);
1134 void BrowserChild::DoFakeShow(const ParentShowInfo
& aParentShowInfo
) {
1135 OwnerShowInfo ownerInfo
{ScreenIntSize(), ScrollbarPreference::Auto
,
1137 RecvShow(aParentShowInfo
, ownerInfo
);
1138 mDidFakeShow
= true;
1141 void BrowserChild::ApplyParentShowInfo(const ParentShowInfo
& aInfo
) {
1142 // Even if we already set real show info, the dpi / rounding & scale may still
1143 // be invalid (if BrowserParent wasn't able to get widget it would just send
1144 // 0). So better to always set up-to-date values here.
1145 if (aInfo
.dpi() > 0) {
1146 mPuppetWidget
->UpdateBackingScaleCache(aInfo
.dpi(), aInfo
.widgetRounding(),
1147 aInfo
.defaultScale());
1150 if (mDidSetRealShowInfo
) {
1154 if (!aInfo
.fakeShowInfo()) {
1155 // Once we've got one ShowInfo from parent, no need to update the values
1157 mDidSetRealShowInfo
= true;
1160 mIsTransparent
= aInfo
.isTransparent();
1163 mozilla::ipc::IPCResult
BrowserChild::RecvShow(
1164 const ParentShowInfo
& aParentInfo
, const OwnerShowInfo
& aOwnerInfo
) {
1167 mPuppetWidget
->SetSizeMode(aOwnerInfo
.sizeMode());
1168 if (!mDidFakeShow
) {
1169 nsCOMPtr
<nsIBaseWindow
> baseWindow
= do_QueryInterface(WebNavigation());
1171 NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
1172 return IPC_FAIL_NO_REASON(this);
1175 baseWindow
->SetVisibility(true);
1176 res
= InitBrowserChildMessageManager();
1179 ApplyParentShowInfo(aParentInfo
);
1182 RecvScrollbarPreferenceChanged(aOwnerInfo
.scrollbarPreference());
1186 return IPC_FAIL_NO_REASON(this);
1194 mozilla::ipc::IPCResult
BrowserChild::RecvInitRendering(
1195 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
1196 const layers::LayersId
& aLayersId
,
1197 const CompositorOptions
& aCompositorOptions
, const bool& aLayersConnected
) {
1198 mLayersConnected
= Some(aLayersConnected
);
1199 mLayersConnectRequested
= Some(aLayersConnected
);
1200 InitRenderingState(aTextureFactoryIdentifier
, aLayersId
, aCompositorOptions
);
1204 mozilla::ipc::IPCResult
BrowserChild::RecvScrollbarPreferenceChanged(
1205 ScrollbarPreference aPreference
) {
1206 MOZ_ASSERT(!mIsTopLevel
,
1207 "Scrollbar visibility should be derived from chrome flags for "
1208 "top-level windows");
1209 if (nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation())) {
1210 nsDocShell::Cast(docShell
)->SetScrollbarPreference(aPreference
);
1215 mozilla::ipc::IPCResult
BrowserChild::RecvCompositorOptionsChanged(
1216 const CompositorOptions
& aNewOptions
) {
1217 MOZ_ASSERT(mCompositorOptions
);
1219 // The only compositor option we currently support changing is APZ
1220 // enablement. Even that is only partially supported for now:
1221 // * Going from APZ to non-APZ is fine - we just flip the stored flag.
1222 // Note that we keep the actors (mApzcTreeManager, and the APZChild
1223 // created in InitAPZState()) around (read on for why).
1224 // * Going from non-APZ to APZ is only supported if we were using
1225 // APZ initially (at InitRendering() time) and we are transitioning
1226 // back. In this case, we just reuse the actors which we kept around.
1227 // Fully supporting a non-APZ to APZ transition (i.e. even in cases
1228 // where we initialized as non-APZ) would require setting up the actors
1229 // here. (In that case, we would also have the options of destroying
1230 // the actors in the APZ --> non-APZ case, and always re-creating them
1231 // during a non-APZ --> APZ transition).
1232 mCompositorOptions
->SetUseAPZ(aNewOptions
.UseAPZ());
1236 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateDimensions(
1237 const DimensionInfo
& aDimensionInfo
) {
1238 if (mLayersConnected
.isNothing()) {
1242 mUnscaledOuterRect
= aDimensionInfo
.rect();
1243 mClientOffset
= aDimensionInfo
.clientOffset();
1244 mChromeOffset
= aDimensionInfo
.chromeOffset();
1245 MOZ_ASSERT_IF(!IsTopLevel(), mChromeOffset
== LayoutDeviceIntPoint());
1247 SetUnscaledInnerSize(aDimensionInfo
.size());
1248 if (!mHasValidInnerSize
&& aDimensionInfo
.size().width
!= 0 &&
1249 aDimensionInfo
.size().height
!= 0) {
1250 mHasValidInnerSize
= true;
1253 ScreenIntSize screenSize
= GetInnerSize();
1254 ScreenIntRect screenRect
= GetOuterRect();
1256 // Make sure to set the size on the document viewer first. The
1257 // MobileViewportManager needs the content viewer size to be updated before
1258 // the reflow, otherwise it gets a stale size when it computes a new CSS
1260 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
1261 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
1262 nsIBaseWindow::eRepaint
);
1264 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
1265 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
1266 screenSize
.width
, screenSize
.height
, true);
1268 RecvSafeAreaInsetsChanged(mPuppetWidget
->GetSafeAreaInsets());
1273 mozilla::ipc::IPCResult
BrowserChild::RecvSizeModeChanged(
1274 const nsSizeMode
& aSizeMode
) {
1275 mPuppetWidget
->SetSizeMode(aSizeMode
);
1276 if (!mPuppetWidget
->IsVisible()) {
1279 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1283 nsPresContext
* presContext
= document
->GetPresContext();
1285 presContext
->SizeModeChanged(aSizeMode
);
1290 mozilla::ipc::IPCResult
BrowserChild::RecvChildToParentMatrix(
1291 const Maybe
<gfx::Matrix4x4
>& aMatrix
,
1292 const ScreenRect
& aTopLevelViewportVisibleRectInBrowserCoords
) {
1293 mChildToParentConversionMatrix
=
1294 LayoutDeviceToLayoutDeviceMatrix4x4::FromUnknownMatrix(aMatrix
);
1295 mTopLevelViewportVisibleRectInBrowserCoords
=
1296 aTopLevelViewportVisibleRectInBrowserCoords
;
1298 if (mContentTransformPromise
) {
1299 mContentTransformPromise
->MaybeResolveWithUndefined();
1300 mContentTransformPromise
= nullptr;
1303 // Trigger an intersection observation update since ancestor viewports
1305 if (RefPtr
<Document
> toplevelDoc
= GetTopLevelDocument()) {
1306 if (nsPresContext
* pc
= toplevelDoc
->GetPresContext()) {
1307 pc
->RefreshDriver()->EnsureIntersectionObservationsUpdateHappens();
1314 mozilla::ipc::IPCResult
BrowserChild::RecvSetIsUnderHiddenEmbedderElement(
1315 const bool& aIsUnderHiddenEmbedderElement
) {
1316 if (RefPtr
<PresShell
> presShell
= GetTopLevelPresShell()) {
1317 presShell
->SetIsUnderHiddenEmbedderElement(aIsUnderHiddenEmbedderElement
);
1322 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateRemoteStyle(
1323 const StyleImageRendering
& aImageRendering
) {
1324 BrowsingContext
* context
= GetBrowsingContext();
1329 Document
* document
= context
->GetDocument();
1334 if (document
->IsImageDocument()) {
1335 document
->AsImageDocument()->UpdateRemoteStyle(aImageRendering
);
1341 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarMaxHeightChanged(
1342 const ScreenIntCoord
& aHeight
) {
1343 #if defined(MOZ_WIDGET_ANDROID)
1344 mDynamicToolbarMaxHeight
= aHeight
;
1346 RefPtr
<Document
> document
= GetTopLevelDocument();
1351 if (RefPtr
<nsPresContext
> presContext
= document
->GetPresContext()) {
1352 presContext
->SetDynamicToolbarMaxHeight(aHeight
);
1358 mozilla::ipc::IPCResult
BrowserChild::RecvDynamicToolbarOffsetChanged(
1359 const ScreenIntCoord
& aOffset
) {
1360 #if defined(MOZ_WIDGET_ANDROID)
1361 RefPtr
<Document
> document
= GetTopLevelDocument();
1366 if (nsPresContext
* presContext
= document
->GetPresContext()) {
1367 presContext
->UpdateDynamicToolbarOffset(aOffset
);
1373 mozilla::ipc::IPCResult
BrowserChild::RecvSuppressDisplayport(
1374 const bool& aEnabled
) {
1375 if (RefPtr
<PresShell
> presShell
= GetTopLevelPresShell()) {
1376 presShell
->SuppressDisplayport(aEnabled
);
1381 void BrowserChild::HandleDoubleTap(const CSSPoint
& aPoint
,
1382 const Modifiers
& aModifiers
,
1383 const ScrollableLayerGuid
& aGuid
) {
1385 sApzChildLog
, LogLevel::Debug
,
1386 ("Handling double tap at %s with %p %p\n", ToString(aPoint
).c_str(),
1387 mBrowserChildMessageManager
? mBrowserChildMessageManager
->GetWrapper()
1389 mBrowserChildMessageManager
.get()));
1391 if (!mBrowserChildMessageManager
) {
1395 // Note: there is nothing to do with the modifiers here, as we are not
1396 // synthesizing any sort of mouse event.
1397 RefPtr
<Document
> document
= GetTopLevelDocument();
1398 ZoomTarget zoomTarget
= CalculateRectToZoomTo(document
, aPoint
);
1399 // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
1400 // the guid of any scroll frame), but the zoom-to-rect operation must be
1401 // performed by the root content scroll frame, so query its identifiers
1402 // for the SendZoomToRect() call rather than using the ones from |aGuid|.
1403 uint32_t presShellId
;
1405 if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
1406 document
->GetDocumentElement(), &presShellId
, &viewId
) &&
1408 ScrollableLayerGuid
guid(mLayersId
, presShellId
, viewId
);
1410 mApzcTreeManager
->ZoomToRect(guid
, zoomTarget
,
1411 ZoomToRectBehavior::DEFAULT_BEHAVIOR
);
1415 mozilla::ipc::IPCResult
BrowserChild::RecvHandleTap(
1416 const GeckoContentController::TapType
& aType
,
1417 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1418 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
) {
1419 // IPDL doesn't hold a strong reference to protocols as they're not required
1420 // to be refcounted. This function can run script, which may trigger a nested
1421 // event loop, which may release this, so we hold a strong reference here.
1422 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1423 RefPtr
<PresShell
> presShell
= GetTopLevelPresShell();
1427 if (!presShell
->GetPresContext()) {
1430 CSSToLayoutDeviceScale
scale(
1431 presShell
->GetPresContext()->CSSToDevPixelScale());
1432 CSSPoint point
= aPoint
/ scale
;
1434 // Stash the guid in InputAPZContext so that when the visual-to-layout
1435 // transform is applied to the event's coordinates, we use the right transform
1436 // based on the scroll frame being targeted.
1437 // The other values don't really matter.
1438 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1441 case GeckoContentController::TapType::eSingleTap
:
1442 if (mBrowserChildMessageManager
) {
1443 mAPZEventState
->ProcessSingleTap(point
, scale
, aModifiers
, 1);
1446 case GeckoContentController::TapType::eDoubleTap
:
1447 HandleDoubleTap(point
, aModifiers
, aGuid
);
1449 case GeckoContentController::TapType::eSecondTap
:
1450 if (mBrowserChildMessageManager
) {
1451 mAPZEventState
->ProcessSingleTap(point
, scale
, aModifiers
, 2);
1454 case GeckoContentController::TapType::eLongTap
:
1455 if (mBrowserChildMessageManager
) {
1456 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1457 eventState
->ProcessLongTap(presShell
, point
, scale
, aModifiers
,
1461 case GeckoContentController::TapType::eLongTapUp
:
1462 if (mBrowserChildMessageManager
) {
1463 RefPtr
<APZEventState
> eventState(mAPZEventState
);
1464 eventState
->ProcessLongTapUp(presShell
, point
, scale
, aModifiers
);
1471 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityHandleTap(
1472 const GeckoContentController::TapType
& aType
,
1473 const LayoutDevicePoint
& aPoint
, const Modifiers
& aModifiers
,
1474 const ScrollableLayerGuid
& aGuid
, const uint64_t& aInputBlockId
) {
1475 // IPDL doesn't hold a strong reference to protocols as they're not required
1476 // to be refcounted. This function can run script, which may trigger a nested
1477 // event loop, which may release this, so we hold a strong reference here.
1478 RefPtr
<BrowserChild
> kungFuDeathGrip(this);
1479 return RecvHandleTap(aType
, aPoint
, aModifiers
, aGuid
, aInputBlockId
);
1482 bool BrowserChild::NotifyAPZStateChange(
1483 const ViewID
& aViewId
,
1484 const layers::GeckoContentController::APZStateChange
& aChange
,
1486 mAPZEventState
->ProcessAPZStateChange(aViewId
, aChange
, aArg
);
1487 nsCOMPtr
<nsIObserverService
> observerService
=
1488 mozilla::services::GetObserverService();
1490 layers::GeckoContentController::APZStateChange::eTransformEnd
) {
1491 // This is used by tests to determine when the APZ is done doing whatever
1492 // it's doing. XXX generify this as needed when writing additional tests.
1493 observerService
->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
1494 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1496 } else if (aChange
==
1497 layers::GeckoContentController::APZStateChange::eTransformBegin
) {
1498 observerService
->NotifyObservers(nullptr, "PanZoom:StateChange",
1504 void BrowserChild::StartScrollbarDrag(
1505 const layers::AsyncDragMetrics
& aDragMetrics
) {
1506 ScrollableLayerGuid
guid(mLayersId
, aDragMetrics
.mPresShellId
,
1507 aDragMetrics
.mViewId
);
1509 if (mApzcTreeManager
) {
1510 mApzcTreeManager
->StartScrollbarDrag(guid
, aDragMetrics
);
1514 void BrowserChild::ZoomToRect(const uint32_t& aPresShellId
,
1515 const ScrollableLayerGuid::ViewID
& aViewId
,
1516 const CSSRect
& aRect
, const uint32_t& aFlags
) {
1517 ScrollableLayerGuid
guid(mLayersId
, aPresShellId
, aViewId
);
1519 if (mApzcTreeManager
) {
1520 mApzcTreeManager
->ZoomToRect(guid
, ZoomTarget
{aRect
}, aFlags
);
1524 mozilla::ipc::IPCResult
BrowserChild::RecvActivate(uint64_t aActionId
) {
1525 MOZ_ASSERT(mWebBrowser
);
1526 mWebBrowser
->FocusActivate(aActionId
);
1530 mozilla::ipc::IPCResult
BrowserChild::RecvDeactivate(uint64_t aActionId
) {
1531 MOZ_ASSERT(mWebBrowser
);
1532 mWebBrowser
->FocusDeactivate(aActionId
);
1536 mozilla::ipc::IPCResult
BrowserChild::RecvSetKeyboardIndicators(
1537 const UIStateChangeType
& aShowFocusRings
) {
1538 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
1539 NS_ENSURE_TRUE(window
, IPC_OK());
1540 window
->SetKeyboardIndicators(aShowFocusRings
);
1544 mozilla::ipc::IPCResult
BrowserChild::RecvStopIMEStateManagement() {
1545 IMEStateManager::StopIMEStateManagement();
1549 void BrowserChild::ProcessPendingCoalescedTouchData() {
1550 MOZ_ASSERT(StaticPrefs::dom_events_coalesce_touchmove());
1552 if (mCoalescedTouchData
.IsEmpty()) {
1556 if (mCoalescedTouchMoveEventFlusher
) {
1557 mCoalescedTouchMoveEventFlusher
->RemoveObserver();
1560 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1561 mCoalescedTouchData
.TakeCoalescedEvent();
1562 Unused
<< RecvRealTouchEvent(*touchMoveEvent
,
1563 mCoalescedTouchData
.GetScrollableLayerGuid(),
1564 mCoalescedTouchData
.GetInputBlockId(),
1565 mCoalescedTouchData
.GetApzResponse());
1568 void BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() {
1569 if (!mCoalesceMouseMoveEvents
|| !mCoalescedMouseEventFlusher
) {
1570 // We don't enable mouse coalescing or we are destroying BrowserChild.
1574 // We may reentry the event loop and push more data to
1575 // mToBeDispatchedMouseData while dispatching an event.
1577 // We may have some pending coalesced data while dispatch an event and reentry
1578 // the event loop. In that case we don't have chance to consume the remainding
1579 // pending data until we get new mouse events. Get some helps from
1580 // mCoalescedMouseEventFlusher to trigger it.
1581 mCoalescedMouseEventFlusher
->StartObserver();
1583 while (mToBeDispatchedMouseData
.GetSize() > 0) {
1584 UniquePtr
<CoalescedMouseData
> data(
1585 static_cast<CoalescedMouseData
*>(mToBeDispatchedMouseData
.PopFront()));
1587 UniquePtr
<WidgetMouseEvent
> event
= data
->TakeCoalescedEvent();
1589 // Dispatch the pending events. Using HandleRealMouseButtonEvent
1590 // to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
1591 // RecvRealMouseButtonEvent because we may also put some mouse events
1592 // other than mousemove.
1593 HandleRealMouseButtonEvent(*event
, data
->GetScrollableLayerGuid(),
1594 data
->GetInputBlockId());
1597 // mCoalescedMouseEventFlusher may be destroyed when reentrying the event
1599 if (mCoalescedMouseEventFlusher
) {
1600 mCoalescedMouseEventFlusher
->RemoveObserver();
1604 LayoutDeviceToLayoutDeviceMatrix4x4
1605 BrowserChild::GetChildToParentConversionMatrix() const {
1606 if (mChildToParentConversionMatrix
) {
1607 return *mChildToParentConversionMatrix
;
1609 LayoutDevicePoint
offset(GetChromeOffset());
1610 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset
);
1613 Maybe
<ScreenRect
> BrowserChild::GetTopLevelViewportVisibleRectInBrowserCoords()
1615 if (!mChildToParentConversionMatrix
) {
1618 return Some(mTopLevelViewportVisibleRectInBrowserCoords
);
1621 void BrowserChild::FlushAllCoalescedMouseData() {
1622 MOZ_ASSERT(mCoalesceMouseMoveEvents
);
1624 // Move all entries from mCoalescedMouseData to mToBeDispatchedMouseData.
1625 for (const auto& data
: mCoalescedMouseData
.Values()) {
1626 if (!data
|| data
->IsEmpty()) {
1629 UniquePtr
<CoalescedMouseData
> dispatchData
=
1630 MakeUnique
<CoalescedMouseData
>();
1632 dispatchData
->RetrieveDataFrom(*data
);
1633 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1635 mCoalescedMouseData
.Clear();
1638 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEvent(
1639 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1640 const uint64_t& aInputBlockId
) {
1641 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
) {
1642 CoalescedMouseData
* data
=
1643 mCoalescedMouseData
.GetOrInsertNew(aEvent
.pointerId
);
1645 if (data
->CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1646 data
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1647 mCoalescedMouseEventFlusher
->StartObserver();
1650 // Can't coalesce current mousemove event. Put the coalesced mousemove data
1651 // with the same pointer id to mToBeDispatchedMouseData, coalesce the
1652 // current one, and process all pending data in mToBeDispatchedMouseData.
1653 UniquePtr
<CoalescedMouseData
> dispatchData
=
1654 MakeUnique
<CoalescedMouseData
>();
1656 dispatchData
->RetrieveDataFrom(*data
);
1657 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1659 // Put new data to replace the old one in the hash table.
1660 CoalescedMouseData
* newData
=
1662 .InsertOrUpdate(aEvent
.pointerId
, MakeUnique
<CoalescedMouseData
>())
1664 newData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1666 // Dispatch all pending mouse events.
1667 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1668 mCoalescedMouseEventFlusher
->StartObserver();
1669 } else if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1670 return IPC_FAIL_NO_REASON(this);
1675 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseMoveEventForTests(
1676 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1677 const uint64_t& aInputBlockId
) {
1678 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1681 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseMoveEvent(
1682 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1683 const uint64_t& aInputBlockId
) {
1684 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1687 mozilla::ipc::IPCResult
1688 BrowserChild::RecvNormalPriorityRealMouseMoveEventForTests(
1689 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1690 const uint64_t& aInputBlockId
) {
1691 return RecvRealMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1694 mozilla::ipc::IPCResult
BrowserChild::RecvSynthMouseMoveEvent(
1695 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1696 const uint64_t& aInputBlockId
) {
1697 if (!RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
)) {
1698 return IPC_FAIL_NO_REASON(this);
1703 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySynthMouseMoveEvent(
1704 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1705 const uint64_t& aInputBlockId
) {
1706 return RecvSynthMouseMoveEvent(aEvent
, aGuid
, aInputBlockId
);
1709 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseButtonEvent(
1710 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1711 const uint64_t& aInputBlockId
) {
1712 if (mCoalesceMouseMoveEvents
&& mCoalescedMouseEventFlusher
&&
1713 aEvent
.mMessage
!= eMouseMove
) {
1714 // When receiving a mouse event other than mousemove, we have to dispatch
1715 // all coalesced events before it. However, we can't dispatch all pending
1716 // coalesced events directly because we may reentry the event loop while
1717 // dispatching. To make sure we won't dispatch disorder events, we move all
1718 // coalesced mousemove events and current event to a deque to dispatch them.
1719 // When reentrying the event loop and dispatching more events, we put new
1720 // events in the end of the nsQueue and dispatch events from the beginning.
1721 FlushAllCoalescedMouseData();
1723 UniquePtr
<CoalescedMouseData
> dispatchData
=
1724 MakeUnique
<CoalescedMouseData
>();
1726 dispatchData
->Coalesce(aEvent
, aGuid
, aInputBlockId
);
1727 mToBeDispatchedMouseData
.Push(dispatchData
.release());
1729 ProcessPendingCoalescedMouseDataAndDispatchEvents();
1732 HandleRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1736 void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent
& aEvent
,
1737 const ScrollableLayerGuid
& aGuid
,
1738 const uint64_t& aInputBlockId
) {
1739 WidgetMouseEvent
localEvent(aEvent
);
1740 localEvent
.mWidget
= mPuppetWidget
;
1742 // We need one InputAPZContext here to propagate |aGuid| to places in
1743 // SendSetTargetAPZCNotification() which apply the visual-to-layout transform,
1744 // and another below to propagate the |postLayerization| flag (whose value
1745 // we don't know until SendSetTargetAPZCNotification() returns) into
1746 // the event dispatch code.
1747 InputAPZContext
context1(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1749 // Mouse events like eMouseEnterIntoWidget, that are created in the parent
1750 // process EventStateManager code, have an input block id which they get from
1751 // the InputAPZContext in the parent process stack. However, they did not
1752 // actually go through the APZ code and so their mHandledByAPZ flag is false.
1753 // Since thos events didn't go through APZ, we don't need to send
1754 // notifications for them.
1755 RefPtr
<DisplayportSetListener
> postLayerization
;
1756 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
) {
1757 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1758 postLayerization
= APZCCallbackHelper::SendSetTargetAPZCNotification(
1759 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
, aInputBlockId
);
1762 InputAPZContext
context2(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
,
1763 postLayerization
!= nullptr);
1765 DispatchWidgetEventViaAPZ(localEvent
);
1767 if (aInputBlockId
&& localEvent
.mFlags
.mHandledByAPZ
) {
1768 mAPZEventState
->ProcessMouseEvent(localEvent
, aInputBlockId
);
1771 // Do this after the DispatchWidgetEventViaAPZ call above, so that if the
1772 // mouse event triggered a post-refresh AsyncDragMetrics message to be sent
1773 // to APZ (from scrollbar dragging in nsSliderFrame), then that will reach
1774 // APZ before the SetTargetAPZC message. This ensures the drag input block
1775 // gets the drag metrics before handling the input events.
1776 if (postLayerization
) {
1777 postLayerization
->Register();
1781 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealMouseButtonEvent(
1782 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1783 const uint64_t& aInputBlockId
) {
1784 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1787 mozilla::ipc::IPCResult
BrowserChild::RecvRealMouseEnterExitWidgetEvent(
1788 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1789 const uint64_t& aInputBlockId
) {
1790 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1793 mozilla::ipc::IPCResult
1794 BrowserChild::RecvNormalPriorityRealMouseEnterExitWidgetEvent(
1795 const WidgetMouseEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1796 const uint64_t& aInputBlockId
) {
1797 return RecvRealMouseButtonEvent(aEvent
, aGuid
, aInputBlockId
);
1800 nsEventStatus
BrowserChild::DispatchWidgetEventViaAPZ(WidgetGUIEvent
& aEvent
) {
1801 aEvent
.ResetWaitingReplyFromRemoteProcessState();
1802 return APZCCallbackHelper::DispatchWidgetEvent(aEvent
);
1805 void BrowserChild::DispatchCoalescedWheelEvent() {
1806 UniquePtr
<WidgetWheelEvent
> wheelEvent
=
1807 mCoalescedWheelData
.TakeCoalescedEvent();
1808 MOZ_ASSERT(wheelEvent
);
1809 DispatchWheelEvent(*wheelEvent
, mCoalescedWheelData
.GetScrollableLayerGuid(),
1810 mCoalescedWheelData
.GetInputBlockId());
1813 void BrowserChild::DispatchWheelEvent(const WidgetWheelEvent
& aEvent
,
1814 const ScrollableLayerGuid
& aGuid
,
1815 const uint64_t& aInputBlockId
) {
1816 WidgetWheelEvent
localEvent(aEvent
);
1817 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
) {
1818 nsCOMPtr
<Document
> document(GetTopLevelDocument());
1819 RefPtr
<DisplayportSetListener
> postLayerization
=
1820 APZCCallbackHelper::SendSetTargetAPZCNotification(
1821 mPuppetWidget
, document
, aEvent
, aGuid
.mLayersId
, aInputBlockId
);
1822 if (postLayerization
) {
1823 postLayerization
->Register();
1827 localEvent
.mWidget
= mPuppetWidget
;
1829 // Stash the guid in InputAPZContext so that when the visual-to-layout
1830 // transform is applied to the event's coordinates, we use the right transform
1831 // based on the scroll frame being targeted.
1832 // The other values don't really matter.
1833 InputAPZContext
context(aGuid
, aInputBlockId
, nsEventStatus_eSentinel
);
1835 DispatchWidgetEventViaAPZ(localEvent
);
1837 if (localEvent
.mCanTriggerSwipe
) {
1838 SendRespondStartSwipeEvent(aInputBlockId
, localEvent
.TriggersSwipe());
1841 if (aInputBlockId
&& aEvent
.mFlags
.mHandledByAPZ
) {
1842 mAPZEventState
->ProcessWheelEvent(localEvent
, aInputBlockId
);
1846 mozilla::ipc::IPCResult
BrowserChild::RecvMouseWheelEvent(
1847 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1848 const uint64_t& aInputBlockId
) {
1849 bool isNextWheelEvent
= false;
1850 // We only coalesce the current event when
1851 // 1. It's eWheel (we don't coalesce eOperationStart and eWheelOperationEnd)
1852 // 2. It has same attributes as the coalesced wheel event which is not yet
1854 if (aEvent
.mMessage
== eWheel
) {
1855 GetIPCChannel()->PeekMessages(
1856 [&isNextWheelEvent
](const IPC::Message
& aMsg
) -> bool {
1857 if (aMsg
.type() == mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID
) {
1858 isNextWheelEvent
= true;
1860 return false; // Stop peeking.
1863 if (!mCoalescedWheelData
.IsEmpty() &&
1864 !mCoalescedWheelData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
)) {
1865 DispatchCoalescedWheelEvent();
1866 MOZ_ASSERT(mCoalescedWheelData
.IsEmpty());
1868 mCoalescedWheelData
.Coalesce(aEvent
, aGuid
, aInputBlockId
);
1870 MOZ_ASSERT(!mCoalescedWheelData
.IsEmpty());
1871 // If the next event isn't a wheel event, make sure we dispatch.
1872 if (!isNextWheelEvent
) {
1873 DispatchCoalescedWheelEvent();
1876 DispatchWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1882 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityMouseWheelEvent(
1883 const WidgetWheelEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1884 const uint64_t& aInputBlockId
) {
1885 return RecvMouseWheelEvent(aEvent
, aGuid
, aInputBlockId
);
1888 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchEvent(
1889 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1890 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1891 MOZ_LOG(sApzChildLog
, LogLevel::Debug
,
1892 ("Receiving touch event of type %d\n", aEvent
.mMessage
));
1894 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1895 if (aEvent
.mMessage
== eTouchEnd
|| aEvent
.mMessage
== eTouchStart
) {
1896 ProcessPendingCoalescedTouchData();
1899 if (aEvent
.mMessage
!= eTouchMove
) {
1900 sConsecutiveTouchMoveCount
= 0;
1904 WidgetTouchEvent
localEvent(aEvent
);
1905 localEvent
.mWidget
= mPuppetWidget
;
1907 // Stash the guid in InputAPZContext so that when the visual-to-layout
1908 // transform is applied to the event's coordinates, we use the right transform
1909 // based on the scroll frame being targeted.
1910 // The other values don't really matter.
1911 InputAPZContext
context(aGuid
, aInputBlockId
, aApzResponse
);
1913 nsTArray
<TouchBehaviorFlags
> allowedTouchBehaviors
;
1914 if (localEvent
.mMessage
== eTouchStart
&& AsyncPanZoomEnabled()) {
1915 nsCOMPtr
<Document
> document
= GetTopLevelDocument();
1916 allowedTouchBehaviors
= TouchActionHelper::GetAllowedTouchBehavior(
1917 mPuppetWidget
, document
, localEvent
);
1918 if (!allowedTouchBehaviors
.IsEmpty() && mApzcTreeManager
) {
1919 mApzcTreeManager
->SetAllowedTouchBehavior(aInputBlockId
,
1920 allowedTouchBehaviors
);
1922 RefPtr
<DisplayportSetListener
> postLayerization
=
1923 APZCCallbackHelper::SendSetTargetAPZCNotification(
1924 mPuppetWidget
, document
, localEvent
, aGuid
.mLayersId
,
1926 if (postLayerization
) {
1927 postLayerization
->Register();
1931 // Dispatch event to content (potentially a long-running operation)
1932 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
1934 if (!AsyncPanZoomEnabled()) {
1935 // We shouldn't have any e10s platforms that have touch events enabled
1941 mAPZEventState
->ProcessTouchEvent(localEvent
, aGuid
, aInputBlockId
,
1942 aApzResponse
, status
,
1943 std::move(allowedTouchBehaviors
));
1947 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchEvent(
1948 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1949 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1950 return RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
1953 mozilla::ipc::IPCResult
BrowserChild::RecvRealTouchMoveEvent(
1954 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1955 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
1956 if (StaticPrefs::dom_events_coalesce_touchmove()) {
1957 ++sConsecutiveTouchMoveCount
;
1958 if (mCoalescedTouchMoveEventFlusher
) {
1959 MOZ_ASSERT(aEvent
.mMessage
== eTouchMove
);
1960 if (mCoalescedTouchData
.IsEmpty() ||
1961 mCoalescedTouchData
.CanCoalesce(aEvent
, aGuid
, aInputBlockId
,
1963 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1966 UniquePtr
<WidgetTouchEvent
> touchMoveEvent
=
1967 mCoalescedTouchData
.TakeCoalescedEvent();
1969 mCoalescedTouchData
.Coalesce(aEvent
, aGuid
, aInputBlockId
,
1972 if (!RecvRealTouchEvent(*touchMoveEvent
,
1973 mCoalescedTouchData
.GetScrollableLayerGuid(),
1974 mCoalescedTouchData
.GetInputBlockId(),
1975 mCoalescedTouchData
.GetApzResponse())) {
1976 return IPC_FAIL_NO_REASON(this);
1980 if (sConsecutiveTouchMoveCount
> 1) {
1981 mCoalescedTouchMoveEventFlusher
->StartObserver();
1983 // Flush the pending coalesced touch in order to avoid the first
1984 // touchmove be overridden by the second one.
1985 ProcessPendingCoalescedTouchData();
1991 if (!RecvRealTouchEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
)) {
1992 return IPC_FAIL_NO_REASON(this);
1997 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealTouchMoveEvent(
1998 const WidgetTouchEvent
& aEvent
, const ScrollableLayerGuid
& aGuid
,
1999 const uint64_t& aInputBlockId
, const nsEventStatus
& aApzResponse
) {
2000 return RecvRealTouchMoveEvent(aEvent
, aGuid
, aInputBlockId
, aApzResponse
);
2003 mozilla::ipc::IPCResult
BrowserChild::RecvRealDragEvent(
2004 const WidgetDragEvent
& aEvent
, const uint32_t& aDragAction
,
2005 const uint32_t& aDropEffect
, nsIPrincipal
* aPrincipal
,
2006 nsIContentSecurityPolicy
* aCsp
) {
2007 WidgetDragEvent
localEvent(aEvent
);
2008 localEvent
.mWidget
= mPuppetWidget
;
2010 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
2012 dragSession
->SetDragAction(aDragAction
);
2013 dragSession
->SetTriggeringPrincipal(aPrincipal
);
2014 dragSession
->SetCsp(aCsp
);
2015 RefPtr
<DataTransfer
> initialDataTransfer
= dragSession
->GetDataTransfer();
2016 if (initialDataTransfer
) {
2017 initialDataTransfer
->SetDropEffectInt(aDropEffect
);
2021 if (aEvent
.mMessage
== eDrop
) {
2022 bool canDrop
= true;
2023 if (!dragSession
|| NS_FAILED(dragSession
->GetCanDrop(&canDrop
)) ||
2025 localEvent
.mMessage
= eDragExit
;
2027 } else if (aEvent
.mMessage
== eDragOver
) {
2028 nsCOMPtr
<nsIDragService
> dragService
=
2029 do_GetService("@mozilla.org/widget/dragservice;1");
2031 // This will dispatch 'drag' event at the source if the
2032 // drag transaction started in this process.
2033 dragService
->FireDragEventAtSource(eDrag
, aEvent
.mModifiers
);
2037 DispatchWidgetEventViaAPZ(localEvent
);
2041 void BrowserChild::RequestEditCommands(NativeKeyBindingsType aType
,
2042 const WidgetKeyboardEvent
& aEvent
,
2043 nsTArray
<CommandInt
>& aCommands
) {
2044 MOZ_ASSERT(aCommands
.IsEmpty());
2046 if (NS_WARN_IF(aEvent
.IsEditCommandsInitialized(aType
))) {
2047 aCommands
= aEvent
.EditCommandsConstRef(aType
).Clone();
2052 case NativeKeyBindingsType::SingleLineEditor
:
2053 case NativeKeyBindingsType::MultiLineEditor
:
2054 case NativeKeyBindingsType::RichTextEditor
:
2057 MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type");
2060 // Don't send aEvent to the parent process directly because it'll be marked
2061 // as posted to remote process.
2062 WidgetKeyboardEvent
localEvent(aEvent
);
2063 SendRequestNativeKeyBindings(static_cast<uint32_t>(aType
), localEvent
,
2067 mozilla::ipc::IPCResult
BrowserChild::RecvNativeSynthesisResponse(
2068 const uint64_t& aObserverId
, const nsCString
& aResponse
) {
2069 mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId
,
2074 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateSHistory() {
2075 if (mSessionStoreChild
) {
2076 mSessionStoreChild
->UpdateSHistoryChanges();
2081 // In case handling repeated keys takes much time, we skip firing new ones.
2082 bool BrowserChild::SkipRepeatedKeyEvent(const WidgetKeyboardEvent
& aEvent
) {
2083 if (mRepeatedKeyEventTime
.IsNull() || !aEvent
.CanSkipInRemoteProcess() ||
2084 (aEvent
.mMessage
!= eKeyDown
&& aEvent
.mMessage
!= eKeyPress
)) {
2085 mRepeatedKeyEventTime
= TimeStamp();
2086 mSkipKeyPress
= false;
2090 if ((aEvent
.mMessage
== eKeyDown
&&
2091 (mRepeatedKeyEventTime
> aEvent
.mTimeStamp
)) ||
2092 (mSkipKeyPress
&& (aEvent
.mMessage
== eKeyPress
))) {
2093 // If we skip a keydown event, also the following keypress events should be
2095 mSkipKeyPress
|= aEvent
.mMessage
== eKeyDown
;
2099 if (aEvent
.mMessage
== eKeyDown
) {
2100 // If keydown wasn't skipped, nor should the possible following keypress.
2101 mRepeatedKeyEventTime
= TimeStamp();
2102 mSkipKeyPress
= false;
2107 void BrowserChild::UpdateRepeatedKeyEventEndTime(
2108 const WidgetKeyboardEvent
& aEvent
) {
2109 if (aEvent
.mIsRepeat
&&
2110 (aEvent
.mMessage
== eKeyDown
|| aEvent
.mMessage
== eKeyPress
)) {
2111 mRepeatedKeyEventTime
= TimeStamp::Now();
2115 mozilla::ipc::IPCResult
BrowserChild::RecvRealKeyEvent(
2116 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
2117 MOZ_ASSERT_IF(aEvent
.mMessage
== eKeyPress
,
2118 aEvent
.AreAllEditCommandsInitialized());
2120 // If content code called preventDefault() on a keydown event, then we don't
2121 // want to process any following keypress events.
2122 const bool isPrecedingKeyDownEventConsumed
=
2123 aEvent
.mMessage
== eKeyPress
&& mIgnoreKeyPressEvent
;
2125 WidgetKeyboardEvent
localEvent(aEvent
);
2126 localEvent
.mWidget
= mPuppetWidget
;
2127 localEvent
.mUniqueId
= aEvent
.mUniqueId
;
2129 if (!SkipRepeatedKeyEvent(aEvent
) && !isPrecedingKeyDownEventConsumed
) {
2130 nsEventStatus status
= DispatchWidgetEventViaAPZ(localEvent
);
2132 // Update the end time of the possible repeated event so that we can skip
2133 // some incoming events in case event handling took long time.
2134 UpdateRepeatedKeyEventEndTime(localEvent
);
2136 if (aEvent
.mMessage
== eKeyDown
) {
2137 mIgnoreKeyPressEvent
= status
== nsEventStatus_eConsumeNoDefault
;
2140 if (localEvent
.mFlags
.mIsSuppressedOrDelayed
) {
2141 localEvent
.PreventDefault();
2144 // If the event's default isn't prevented but the status is no default,
2145 // That means that the event was consumed by EventStateManager or something
2146 // which is not a usual event handler. In such case, prevent its default
2147 // as a default handler. For example, when an eKeyPress event matches
2148 // with a content accesskey, and it's executed, preventDefault() of the
2149 // event won't be called but the status is set to "no default". Then,
2150 // the event shouldn't be handled by nsMenuBarListener in the main process.
2151 if (!localEvent
.DefaultPrevented() &&
2152 status
== nsEventStatus_eConsumeNoDefault
) {
2153 localEvent
.PreventDefault();
2156 MOZ_DIAGNOSTIC_ASSERT(!localEvent
.PropagationStopped());
2158 // The keyboard event which we ignore should not be handled in the main
2159 // process for shortcut key handling. For notifying if we skipped it, we can
2160 // use "stop propagation" flag here because it must be cleared by
2161 // `EventTargetChainItem` if we've dispatched it.
2163 localEvent
.StopPropagation();
2166 // If we don't need to send a rely for the given keyboard event, we do nothing
2168 if (!aEvent
.WantReplyFromContentProcess()) {
2172 // This is an ugly hack, mNoRemoteProcessDispatch is set to true when the
2173 // event's PreventDefault() or StopScrollProcessForwarding() is called.
2174 // And then, it'll be checked by ParamTraits<mozilla::WidgetEvent>::Write()
2175 // whether the event is being sent to remote process unexpectedly.
2176 // However, unfortunately, it cannot check the destination. Therefore,
2177 // we need to clear the flag explicitly here because ParamTraits should
2178 // keep checking the flag for avoiding regression.
2179 localEvent
.mFlags
.mNoRemoteProcessDispatch
= false;
2180 SendReplyKeyEvent(localEvent
, aUUID
);
2185 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityRealKeyEvent(
2186 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
2187 return RecvRealKeyEvent(aEvent
, aUUID
);
2190 mozilla::ipc::IPCResult
BrowserChild::RecvCompositionEvent(
2191 const WidgetCompositionEvent
& aEvent
) {
2192 WidgetCompositionEvent
localEvent(aEvent
);
2193 localEvent
.mWidget
= mPuppetWidget
;
2194 DispatchWidgetEventViaAPZ(localEvent
);
2195 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
);
2199 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityCompositionEvent(
2200 const WidgetCompositionEvent
& aEvent
) {
2201 return RecvCompositionEvent(aEvent
);
2204 mozilla::ipc::IPCResult
BrowserChild::RecvSelectionEvent(
2205 const WidgetSelectionEvent
& aEvent
) {
2206 WidgetSelectionEvent
localEvent(aEvent
);
2207 localEvent
.mWidget
= mPuppetWidget
;
2208 DispatchWidgetEventViaAPZ(localEvent
);
2209 Unused
<< SendOnEventNeedingAckHandled(aEvent
.mMessage
);
2213 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPrioritySelectionEvent(
2214 const WidgetSelectionEvent
& aEvent
) {
2215 return RecvSelectionEvent(aEvent
);
2218 mozilla::ipc::IPCResult
BrowserChild::RecvInsertText(
2219 const nsAString
& aStringToInsert
) {
2220 // Use normal event path to reach focused document.
2221 WidgetContentCommandEvent
localEvent(true, eContentCommandInsertText
,
2223 localEvent
.mString
= Some(nsString(aStringToInsert
));
2224 DispatchWidgetEventViaAPZ(localEvent
);
2228 mozilla::ipc::IPCResult
BrowserChild::RecvNormalPriorityInsertText(
2229 const nsAString
& aStringToInsert
) {
2230 return RecvInsertText(aStringToInsert
);
2233 mozilla::ipc::IPCResult
BrowserChild::RecvPasteTransferable(
2234 const IPCDataTransfer
& aDataTransfer
, const bool& aIsPrivateData
,
2235 nsIPrincipal
* aRequestingPrincipal
,
2236 const nsContentPolicyType
& aContentPolicyType
) {
2238 nsCOMPtr
<nsITransferable
> trans
=
2239 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
2240 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2241 trans
->Init(nullptr);
2243 rv
= nsContentUtils::IPCTransferableToTransferable(
2244 aDataTransfer
, aIsPrivateData
, aRequestingPrincipal
, aContentPolicyType
,
2245 true /* aAddDataFlavor */, trans
);
2246 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2248 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2249 if (NS_WARN_IF(!ourDocShell
)) {
2253 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
2254 rv
= params
->SetISupports("transferable", trans
);
2255 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2257 ourDocShell
->DoCommandWithParams("cmd_pasteTransferable", params
);
2261 #ifdef ACCESSIBILITY
2262 a11y::PDocAccessibleChild
* BrowserChild::AllocPDocAccessibleChild(
2263 PDocAccessibleChild
*, const uint64_t&, const MaybeDiscardedBrowsingContext
&,
2264 const uint32_t&, const IAccessibleHolder
&) {
2265 MOZ_ASSERT(false, "should never call this!");
2269 bool BrowserChild::DeallocPDocAccessibleChild(
2270 a11y::PDocAccessibleChild
* aChild
) {
2271 delete static_cast<mozilla::a11y::DocAccessibleChild
*>(aChild
);
2276 PColorPickerChild
* BrowserChild::AllocPColorPickerChild(const nsAString
&,
2278 MOZ_CRASH("unused");
2282 bool BrowserChild::DeallocPColorPickerChild(PColorPickerChild
* aColorPicker
) {
2283 nsColorPickerProxy
* picker
= static_cast<nsColorPickerProxy
*>(aColorPicker
);
2288 PFilePickerChild
* BrowserChild::AllocPFilePickerChild(const nsAString
&,
2290 MOZ_CRASH("unused");
2294 bool BrowserChild::DeallocPFilePickerChild(PFilePickerChild
* actor
) {
2295 nsFilePickerProxy
* filePicker
= static_cast<nsFilePickerProxy
*>(actor
);
2296 NS_RELEASE(filePicker
);
2300 RefPtr
<VsyncMainChild
> BrowserChild::GetVsyncChild() {
2301 // Initializing mVsyncChild here turns on per-BrowserChild Vsync for a
2302 // given platform. Note: this only makes sense if nsWindow returns a
2303 // window-specific VsyncSource.
2304 #if defined(MOZ_WAYLAND)
2305 if (IsWaylandEnabled() && !mVsyncChild
) {
2306 mVsyncChild
= MakeRefPtr
<VsyncMainChild
>();
2307 if (!SendPVsyncConstructor(mVsyncChild
)) {
2308 mVsyncChild
= nullptr;
2315 mozilla::ipc::IPCResult
BrowserChild::RecvLoadRemoteScript(
2316 const nsAString
& aURL
, const bool& aRunInGlobalScope
) {
2317 if (!InitBrowserChildMessageManager())
2318 // This can happen if we're half-destroyed. It's not a fatal
2322 JS::Rooted
<JSObject
*> mm(RootingCx(),
2323 mBrowserChildMessageManager
->GetOrCreateWrapper());
2325 // This can happen if we're half-destroyed. It's not a fatal error.
2329 LoadScriptInternal(mm
, aURL
, !aRunInGlobalScope
);
2333 mozilla::ipc::IPCResult
BrowserChild::RecvAsyncMessage(
2334 const nsAString
& aMessage
, const ClonedMessageData
& aData
) {
2335 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserChild::RecvAsyncMessage",
2337 MMPrinter::Print("BrowserChild::RecvAsyncMessage", aMessage
, aData
);
2339 if (!mBrowserChildMessageManager
) {
2343 RefPtr
<nsFrameMessageManager
> mm
=
2344 mBrowserChildMessageManager
->GetMessageManager();
2346 // We should have a message manager if the global is alive, but it
2347 // seems sometimes we don't. Assert in aurora/nightly, but don't
2348 // crash in release builds.
2349 MOZ_DIAGNOSTIC_ASSERT(mm
);
2354 JS::Rooted
<JSObject
*> kungFuDeathGrip(
2355 dom::RootingCx(), mBrowserChildMessageManager
->GetWrapper());
2356 StructuredCloneData data
;
2357 UnpackClonedMessageData(aData
, data
);
2358 mm
->ReceiveMessage(static_cast<EventTarget
*>(mBrowserChildMessageManager
),
2359 nullptr, aMessage
, false, &data
, nullptr, IgnoreErrors());
2363 mozilla::ipc::IPCResult
BrowserChild::RecvSwappedWithOtherRemoteLoader(
2364 const IPCTabContext
& aContext
) {
2365 nsCOMPtr
<nsIDocShell
> ourDocShell
= do_GetInterface(WebNavigation());
2366 if (NS_WARN_IF(!ourDocShell
)) {
2370 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= ourDocShell
->GetWindow();
2371 if (NS_WARN_IF(!ourWindow
)) {
2375 RefPtr
<nsDocShell
> docShell
= static_cast<nsDocShell
*>(ourDocShell
.get());
2377 nsCOMPtr
<EventTarget
> ourEventTarget
= nsGlobalWindowOuter::Cast(ourWindow
);
2379 docShell
->SetInFrameSwap(true);
2381 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2382 ourDocShell
, ourEventTarget
, false, true);
2383 nsContentUtils::FirePageHideEventForFrameLoaderSwap(ourDocShell
,
2384 ourEventTarget
, true);
2386 // Owner content type may have changed, so store the possibly updated context
2387 // and notify others.
2388 MaybeInvalidTabContext
maybeContext(aContext
);
2389 if (!maybeContext
.IsValid()) {
2390 NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
2391 "the parent process. (%s)",
2392 maybeContext
.GetInvalidReason())
2394 MOZ_CRASH("Invalid TabContext received from the parent process.");
2397 if (!UpdateTabContextAfterSwap(maybeContext
.GetTabContext())) {
2398 MOZ_CRASH("Update to TabContext after swap was denied.");
2401 // Ignore previous value of mTriedBrowserInit since owner content has changed.
2402 mTriedBrowserInit
= true;
2404 nsContentUtils::FirePageShowEventForFrameLoaderSwap(
2405 ourDocShell
, ourEventTarget
, true, true);
2407 docShell
->SetInFrameSwap(false);
2409 // This is needed to get visibility state right in cases when we swapped a
2410 // visible tab (foreground in visible window) with a non-visible tab.
2411 if (RefPtr
<Document
> doc
= docShell
->GetDocument()) {
2412 doc
->UpdateVisibilityState();
2418 mozilla::ipc::IPCResult
BrowserChild::RecvHandleAccessKey(
2419 const WidgetKeyboardEvent
& aEvent
, nsTArray
<uint32_t>&& aCharCodes
) {
2420 nsCOMPtr
<Document
> document(GetTopLevelDocument());
2421 RefPtr
<nsPresContext
> pc
= document
->GetPresContext();
2423 if (!pc
->EventStateManager()->HandleAccessKey(
2424 &(const_cast<WidgetKeyboardEvent
&>(aEvent
)), pc
, aCharCodes
)) {
2425 // If no accesskey was found, inform the parent so that accesskeys on
2426 // menus can be handled.
2427 WidgetKeyboardEvent
localEvent(aEvent
);
2428 localEvent
.mWidget
= mPuppetWidget
;
2429 SendAccessKeyNotHandled(localEvent
);
2436 mozilla::ipc::IPCResult
BrowserChild::RecvPrintPreview(
2437 const PrintData
& aPrintData
, const MaybeDiscardedBrowsingContext
& aSourceBC
,
2438 PrintPreviewResolver
&& aCallback
) {
2440 // If we didn't succeed in passing off ownership of aCallback, then something
2442 auto sendCallbackError
= MakeScopeExit([&] {
2445 aCallback(PrintPreviewResultInfo(0, 0, false, false, false, {}));
2449 if (NS_WARN_IF(aSourceBC
.IsDiscarded())) {
2453 RefPtr
<nsGlobalWindowOuter
> sourceWindow
;
2454 if (!aSourceBC
.IsNull()) {
2455 sourceWindow
= nsGlobalWindowOuter::Cast(aSourceBC
.get()->GetDOMWindow());
2456 if (NS_WARN_IF(!sourceWindow
)) {
2460 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= do_GetInterface(WebNavigation());
2461 if (NS_WARN_IF(!ourWindow
)) {
2464 sourceWindow
= nsGlobalWindowOuter::Cast(ourWindow
);
2467 RefPtr
<nsIPrintSettings
> printSettings
;
2468 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2469 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2470 if (NS_WARN_IF(!printSettingsSvc
)) {
2473 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2474 if (NS_WARN_IF(!printSettings
)) {
2477 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2479 nsCOMPtr
<nsIDocShell
> docShellToCloneInto
;
2480 if (!aSourceBC
.IsNull()) {
2481 docShellToCloneInto
= do_GetInterface(WebNavigation());
2482 if (NS_WARN_IF(!docShellToCloneInto
)) {
2487 sourceWindow
->Print(printSettings
,
2488 /* aRemotePrintJob = */ nullptr,
2489 /* aListener = */ nullptr, docShellToCloneInto
,
2490 nsGlobalWindowOuter::IsPreview::Yes
,
2491 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2492 std::move(aCallback
), IgnoreErrors());
2497 mozilla::ipc::IPCResult
BrowserChild::RecvExitPrintPreview() {
2499 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
=
2500 do_GetInterface(ToSupports(WebNavigation()));
2501 if (NS_WARN_IF(!webBrowserPrint
)) {
2504 webBrowserPrint
->ExitPrintPreview();
2509 mozilla::ipc::IPCResult
BrowserChild::RecvPrint(
2510 const MaybeDiscardedBrowsingContext
& aBc
, const PrintData
& aPrintData
) {
2512 if (NS_WARN_IF(aBc
.IsNullOrDiscarded())) {
2515 RefPtr
<nsGlobalWindowOuter
> outerWindow
=
2516 nsGlobalWindowOuter::Cast(aBc
.get()->GetDOMWindow());
2517 if (NS_WARN_IF(!outerWindow
)) {
2521 nsCOMPtr
<nsIPrintSettingsService
> printSettingsSvc
=
2522 do_GetService("@mozilla.org/gfx/printsettings-service;1");
2523 if (NS_WARN_IF(!printSettingsSvc
)) {
2527 nsCOMPtr
<nsIPrintSettings
> printSettings
;
2529 printSettingsSvc
->CreateNewPrintSettings(getter_AddRefs(printSettings
));
2530 if (NS_WARN_IF(NS_FAILED(rv
))) {
2534 printSettingsSvc
->DeserializeToPrintSettings(aPrintData
, printSettings
);
2536 IgnoredErrorResult rv
;
2538 static_cast<RemotePrintJobChild
*>(aPrintData
.remotePrintJobChild());
2539 outerWindow
->Print(printSettings
, printJob
,
2540 /* aListener = */ nullptr,
2541 /* aWindowToCloneInto = */ nullptr,
2542 nsGlobalWindowOuter::IsPreview::No
,
2543 nsGlobalWindowOuter::IsForWindowDotPrint::No
,
2544 /* aPrintPreviewCallback = */ nullptr, rv
);
2545 if (NS_WARN_IF(rv
.Failed())) {
2553 mozilla::ipc::IPCResult
BrowserChild::RecvUpdateNativeWindowHandle(
2554 const uintptr_t& aNewHandle
) {
2555 #if defined(XP_WIN) && defined(ACCESSIBILITY)
2556 mNativeWindowHandle
= aNewHandle
;
2559 return IPC_FAIL_NO_REASON(this);
2563 mozilla::ipc::IPCResult
BrowserChild::RecvDestroy() {
2564 MOZ_ASSERT(mDestroyed
== false);
2567 nsTArray
<PContentPermissionRequestChild
*> childArray
=
2568 nsContentPermissionUtils::GetContentPermissionRequestChildById(
2571 // Need to close undeleted ContentPermissionRequestChilds before tab is
2573 for (auto& permissionRequestChild
: childArray
) {
2574 auto child
= static_cast<RemotePermissionRequest
*>(permissionRequestChild
);
2578 if (mBrowserChildMessageManager
) {
2579 // Message handlers are called from the event loop, so it better be safe to
2581 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
2582 mBrowserChildMessageManager
->DispatchTrustedEvent(u
"unload"_ns
);
2585 nsCOMPtr
<nsIObserverService
> observerService
=
2586 mozilla::services::GetObserverService();
2588 observerService
->RemoveObserver(this, BEFORE_FIRST_PAINT
);
2590 // XXX what other code in ~BrowserChild() should we be running here?
2593 // Bounce through the event loop once to allow any delayed teardown runnables
2594 // that were just generated to have a chance to run.
2595 nsCOMPtr
<nsIRunnable
> deleteRunnable
= new DelayedDeleteRunnable(this);
2596 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable
));
2601 mozilla::ipc::IPCResult
BrowserChild::RecvRenderLayers(
2602 const bool& aEnabled
, const layers::LayersObserverEpoch
& aEpoch
) {
2603 if (mPendingDocShellBlockers
> 0) {
2604 mPendingRenderLayersReceivedMessage
= true;
2605 mPendingRenderLayers
= aEnabled
;
2606 mPendingLayersObserverEpoch
= aEpoch
;
2610 // Since requests to change the rendering state come in from both the hang
2611 // monitor channel and the PContent channel, we have an ordering problem. This
2612 // code ensures that we respect the order in which the requests were made and
2613 // ignore stale requests.
2614 if (mLayersObserverEpoch
>= aEpoch
) {
2617 mLayersObserverEpoch
= aEpoch
;
2619 auto clearPaintWhileInterruptingJS
= MakeScopeExit([&] {
2620 // We might force a paint, or we might already have painted and this is a
2621 // no-op. In either case, once we exit this scope, we need to alert the
2622 // ProcessHangMonitor that we've finished responding to what might have
2623 // been a request to force paint. This is so that the BackgroundHangMonitor
2624 // for force painting can be made to wait again.
2626 ProcessHangMonitor::ClearPaintWhileInterruptingJS(mLayersObserverEpoch
);
2631 ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS();
2634 if (mCompositorOptions
) {
2635 MOZ_ASSERT(mPuppetWidget
);
2636 RefPtr
<WebRenderLayerManager
> lm
=
2637 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2639 // We send the current layer observer epoch to the compositor so that
2640 // BrowserParent knows whether a layer update notification corresponds to
2641 // the latest RecvRenderLayers request that was made.
2642 lm
->SetLayersObserverEpoch(mLayersObserverEpoch
);
2646 mRenderLayers
= aEnabled
;
2648 if (aEnabled
&& IsVisible()) {
2649 // This request is a no-op.
2650 // In this case, we still want a MozLayerTreeReady notification to fire
2651 // in the parent (so that it knows that the child has updated its epoch).
2652 // PaintWhileInterruptingJSNoOp does that.
2654 Unused
<< SendPaintWhileInterruptingJSNoOp(mLayersObserverEpoch
);
2659 // FIXME(emilio): Probably / maybe this shouldn't be needed? See the comment
2660 // in MakeVisible(), having the two separate states is not great.
2667 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2672 // We don't use BrowserChildBase::GetPresShell() here because that would
2673 // create a content viewer if one doesn't exist yet. Creating a content
2674 // viewer can cause JS to run, which we want to avoid.
2675 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2676 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2681 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2682 root
->SchedulePaint();
2685 Telemetry::AutoTimer
<Telemetry::TABCHILD_PAINT_TIME
> timer
;
2686 // If we need to repaint, let's do that right away. No sense waiting until
2687 // we get back to the event loop again. We suppress the display port so
2688 // that we only paint what's visible. This ensures that the tab we're
2689 // switching to paints as quickly as possible.
2690 presShell
->SuppressDisplayport(true);
2691 if (nsContentUtils::IsSafeToRunScript()) {
2692 WebWidget()->PaintNowIfNeeded();
2694 RefPtr
<nsViewManager
> vm
= presShell
->GetViewManager();
2695 if (nsView
* view
= vm
->GetRootView()) {
2696 presShell
->PaintAndRequestComposite(view
, PaintFlags::None
);
2699 presShell
->SuppressDisplayport(false);
2703 mozilla::ipc::IPCResult
BrowserChild::RecvNavigateByKey(
2704 const bool& aForward
, const bool& aForDocumentNavigation
) {
2705 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2710 RefPtr
<Element
> result
;
2711 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2713 // Move to the first or last document.
2717 ? (aForDocumentNavigation
2718 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC
)
2719 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT
))
2720 : (aForDocumentNavigation
2721 ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC
)
2722 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LAST
));
2723 uint32_t flags
= nsIFocusManager::FLAG_BYKEY
;
2724 if (aForward
|| aForDocumentNavigation
) {
2725 flags
|= nsIFocusManager::FLAG_NOSCROLL
;
2727 fm
->MoveFocus(window
, nullptr, type
, flags
, getter_AddRefs(result
));
2730 // No valid root element was found, so move to the first focusable element.
2731 if (!result
&& aForward
&& !aForDocumentNavigation
) {
2732 fm
->MoveFocus(window
, nullptr, nsIFocusManager::MOVEFOCUS_FIRST
,
2733 nsIFocusManager::FLAG_BYKEY
, getter_AddRefs(result
));
2736 SendRequestFocus(false, CallerType::System
);
2740 bool BrowserChild::InitBrowserChildMessageManager() {
2741 mShouldSendWebProgressEventsToParent
= true;
2743 if (!mBrowserChildMessageManager
) {
2744 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
2745 NS_ENSURE_TRUE(window
, false);
2746 nsCOMPtr
<EventTarget
> chromeHandler
= window
->GetChromeEventHandler();
2747 NS_ENSURE_TRUE(chromeHandler
, false);
2749 RefPtr
<BrowserChildMessageManager
> scope
= mBrowserChildMessageManager
=
2750 new BrowserChildMessageManager(this);
2752 MOZ_ALWAYS_TRUE(nsMessageManagerScriptExecutor::Init());
2754 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(chromeHandler
);
2755 if (NS_WARN_IF(!root
)) {
2756 mBrowserChildMessageManager
= nullptr;
2759 root
->SetParentTarget(scope
);
2762 if (!mTriedBrowserInit
) {
2763 mTriedBrowserInit
= true;
2769 void BrowserChild::InitRenderingState(
2770 const TextureFactoryIdentifier
& aTextureFactoryIdentifier
,
2771 const layers::LayersId
& aLayersId
,
2772 const CompositorOptions
& aCompositorOptions
) {
2773 mPuppetWidget
->InitIMEState();
2775 MOZ_ASSERT(aLayersId
.IsValid());
2776 mTextureFactoryIdentifier
= aTextureFactoryIdentifier
;
2778 // Pushing layers transactions directly to a separate
2779 // compositor context.
2780 PCompositorBridgeChild
* compositorChild
= CompositorBridgeChild::Get();
2781 if (!compositorChild
) {
2782 mLayersConnected
= Some(false);
2783 NS_WARNING("failed to get CompositorBridgeChild instance");
2787 mCompositorOptions
= Some(aCompositorOptions
);
2789 if (aLayersId
.IsValid()) {
2790 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
2792 if (!sBrowserChildren
) {
2793 sBrowserChildren
= new BrowserChildMap
;
2795 MOZ_ASSERT(!sBrowserChildren
->Contains(uint64_t(aLayersId
)));
2796 sBrowserChildren
->InsertOrUpdate(uint64_t(aLayersId
), this);
2797 mLayersId
= aLayersId
;
2800 // Depending on timing, we might paint too early and fall back to basic
2801 // layers. CreateRemoteLayerManager will destroy us if we manage to get a
2802 // remote layer manager though, so that's fine.
2803 MOZ_ASSERT(!mPuppetWidget
->HasWindowRenderer() ||
2804 mPuppetWidget
->GetWindowRenderer()->GetBackendType() ==
2805 layers::LayersBackend::LAYERS_NONE
);
2806 bool success
= false;
2807 if (mLayersConnected
== Some(true)) {
2808 success
= CreateRemoteLayerManager(compositorChild
);
2812 MOZ_ASSERT(mLayersConnected
== Some(true));
2813 // Succeeded to create "remote" layer manager
2814 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
2815 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
2817 RefPtr
<WebRenderLayerManager
> lm
=
2818 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
2820 lm
->SetLayersObserverEpoch(mLayersObserverEpoch
);
2823 NS_WARNING("Fallback to FallbackRenderer");
2824 mLayersConnected
= Some(false);
2827 nsCOMPtr
<nsIObserverService
> observerService
=
2828 mozilla::services::GetObserverService();
2830 if (observerService
) {
2831 observerService
->AddObserver(this, BEFORE_FIRST_PAINT
, false);
2835 bool BrowserChild::CreateRemoteLayerManager(
2836 mozilla::layers::PCompositorBridgeChild
* aCompositorChild
) {
2837 MOZ_ASSERT(aCompositorChild
);
2839 return mPuppetWidget
->CreateRemoteLayerManager(
2840 [&](WebRenderLayerManager
* aLayerManager
) -> bool {
2842 return aLayerManager
->Initialize(aCompositorChild
,
2843 wr::AsPipelineId(mLayersId
),
2844 &mTextureFactoryIdentifier
, error
);
2848 void BrowserChild::InitAPZState() {
2849 if (!mCompositorOptions
->UseAPZ()) {
2852 auto cbc
= CompositorBridgeChild::Get();
2854 // Initialize the ApzcTreeManager. This takes multiple casts because of ugly
2855 // multiple inheritance.
2856 PAPZCTreeManagerChild
* baseProtocol
=
2857 cbc
->SendPAPZCTreeManagerConstructor(mLayersId
);
2858 APZCTreeManagerChild
* derivedProtocol
=
2859 static_cast<APZCTreeManagerChild
*>(baseProtocol
);
2861 mApzcTreeManager
= RefPtr
<IAPZCTreeManager
>(derivedProtocol
);
2863 // Initialize the GeckoContentController for this tab. We don't hold a
2864 // reference because we don't need it. The ContentProcessController will hold
2865 // a reference to the tab, and will be destroyed by the compositor or ipdl
2866 // during destruction.
2867 RefPtr
<GeckoContentController
> contentController
=
2868 new ContentProcessController(this);
2869 APZChild
* apzChild
= new APZChild(contentController
);
2870 cbc
->SendPAPZConstructor(apzChild
, mLayersId
);
2873 IPCResult
BrowserChild::RecvUpdateEffects(const EffectsInfo
& aEffects
) {
2874 mDidSetEffectsInfo
= true;
2876 bool needInvalidate
= false;
2877 if (mEffectsInfo
.IsVisible() && aEffects
.IsVisible() &&
2878 mEffectsInfo
!= aEffects
) {
2879 // if we are staying visible and either the visrect or scale changed we need
2881 needInvalidate
= true;
2884 mEffectsInfo
= aEffects
;
2887 if (needInvalidate
) {
2888 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2890 // We don't use BrowserChildBase::GetPresShell() here because that would
2891 // create a content viewer if one doesn't exist yet. Creating a content
2892 // viewer can cause JS to run, which we want to avoid.
2893 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2894 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2896 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
2897 root
->InvalidateFrame();
2906 bool BrowserChild::IsVisible() {
2907 return mPuppetWidget
&& mPuppetWidget
->IsVisible();
2910 void BrowserChild::UpdateVisibility() {
2911 bool shouldBeVisible
= mIsTopLevel
? mRenderLayers
: mEffectsInfo
.IsVisible();
2912 bool isVisible
= IsVisible();
2914 if (shouldBeVisible
!= isVisible
) {
2915 if (shouldBeVisible
) {
2923 void BrowserChild::MakeVisible() {
2928 if (mPuppetWidget
) {
2929 mPuppetWidget
->Show(true);
2932 PresShellActivenessMaybeChanged();
2935 void BrowserChild::MakeHidden() {
2940 // Due to the nested event loop in ContentChild::ProvideWindowCommon,
2941 // it's possible to be told to become hidden before we're finished
2942 // setting up a layer manager. We should skip clearing cached layers
2943 // in that case, since doing so might accidentally put is into
2944 // BasicLayers mode.
2945 if (mPuppetWidget
) {
2946 if (mPuppetWidget
->HasWindowRenderer()) {
2947 ClearCachedResources();
2949 mPuppetWidget
->Show(false);
2952 PresShellActivenessMaybeChanged();
2955 IPCResult
BrowserChild::RecvPreserveLayers(bool aPreserve
) {
2956 mIsPreservingLayers
= aPreserve
;
2958 PresShellActivenessMaybeChanged();
2963 void BrowserChild::PresShellActivenessMaybeChanged() {
2964 // We don't use BrowserChildBase::GetPresShell() here because that would
2965 // create a content viewer if one doesn't exist yet. Creating a content
2966 // viewer can cause JS to run, which we want to avoid.
2967 // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
2969 // When this method is called we don't want to go through the browsing context
2970 // because we don't want to change the visibility state of the document, which
2971 // has side effects like firing events to content, unblocking media playback,
2972 // unthrottling timeouts... PresShell activeness has a lot less side effects.
2973 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
2977 RefPtr
<PresShell
> presShell
= docShell
->GetPresShell();
2981 presShell
->ActivenessMaybeChanged();
2985 BrowserChild::GetMessageManager(ContentFrameMessageManager
** aResult
) {
2986 RefPtr
<ContentFrameMessageManager
> mm(mBrowserChildMessageManager
);
2988 return *aResult
? NS_OK
: NS_ERROR_FAILURE
;
2991 void BrowserChild::SendRequestFocus(bool aCanFocus
, CallerType aCallerType
) {
2992 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
2997 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
3002 BrowsingContext
* focusedBC
= fm
->GetFocusedBrowsingContext();
3003 if (focusedBC
== window
->GetBrowsingContext()) {
3004 // BrowsingContext has the focus already, do not request again.
3008 PBrowserChild::SendRequestFocus(aCanFocus
, aCallerType
);
3012 BrowserChild::GetTabId(uint64_t* aId
) {
3018 BrowserChild::GetChromeOuterWindowID(uint64_t* aId
) {
3019 *aId
= ChromeOuterWindowID();
3023 bool BrowserChild::DoSendBlockingMessage(
3024 const nsAString
& aMessage
, StructuredCloneData
& aData
,
3025 nsTArray
<StructuredCloneData
>* aRetVal
) {
3026 ClonedMessageData data
;
3027 if (!BuildClonedMessageData(aData
, data
)) {
3030 return SendSyncMessage(PromiseFlatString(aMessage
), data
, aRetVal
);
3033 nsresult
BrowserChild::DoSendAsyncMessage(const nsAString
& aMessage
,
3034 StructuredCloneData
& aData
) {
3035 ClonedMessageData data
;
3036 if (!BuildClonedMessageData(aData
, data
)) {
3037 return NS_ERROR_DOM_DATA_CLONE_ERR
;
3039 if (!SendAsyncMessage(PromiseFlatString(aMessage
), data
)) {
3040 return NS_ERROR_UNEXPECTED
;
3046 nsTArray
<RefPtr
<BrowserChild
>> BrowserChild::GetAll() {
3047 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
3049 if (!sBrowserChildren
) {
3053 return ToTArray
<nsTArray
<RefPtr
<BrowserChild
>>>(sBrowserChildren
->Values());
3056 BrowserChild
* BrowserChild::GetFrom(PresShell
* aPresShell
) {
3057 Document
* doc
= aPresShell
->GetDocument();
3061 nsCOMPtr
<nsIDocShell
> docShell(doc
->GetDocShell());
3062 return GetFrom(docShell
);
3065 BrowserChild
* BrowserChild::GetFrom(layers::LayersId aLayersId
) {
3066 StaticMutexAutoLock
lock(sBrowserChildrenMutex
);
3067 if (!sBrowserChildren
) {
3070 return sBrowserChildren
->Get(uint64_t(aLayersId
));
3073 void BrowserChild::DidComposite(mozilla::layers::TransactionId aTransactionId
,
3074 const TimeStamp
& aCompositeStart
,
3075 const TimeStamp
& aCompositeEnd
) {
3076 MOZ_ASSERT(mPuppetWidget
);
3077 RefPtr
<WebRenderLayerManager
> lm
=
3078 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3082 lm
->DidComposite(aTransactionId
, aCompositeStart
, aCompositeEnd
);
3086 void BrowserChild::DidRequestComposite(const TimeStamp
& aCompositeReqStart
,
3087 const TimeStamp
& aCompositeReqEnd
) {
3088 nsCOMPtr
<nsIDocShell
> docShellComPtr
= do_GetInterface(WebNavigation());
3089 if (!docShellComPtr
) {
3093 nsDocShell
* docShell
= static_cast<nsDocShell
*>(docShellComPtr
.get());
3095 if (TimelineConsumers::HasConsumer(docShell
)) {
3096 // Since we're assuming that it's impossible for content JS to directly
3097 // trigger a synchronous paint, we can avoid capturing a stack trace here,
3098 // which means we won't run into JS engine reentrancy issues like bug
3100 TimelineConsumers::AddMarkerForDocShell(
3101 docShell
, "CompositeForwardTransaction", aCompositeReqStart
,
3102 MarkerTracingType::START
, MarkerStackRequest::NO_STACK
);
3103 TimelineConsumers::AddMarkerForDocShell(
3104 docShell
, "CompositeForwardTransaction", aCompositeReqEnd
,
3105 MarkerTracingType::END
, MarkerStackRequest::NO_STACK
);
3109 void BrowserChild::ClearCachedResources() {
3110 MOZ_ASSERT(mPuppetWidget
);
3111 RefPtr
<WebRenderLayerManager
> lm
=
3112 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3114 lm
->ClearCachedResources();
3117 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
3118 nsPresContext
* presContext
= document
->GetPresContext();
3120 presContext
->NotifyPaintStatusReset();
3125 void BrowserChild::SchedulePaint() {
3126 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
3131 // We don't use BrowserChildBase::GetPresShell() here because that would
3132 // create a content viewer if one doesn't exist yet. Creating a content viewer
3133 // can cause JS to run, which we want to avoid. nsIDocShell::GetPresShell
3134 // returns null if no content viewer exists yet.
3135 if (RefPtr
<PresShell
> presShell
= docShell
->GetPresShell()) {
3136 if (nsIFrame
* root
= presShell
->GetRootFrame()) {
3137 root
->SchedulePaint();
3142 void BrowserChild::ReinitRendering() {
3143 MOZ_ASSERT(mLayersId
.IsValid());
3145 // In some cases, like when we create a windowless browser,
3146 // RemoteLayerTreeOwner/BrowserChild is not connected to a compositor.
3147 if (mLayersConnectRequested
.isNothing() ||
3148 mLayersConnectRequested
== Some(false)) {
3152 // Before we establish a new PLayerTransaction, we must connect our layer tree
3153 // id, CompositorBridge, and the widget compositor all together again.
3154 // Normally this happens in BrowserParent before BrowserChild is given
3155 // rendering information.
3157 // In this case, we will send a sync message to our BrowserParent, which in
3158 // turn will send a sync message to the Compositor of the widget owning this
3159 // tab. This guarantees the correct association is in place before our
3160 // PLayerTransaction constructor message arrives on the cross-process
3161 // compositor bridge.
3162 CompositorOptions options
;
3163 SendEnsureLayersConnected(&options
);
3164 mCompositorOptions
= Some(options
);
3166 bool success
= false;
3167 RefPtr
<CompositorBridgeChild
> cb
= CompositorBridgeChild::Get();
3170 success
= CreateRemoteLayerManager(cb
);
3174 NS_WARNING("failed to recreate layer manager");
3178 mLayersConnected
= Some(true);
3179 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier
);
3180 gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier
);
3183 RefPtr
<WebRenderLayerManager
> lm
=
3184 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3186 lm
->SetLayersObserverEpoch(mLayersObserverEpoch
);
3189 if (nsCOMPtr
<Document
> doc
= GetTopLevelDocument()) {
3190 doc
->NotifyLayerManagerRecreated();
3193 if (mRenderLayers
) {
3198 void BrowserChild::ReinitRenderingForDeviceReset() {
3199 RefPtr
<WebRenderLayerManager
> lm
=
3200 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3202 lm
->DoDestroy(/* aIsSync */ true);
3205 // Proceed with destroying and recreating the layer manager.
3210 BrowserChild::OnShowTooltip(int32_t aXCoords
, int32_t aYCoords
,
3211 const nsAString
& aTipText
,
3212 const nsAString
& aTipDir
) {
3213 nsString
str(aTipText
);
3214 nsString
dir(aTipDir
);
3215 SendShowTooltip(aXCoords
, aYCoords
, str
, dir
);
3220 BrowserChild::OnHideTooltip() {
3225 void BrowserChild::NotifyJankedAnimations(
3226 const nsTArray
<uint64_t>& aJankedAnimations
) {
3227 MOZ_ASSERT(mPuppetWidget
);
3228 RefPtr
<WebRenderLayerManager
> lm
=
3229 mPuppetWidget
->GetWindowRenderer()->AsWebRender();
3231 lm
->UpdatePartialPrerenderedAnimations(aJankedAnimations
);
3235 mozilla::ipc::IPCResult
BrowserChild::RecvUIResolutionChanged(
3236 const float& aDpi
, const int32_t& aRounding
, const double& aScale
) {
3237 ScreenIntSize oldScreenSize
= GetInnerSize();
3239 mPuppetWidget
->UpdateBackingScaleCache(aDpi
, aRounding
, aScale
);
3242 ScreenIntSize screenSize
= GetInnerSize();
3243 if (mHasValidInnerSize
&& oldScreenSize
!= screenSize
) {
3244 ScreenIntRect screenRect
= GetOuterRect();
3246 // See RecvUpdateDimensions for the order of these operations.
3247 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(WebNavigation());
3248 baseWin
->SetPositionAndSize(0, 0, screenSize
.width
, screenSize
.height
,
3249 nsIBaseWindow::eRepaint
);
3251 mPuppetWidget
->Resize(screenRect
.x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3252 screenRect
.y
+ mClientOffset
.y
+ mChromeOffset
.y
,
3253 screenSize
.width
, screenSize
.height
, true);
3256 nsCOMPtr
<Document
> document(GetTopLevelDocument());
3257 RefPtr
<nsPresContext
> presContext
=
3258 document
? document
->GetPresContext() : nullptr;
3260 presContext
->UIResolutionChangedSync();
3266 mozilla::ipc::IPCResult
BrowserChild::RecvSafeAreaInsetsChanged(
3267 const mozilla::ScreenIntMargin
& aSafeAreaInsets
) {
3268 mPuppetWidget
->UpdateSafeAreaInsets(aSafeAreaInsets
);
3270 nsCOMPtr
<nsIScreenManager
> screenMgr
=
3271 do_GetService("@mozilla.org/gfx/screenmanager;1");
3272 ScreenIntMargin currentSafeAreaInsets
;
3274 // aSafeAreaInsets is for current screen. But we have to calculate
3275 // safe insets for content window.
3276 int32_t x
, y
, cx
, cy
;
3277 GetDimensions(0, &x
, &y
, &cx
, &cy
);
3278 nsCOMPtr
<nsIScreen
> screen
;
3279 screenMgr
->ScreenForRect(x
, y
, cx
, cy
, getter_AddRefs(screen
));
3282 LayoutDeviceIntRect
windowRect(x
+ mClientOffset
.x
+ mChromeOffset
.x
,
3283 y
+ mClientOffset
.y
+ mChromeOffset
.y
, cx
,
3285 currentSafeAreaInsets
= nsContentUtils::GetWindowSafeAreaInsets(
3286 screen
, aSafeAreaInsets
, windowRect
);
3290 if (nsCOMPtr
<Document
> document
= GetTopLevelDocument()) {
3291 nsPresContext
* presContext
= document
->GetPresContext();
3293 presContext
->SetSafeAreaInsets(currentSafeAreaInsets
);
3297 // https://github.com/w3c/csswg-drafts/issues/4670
3298 // Actually we don't set this value on sub document. This behaviour is
3299 // same as Blink that safe area insets isn't set on sub document.
3304 mozilla::ipc::IPCResult
BrowserChild::RecvAllowScriptsToClose() {
3305 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_GetInterface(WebNavigation());
3307 nsGlobalWindowOuter::Cast(window
)->AllowScriptsToClose();
3312 mozilla::ipc::IPCResult
BrowserChild::RecvReleaseAllPointerCapture() {
3313 PointerEventHandler::ReleaseAllPointerCapture();
3317 PPaymentRequestChild
* BrowserChild::AllocPPaymentRequestChild() {
3319 "We should never be manually allocating PPaymentRequestChild actors");
3323 bool BrowserChild::DeallocPPaymentRequestChild(PPaymentRequestChild
* actor
) {
3328 ScreenIntSize
BrowserChild::GetInnerSize() {
3329 LayoutDeviceIntSize innerSize
=
3330 RoundedToInt(mUnscaledInnerSize
* mPuppetWidget
->GetDefaultScale());
3331 return ViewAs
<ScreenPixel
>(
3332 innerSize
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3335 Maybe
<nsRect
> BrowserChild::GetVisibleRect() const {
3337 // We are conservative about visible rects for top-level browsers to avoid
3338 // artifacts when resizing
3342 return mDidSetEffectsInfo
? Some(mEffectsInfo
.mVisibleRect
) : Nothing();
3345 Maybe
<LayoutDeviceRect
>
3346 BrowserChild::GetTopLevelViewportVisibleRectInSelfCoords() const {
3351 if (!mChildToParentConversionMatrix
) {
3352 // We have no way to tell this remote document visible rect right now.
3356 Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
> inverse
=
3357 mChildToParentConversionMatrix
->MaybeInverse();
3362 // Convert the remote document visible rect to the coordinate system of the
3364 Maybe
<LayoutDeviceRect
> rect
= UntransformBy(
3366 ViewAs
<LayoutDevicePixel
>(
3367 mTopLevelViewportVisibleRectInBrowserCoords
,
3368 PixelCastJustification::ContentProcessIsLayerInUiProcess
),
3369 LayoutDeviceRect::MaxIntRect());
3377 ScreenIntRect
BrowserChild::GetOuterRect() {
3378 LayoutDeviceIntRect outerRect
=
3379 RoundedToInt(mUnscaledOuterRect
* mPuppetWidget
->GetDefaultScale());
3380 return ViewAs
<ScreenPixel
>(
3381 outerRect
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
3384 void BrowserChild::PaintWhileInterruptingJS(
3385 const layers::LayersObserverEpoch
& aEpoch
) {
3386 if (!IPCOpen() || !mPuppetWidget
|| !mPuppetWidget
->HasWindowRenderer()) {
3387 // Don't bother doing anything now. Better to wait until we receive the
3388 // message on the PContent channel.
3392 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
3393 nsAutoScriptBlocker scriptBlocker
;
3394 RecvRenderLayers(true /* aEnabled */, aEpoch
);
3397 nsresult
BrowserChild::CanCancelContentJS(
3398 nsIRemoteTab::NavigationType aNavigationType
, int32_t aNavigationIndex
,
3399 nsIURI
* aNavigationURI
, int32_t aEpoch
, bool* aCanCancel
) {
3401 *aCanCancel
= false;
3403 if (aEpoch
<= mCancelContentJSEpoch
) {
3404 // The next page loaded before we got here, so we shouldn't try to cancel
3409 // If we have session history in the parent we've already performed
3410 // the checks following, so we can return early.
3411 if (mozilla::SessionHistoryInParent()) {
3416 nsCOMPtr
<nsIDocShell
> docShell
= do_GetInterface(WebNavigation());
3417 nsCOMPtr
<nsISHistory
> history
;
3419 history
= nsDocShell::Cast(docShell
)->GetSessionHistory()->LegacySHistory();
3423 return NS_ERROR_FAILURE
;
3427 rv
= history
->GetIndex(¤t
);
3428 NS_ENSURE_SUCCESS(rv
, rv
);
3430 if (current
== -1) {
3431 // This tab has no history! Just return.
3435 nsCOMPtr
<nsISHEntry
> entry
;
3436 rv
= history
->GetEntryAtIndex(current
, getter_AddRefs(entry
));
3437 NS_ENSURE_SUCCESS(rv
, rv
);
3439 nsCOMPtr
<nsIURI
> currentURI
= entry
->GetURI();
3440 if (!currentURI
->SchemeIs("http") && !currentURI
->SchemeIs("https") &&
3441 !currentURI
->SchemeIs("file")) {
3442 // Only cancel content JS for http(s) and file URIs. Other URIs are probably
3443 // internal and we should just let them run to completion.
3447 if (aNavigationType
== nsIRemoteTab::NAVIGATE_BACK
) {
3448 aNavigationIndex
= current
- 1;
3449 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_FORWARD
) {
3450 aNavigationIndex
= current
+ 1;
3451 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_URL
) {
3452 if (!aNavigationURI
) {
3453 return NS_ERROR_FAILURE
;
3456 if (aNavigationURI
->SchemeIs("javascript")) {
3457 // "javascript:" URIs don't (necessarily) trigger navigation to a
3458 // different page, so don't allow the current page's JS to terminate.
3462 // If navigating directly to a URL (e.g. via hitting Enter in the location
3463 // bar), then we can cancel anytime the next URL is different from the
3464 // current, *excluding* the ref ("#").
3466 rv
= currentURI
->EqualsExceptRef(aNavigationURI
, &equals
);
3467 NS_ENSURE_SUCCESS(rv
, rv
);
3468 *aCanCancel
= !equals
;
3471 // Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't
3472 // need to do anything special.
3474 int32_t delta
= aNavigationIndex
> current
? 1 : -1;
3475 for (int32_t i
= current
+ delta
; i
!= aNavigationIndex
+ delta
; i
+= delta
) {
3476 nsCOMPtr
<nsISHEntry
> nextEntry
;
3477 // If `i` happens to be negative, this call will fail (which is what we
3478 // would want to happen).
3479 rv
= history
->GetEntryAtIndex(i
, getter_AddRefs(nextEntry
));
3480 NS_ENSURE_SUCCESS(rv
, rv
);
3482 nsCOMPtr
<nsISHEntry
> laterEntry
= delta
== 1 ? nextEntry
: entry
;
3483 nsCOMPtr
<nsIURI
> thisURI
= entry
->GetURI();
3484 nsCOMPtr
<nsIURI
> nextURI
= nextEntry
->GetURI();
3486 // If we changed origin and the load wasn't in a subframe, we know it was
3487 // a full document load, so we can cancel the content JS safely.
3488 if (!laterEntry
->GetIsSubFrame()) {
3489 nsAutoCString thisHost
;
3490 rv
= thisURI
->GetPrePath(thisHost
);
3491 NS_ENSURE_SUCCESS(rv
, rv
);
3493 nsAutoCString nextHost
;
3494 rv
= nextURI
->GetPrePath(nextHost
);
3495 NS_ENSURE_SUCCESS(rv
, rv
);
3497 if (!thisHost
.Equals(nextHost
)) {
3509 nsresult
BrowserChild::GetHasSiblings(bool* aHasSiblings
) {
3510 *aHasSiblings
= mHasSiblings
;
3514 nsresult
BrowserChild::SetHasSiblings(bool aHasSiblings
) {
3515 mHasSiblings
= aHasSiblings
;
3519 NS_IMETHODIMP
BrowserChild::OnStateChange(nsIWebProgress
* aWebProgress
,
3520 nsIRequest
* aRequest
,
3521 uint32_t aStateFlags
,
3523 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3527 // We shouldn't need to notify the parent of redirect state changes, since
3528 // with DocumentChannel that only happens when we switch to the real channel,
3529 // and that's an implementation detail that we can hide.
3530 if (aStateFlags
& nsIWebProgressListener::STATE_IS_REDIRECTED_DOCUMENT
) {
3534 // Our OnStateChange call must have provided the nsIDocShell which the source
3535 // comes from. We'll use this to locate the corresponding BrowsingContext in
3536 // the parent process.
3537 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3539 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3540 return NS_ERROR_UNEXPECTED
;
3543 WebProgressData webProgressData
;
3544 Maybe
<WebProgressStateChangeData
> stateChangeData
;
3545 RequestData requestData
;
3547 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3550 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3551 if (browsingContext
->IsTopContent()) {
3552 stateChangeData
.emplace();
3554 stateChangeData
->isNavigating() = docShell
->GetIsNavigating();
3555 stateChangeData
->mayEnableCharacterEncodingMenu() =
3556 docShell
->GetMayEnableCharacterEncodingMenu();
3558 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3559 if (document
&& aStateFlags
& nsIWebProgressListener::STATE_STOP
) {
3560 document
->GetContentType(stateChangeData
->contentType());
3561 document
->GetCharacterSet(stateChangeData
->charset());
3562 stateChangeData
->documentURI() = document
->GetDocumentURIObject();
3564 stateChangeData
->contentType().SetIsVoid(true);
3565 stateChangeData
->charset().SetIsVoid(true);
3569 Unused
<< SendOnStateChange(webProgressData
, requestData
, aStateFlags
,
3570 aStatus
, stateChangeData
);
3575 NS_IMETHODIMP
BrowserChild::OnProgressChange(nsIWebProgress
* aWebProgress
,
3576 nsIRequest
* aRequest
,
3577 int32_t aCurSelfProgress
,
3578 int32_t aMaxSelfProgress
,
3579 int32_t aCurTotalProgress
,
3580 int32_t aMaxTotalProgress
) {
3581 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3585 // FIXME: We currently ignore ProgressChange events from out-of-process
3586 // subframes both here and in BrowserParent. We may want to change this
3587 // behaviour in the future.
3588 if (!GetBrowsingContext()->IsTopContent()) {
3592 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3593 // nullptr or 0 for all arguments other than aCurTotalProgress and
3594 // aMaxTotalProgress. Don't bother sending them.
3595 MOZ_ASSERT(!aWebProgress
);
3596 MOZ_ASSERT(!aRequest
);
3597 MOZ_ASSERT(aCurSelfProgress
== 0);
3598 MOZ_ASSERT(aMaxSelfProgress
== 0);
3600 Unused
<< SendOnProgressChange(aCurTotalProgress
, aMaxTotalProgress
);
3605 NS_IMETHODIMP
BrowserChild::OnLocationChange(nsIWebProgress
* aWebProgress
,
3606 nsIRequest
* aRequest
,
3609 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3613 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3615 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3616 return NS_ERROR_UNEXPECTED
;
3619 RefPtr
<BrowsingContext
> browsingContext
= docShell
->GetBrowsingContext();
3620 RefPtr
<Document
> document
= browsingContext
->GetExtantDocument();
3625 WebProgressData webProgressData
;
3626 RequestData requestData
;
3628 MOZ_TRY(PrepareProgressListenerData(aWebProgress
, aRequest
, webProgressData
,
3631 Maybe
<WebProgressLocationChangeData
> locationChangeData
;
3633 bool canGoBack
= false;
3634 bool canGoForward
= false;
3635 if (!mozilla::SessionHistoryInParent()) {
3636 MOZ_TRY(WebNavigation()->GetCanGoBack(&canGoBack
));
3637 MOZ_TRY(WebNavigation()->GetCanGoForward(&canGoForward
));
3640 if (browsingContext
->IsTopContent()) {
3642 browsingContext
== GetBrowsingContext(),
3643 "Toplevel content BrowsingContext which isn't GetBrowsingContext()?");
3645 locationChangeData
.emplace();
3647 document
->GetContentType(locationChangeData
->contentType());
3648 locationChangeData
->isNavigating() = docShell
->GetIsNavigating();
3649 locationChangeData
->documentURI() = document
->GetDocumentURIObject();
3650 document
->GetTitle(locationChangeData
->title());
3651 document
->GetCharacterSet(locationChangeData
->charset());
3653 locationChangeData
->mayEnableCharacterEncodingMenu() =
3654 docShell
->GetMayEnableCharacterEncodingMenu();
3656 locationChangeData
->contentPrincipal() = document
->NodePrincipal();
3657 locationChangeData
->contentPartitionedPrincipal() =
3658 document
->PartitionedPrincipal();
3659 locationChangeData
->csp() = document
->GetCsp();
3660 locationChangeData
->referrerInfo() = document
->ReferrerInfo();
3661 locationChangeData
->isSyntheticDocument() = document
->IsSyntheticDocument();
3663 if (nsCOMPtr
<nsILoadGroup
> loadGroup
= document
->GetDocumentLoadGroup()) {
3664 uint64_t requestContextID
= 0;
3665 MOZ_TRY(loadGroup
->GetRequestContextID(&requestContextID
));
3666 locationChangeData
->requestContextID() = Some(requestContextID
);
3669 #ifdef MOZ_CRASHREPORTER
3670 if (CrashReporter::GetEnabled()) {
3671 nsCOMPtr
<nsIURI
> annotationURI
;
3674 NS_MutateURI(aLocation
).SetUserPass(""_ns
).Finalize(annotationURI
);
3676 if (NS_FAILED(rv
)) {
3677 // Ignore failures on about: URIs.
3678 annotationURI
= aLocation
;
3681 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL
,
3682 annotationURI
->GetSpecOrDefault());
3687 Unused
<< SendOnLocationChange(webProgressData
, requestData
, aLocation
,
3688 aFlags
, canGoBack
, canGoForward
,
3689 locationChangeData
);
3694 NS_IMETHODIMP
BrowserChild::OnStatusChange(nsIWebProgress
* aWebProgress
,
3695 nsIRequest
* aRequest
,
3697 const char16_t
* aMessage
) {
3698 if (!IPCOpen() || !mShouldSendWebProgressEventsToParent
) {
3702 // FIXME: We currently ignore StatusChange from out-of-process subframes both
3703 // here and in BrowserParent. We may want to change this behaviour in the
3705 if (!GetBrowsingContext()->IsTopContent()) {
3709 // As we're being filtered by nsBrowserStatusFilter, we will be passed either
3710 // nullptr or NS_OK for all arguments other than aMessage. Don't bother
3712 MOZ_ASSERT(!aWebProgress
);
3713 MOZ_ASSERT(!aRequest
);
3714 MOZ_ASSERT(aStatus
== NS_OK
);
3716 Unused
<< SendOnStatusChange(nsDependentString(aMessage
));
3721 NS_IMETHODIMP
BrowserChild::OnSecurityChange(nsIWebProgress
* aWebProgress
,
3722 nsIRequest
* aRequest
,
3724 // Security changes are now handled entirely in the parent process
3725 // so we don't need to worry about forwarding them (and we shouldn't
3726 // be receiving any to forward).
3730 NS_IMETHODIMP
BrowserChild::OnContentBlockingEvent(nsIWebProgress
* aWebProgress
,
3731 nsIRequest
* aRequest
,
3733 // The OnContentBlockingEvent only happenes in the parent process. It should
3734 // not be seen in the content process.
3735 MOZ_DIAGNOSTIC_ASSERT(
3736 false, "OnContentBlockingEvent should not be seen in content process.");
3737 return NS_ERROR_NOT_IMPLEMENTED
;
3740 NS_IMETHODIMP
BrowserChild::OnProgressChange64(nsIWebProgress
* aWebProgress
,
3741 nsIRequest
* aRequest
,
3742 int64_t aCurSelfProgress
,
3743 int64_t aMaxSelfProgress
,
3744 int64_t aCurTotalProgress
,
3745 int64_t aMaxTotalProgress
) {
3746 // All the events we receive are filtered through an nsBrowserStatusFilter,
3747 // which accepts ProgressChange64 events, but truncates the progress values to
3748 // uint32_t and calls OnProgressChange.
3749 return NS_ERROR_NOT_IMPLEMENTED
;
3752 NS_IMETHODIMP
BrowserChild::OnRefreshAttempted(nsIWebProgress
* aWebProgress
,
3753 nsIURI
* aRefreshURI
,
3754 uint32_t aMillis
, bool aSameURI
,
3756 NS_ENSURE_ARG_POINTER(aOut
);
3762 NS_IMETHODIMP
BrowserChild::NotifyNavigationFinished() {
3763 Unused
<< SendNavigationFinished();
3767 nsresult
BrowserChild::PrepareRequestData(nsIRequest
* aRequest
,
3768 RequestData
& aRequestData
) {
3769 nsCOMPtr
<nsIChannel
> channel
= do_QueryInterface(aRequest
);
3771 aRequestData
.requestURI() = nullptr;
3775 nsresult rv
= channel
->GetURI(getter_AddRefs(aRequestData
.requestURI()));
3776 NS_ENSURE_SUCCESS(rv
, rv
);
3778 rv
= channel
->GetOriginalURI(
3779 getter_AddRefs(aRequestData
.originalRequestURI()));
3780 NS_ENSURE_SUCCESS(rv
, rv
);
3782 nsCOMPtr
<nsIClassifiedChannel
> classifiedChannel
= do_QueryInterface(channel
);
3783 if (classifiedChannel
) {
3784 rv
= classifiedChannel
->GetMatchedList(aRequestData
.matchedList());
3785 NS_ENSURE_SUCCESS(rv
, rv
);
3790 nsresult
BrowserChild::PrepareProgressListenerData(
3791 nsIWebProgress
* aWebProgress
, nsIRequest
* aRequest
,
3792 WebProgressData
& aWebProgressData
, RequestData
& aRequestData
) {
3793 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(aWebProgress
);
3795 MOZ_ASSERT_UNREACHABLE("aWebProgress is null or not a nsIDocShell?");
3796 return NS_ERROR_UNEXPECTED
;
3799 aWebProgressData
.browsingContext() = docShell
->GetBrowsingContext();
3800 nsresult rv
= aWebProgress
->GetLoadType(&aWebProgressData
.loadType());
3801 NS_ENSURE_SUCCESS(rv
, rv
);
3803 return PrepareRequestData(aRequest
, aRequestData
);
3806 void BrowserChild::UpdateSessionStore() {
3807 if (mSessionStoreChild
) {
3808 mSessionStoreChild
->UpdateSessionStore();
3813 RefPtr
<PBrowserChild::IsWindowSupportingProtectedMediaPromise
>
3814 BrowserChild::DoesWindowSupportProtectedMedia() {
3817 "Protected media support check should be done on main thread only.");
3818 if (mWindowSupportsProtectedMedia
) {
3819 // If we've already checked and have a cached result, resolve with that.
3820 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3821 mWindowSupportsProtectedMedia
.value(), __func__
);
3823 RefPtr
<BrowserChild
> self
= this;
3824 // We chain off the promise rather than passing it directly so we can cache
3825 // the result and use that for future calls.
3826 return SendIsWindowSupportingProtectedMedia(ChromeOuterWindowID())
3828 GetCurrentSerialEventTarget(), __func__
,
3829 [self
](bool isSupported
) {
3830 // If a result was cached while this check was inflight, ensure the
3833 self
->mWindowSupportsProtectedMedia
,
3834 self
->mWindowSupportsProtectedMedia
.value() == isSupported
);
3835 // Cache the response as it will not change during the lifetime
3837 self
->mWindowSupportsProtectedMedia
= Some(isSupported
);
3838 return IsWindowSupportingProtectedMediaPromise::CreateAndResolve(
3839 self
->mWindowSupportsProtectedMedia
.value(), __func__
);
3841 [](ResponseRejectReason reason
) {
3842 return IsWindowSupportingProtectedMediaPromise::CreateAndReject(
3848 void BrowserChild::NotifyContentBlockingEvent(
3849 uint32_t aEvent
, nsIChannel
* aChannel
, bool aBlocked
,
3850 const nsACString
& aTrackingOrigin
,
3851 const nsTArray
<nsCString
>& aTrackingFullHashes
,
3853 mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
3859 RequestData requestData
;
3860 if (NS_SUCCEEDED(PrepareRequestData(aChannel
, requestData
))) {
3861 Unused
<< SendNotifyContentBlockingEvent(
3862 aEvent
, requestData
, aBlocked
, PromiseFlatCString(aTrackingOrigin
),
3863 aTrackingFullHashes
, aReason
);
3868 BrowserChild::ContentTransformsReceived(JSContext
* aCx
,
3869 dom::Promise
** aPromise
) {
3870 auto* globalObject
= xpc::CurrentNativeGlobal(aCx
);
3872 if (mChildToParentConversionMatrix
) {
3873 // Already received content transforms
3874 RefPtr
<Promise
> promise
=
3875 Promise::CreateResolvedWithUndefined(globalObject
, rv
);
3876 promise
.forget(aPromise
);
3877 return rv
.StealNSResult();
3880 if (!mContentTransformPromise
) {
3881 mContentTransformPromise
= Promise::Create(globalObject
, rv
);
3884 MOZ_ASSERT(globalObject
== mContentTransformPromise
->GetGlobalObject());
3885 NS_IF_ADDREF(*aPromise
= mContentTransformPromise
);
3886 return rv
.StealNSResult();
3889 BrowserChildMessageManager::BrowserChildMessageManager(
3890 BrowserChild
* aBrowserChild
)
3891 : ContentFrameMessageManager(new nsFrameMessageManager(aBrowserChild
)),
3892 mBrowserChild(aBrowserChild
) {}
3894 BrowserChildMessageManager::~BrowserChildMessageManager() = default;
3896 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChildMessageManager
)
3898 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BrowserChildMessageManager
,
3899 DOMEventTargetHelper
)
3900 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager
);
3901 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild
);
3902 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
3903 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
3905 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BrowserChildMessageManager
,
3906 DOMEventTargetHelper
)
3907 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager
)
3908 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild
)
3909 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
3911 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChildMessageManager
)
3912 NS_INTERFACE_MAP_ENTRY(nsIMessageSender
)
3913 NS_INTERFACE_MAP_ENTRY(ContentFrameMessageManager
)
3914 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
3915 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
3917 NS_IMPL_ADDREF_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3918 NS_IMPL_RELEASE_INHERITED(BrowserChildMessageManager
, DOMEventTargetHelper
)
3920 JSObject
* BrowserChildMessageManager::WrapObject(
3921 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
3922 return ContentFrameMessageManager_Binding::Wrap(aCx
, this, aGivenProto
);
3925 void BrowserChildMessageManager::MarkForCC() {
3926 if (mBrowserChild
) {
3927 mBrowserChild
->MarkScopesForCC();
3929 EventListenerManager
* elm
= GetExistingListenerManager();
3933 MessageManagerGlobal::MarkForCC();
3936 Nullable
<WindowProxyHolder
> BrowserChildMessageManager::GetContent(
3937 ErrorResult
& aError
) {
3938 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell(aError
);
3942 return WindowProxyHolder(docShell
->GetBrowsingContext());
3945 already_AddRefed
<nsIDocShell
> BrowserChildMessageManager::GetDocShell(
3946 ErrorResult
& aError
) {
3947 if (!mBrowserChild
) {
3948 aError
.Throw(NS_ERROR_NULL_POINTER
);
3951 nsCOMPtr
<nsIDocShell
> window
=
3952 do_GetInterface(mBrowserChild
->WebNavigation());
3953 return window
.forget();
3956 already_AddRefed
<nsIEventTarget
>
3957 BrowserChildMessageManager::GetTabEventTarget() {
3958 nsCOMPtr
<nsIEventTarget
> target
= EventTargetFor(TaskCategory::Other
);
3959 return target
.forget();
3962 nsresult
BrowserChildMessageManager::Dispatch(
3963 TaskCategory aCategory
, already_AddRefed
<nsIRunnable
>&& aRunnable
) {
3964 return DispatcherTrait::Dispatch(aCategory
, std::move(aRunnable
));
3967 nsISerialEventTarget
* BrowserChildMessageManager::EventTargetFor(
3968 TaskCategory aCategory
) const {
3969 return DispatcherTrait::EventTargetFor(aCategory
);
3972 AbstractThread
* BrowserChildMessageManager::AbstractMainThreadFor(
3973 TaskCategory aCategory
) {
3974 return DispatcherTrait::AbstractMainThreadFor(aCategory
);