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 "BrowserParent.h"
10 #include "mozilla/AlreadyAddRefed.h"
11 #include "mozilla/EventForwards.h"
14 # include "mozilla/a11y/DocAccessibleParent.h"
15 # include "mozilla/a11y/Platform.h"
16 # include "nsAccessibilityService.h"
18 #include "mozilla/Components.h"
19 #include "mozilla/dom/BrowserHost.h"
20 #include "mozilla/dom/BrowserSessionStore.h"
21 #include "mozilla/dom/BrowsingContextGroup.h"
22 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
23 #include "mozilla/dom/ChromeMessageSender.h"
24 #include "mozilla/dom/ContentParent.h"
25 #include "mozilla/dom/ContentProcessManager.h"
26 #include "mozilla/dom/DataTransfer.h"
27 #include "mozilla/dom/DataTransferItemList.h"
28 #include "mozilla/dom/DocumentInlines.h"
29 #include "mozilla/dom/Event.h"
30 #include "mozilla/dom/indexedDB/ActorsParent.h"
31 #include "mozilla/dom/PaymentRequestParent.h"
32 #include "mozilla/dom/PointerEventHandler.h"
33 #include "mozilla/dom/BrowserBridgeParent.h"
34 #include "mozilla/dom/RemoteDragStartData.h"
35 #include "mozilla/dom/RemoteWebProgressRequest.h"
36 #include "mozilla/dom/SessionHistoryEntry.h"
37 #include "mozilla/dom/SessionStoreParent.h"
38 #include "mozilla/dom/UserActivation.h"
39 #include "mozilla/EventStateManager.h"
40 #include "mozilla/gfx/2D.h"
41 #include "mozilla/gfx/DataSurfaceHelpers.h"
42 #include "mozilla/gfx/GPUProcessManager.h"
43 #include "mozilla/IMEStateManager.h"
44 #include "mozilla/ipc/Endpoint.h"
45 #include "mozilla/layers/AsyncDragMetrics.h"
46 #include "mozilla/layers/InputAPZContext.h"
47 #include "mozilla/layout/RemoteLayerTreeOwner.h"
48 #include "mozilla/LookAndFeel.h"
49 #include "mozilla/Maybe.h"
50 #include "mozilla/MiscEvents.h"
51 #include "mozilla/MouseEvents.h"
52 #include "mozilla/NativeKeyBindingsType.h"
53 #include "mozilla/net/NeckoChild.h"
54 #include "mozilla/net/CookieJarSettings.h"
55 #include "mozilla/Preferences.h"
56 #include "mozilla/PresShell.h"
57 #include "mozilla/ProcessHangMonitor.h"
58 #include "mozilla/RecursiveMutex.h"
59 #include "mozilla/RefPtr.h"
60 #include "mozilla/StaticPrefs_dom.h"
61 #include "mozilla/TextEventDispatcher.h"
62 #include "mozilla/TextEvents.h"
63 #include "mozilla/TouchEvents.h"
64 #include "mozilla/UniquePtr.h"
65 #include "mozilla/Unused.h"
67 #include "nsContentUtils.h"
69 #include "nsFocusManager.h"
70 #include "nsFrameLoader.h"
71 #include "nsFrameLoaderOwner.h"
72 #include "nsFrameManager.h"
73 #include "nsIBaseWindow.h"
74 #include "nsIBrowser.h"
75 #include "nsIBrowserController.h"
76 #include "nsIContent.h"
77 #include "nsICookieJarSettings.h"
78 #include "nsIDocShell.h"
79 #include "nsIDocShellTreeOwner.h"
80 #include "nsImportModule.h"
81 #include "nsIInterfaceRequestorUtils.h"
82 #include "nsILoadInfo.h"
83 #include "nsIPromptFactory.h"
85 #include "nsIWebBrowserChrome.h"
86 #include "nsIWebProtocolHandlerRegistrar.h"
87 #include "nsIWindowWatcher.h"
88 #include "nsIXPConnect.h"
89 #include "nsIXULBrowserWindow.h"
90 #include "nsIAppWindow.h"
91 #include "nsLayoutUtils.h"
92 #include "nsQueryActor.h"
93 #include "nsSHistory.h"
94 #include "nsViewManager.h"
95 #include "nsVariant.h"
96 #include "nsIWidget.h"
97 #include "nsNetUtil.h"
99 # include "nsJARProtocolHandler.h"
101 #include "nsPIDOMWindow.h"
102 #include "nsPrintfCString.h"
103 #include "nsQueryObject.h"
104 #include "nsServiceManagerUtils.h"
105 #include "nsThreadUtils.h"
106 #include "PermissionMessageUtils.h"
107 #include "StructuredCloneData.h"
108 #include "ColorPickerParent.h"
109 #include "FilePickerParent.h"
110 #include "BrowserChild.h"
111 #include "nsNetCID.h"
112 #include "nsIAuthInformation.h"
113 #include "nsIAuthPromptCallback.h"
114 #include "nsAuthInformationHolder.h"
115 #include "nsICancelable.h"
116 #include "gfxUtils.h"
117 #include "nsILoginManagerAuthPrompter.h"
118 #include "nsPIWindowRoot.h"
119 #include "nsReadableUtils.h"
120 #include "nsIAuthPrompt2.h"
121 #include "gfxDrawable.h"
122 #include "ImageOps.h"
123 #include "UnitTransforms.h"
125 #include "mozilla/NullPrincipal.h"
126 #include "mozilla/WebBrowserPersistDocumentParent.h"
127 #include "ProcessPriorityManager.h"
128 #include "nsString.h"
129 #include "IHistory.h"
130 #include "mozilla/dom/WindowGlobalParent.h"
131 #include "mozilla/dom/CanonicalBrowsingContext.h"
132 #include "mozilla/ProfilerLabels.h"
133 #include "MMPrinter.h"
134 #include "mozilla/dom/CrashReport.h"
135 #include "nsISecureBrowserUI.h"
136 #include "nsIXULRuntime.h"
137 #include "VsyncSource.h"
138 #include "nsSubDocumentFrame.h"
141 # include "FxRWindowManager.h"
144 #if defined(XP_WIN) && defined(ACCESSIBILITY)
145 # include "mozilla/a11y/AccessibleWrap.h"
146 # include "mozilla/a11y/Compatibility.h"
147 # include "mozilla/a11y/nsWinUtils.h"
150 #ifdef MOZ_ANDROID_HISTORY
151 # include "GeckoViewHistory.h"
154 #if defined(MOZ_WIDGET_ANDROID)
155 # include "mozilla/widget/nsWindow.h"
156 #endif // defined(MOZ_WIDGET_ANDROID)
158 using namespace mozilla::dom
;
159 using namespace mozilla::ipc
;
160 using namespace mozilla::layers
;
161 using namespace mozilla::layout
;
162 using namespace mozilla::services
;
163 using namespace mozilla::widget
;
164 using namespace mozilla::gfx
;
166 using mozilla::LazyLogModule
;
168 extern mozilla::LazyLogModule gSHIPBFCacheLog
;
170 LazyLogModule
gBrowserFocusLog("BrowserFocus");
172 #define LOGBROWSERFOCUS(args) \
173 MOZ_LOG(gBrowserFocusLog, mozilla::LogLevel::Debug, args)
176 BrowserParent
* BrowserParent::sFocus
= nullptr;
178 BrowserParent
* BrowserParent::sTopLevelWebFocus
= nullptr;
180 BrowserParent
* BrowserParent::sLastMouseRemoteTarget
= nullptr;
182 // The flags passed by the webProgress notifications are 16 bits shifted
183 // from the ones registered by webProgressListeners.
184 #define NOTIFY_FLAG_SHIFT 16
189 * Store data of a keypress event which is requesting to handled it in a remote
190 * process or some remote processes.
192 class RequestingAccessKeyEventData
{
194 RequestingAccessKeyEventData() = delete;
196 static void OnBrowserParentCreated() {
197 MOZ_ASSERT(sBrowserParentCount
<= INT32_MAX
);
198 sBrowserParentCount
++;
200 static void OnBrowserParentDestroyed() {
201 MOZ_ASSERT(sBrowserParentCount
> 0);
202 sBrowserParentCount
--;
203 // To avoid memory leak, we need to reset sData when the last BrowserParent
205 if (!sBrowserParentCount
) {
210 static void Set(const WidgetKeyboardEvent
& aKeyPressEvent
) {
211 MOZ_ASSERT(aKeyPressEvent
.mMessage
== eKeyPress
);
212 MOZ_ASSERT(sBrowserParentCount
> 0);
214 Some(Data
{aKeyPressEvent
.mAlternativeCharCodes
, aKeyPressEvent
.mKeyCode
,
215 aKeyPressEvent
.mCharCode
, aKeyPressEvent
.mKeyNameIndex
,
216 aKeyPressEvent
.mCodeNameIndex
, aKeyPressEvent
.mKeyValue
,
217 aKeyPressEvent
.mModifiers
});
220 static void Clear() { sData
.reset(); }
222 [[nodiscard
]] static bool Equals(const WidgetKeyboardEvent
& aKeyPressEvent
) {
223 MOZ_ASSERT(sBrowserParentCount
> 0);
224 return sData
.isSome() && sData
->Equals(aKeyPressEvent
);
227 [[nodiscard
]] static bool IsSet() {
228 MOZ_ASSERT(sBrowserParentCount
> 0);
229 return sData
.isSome();
234 [[nodiscard
]] bool Equals(const WidgetKeyboardEvent
& aKeyPressEvent
) {
235 return mKeyCode
== aKeyPressEvent
.mKeyCode
&&
236 mCharCode
== aKeyPressEvent
.mCharCode
&&
237 mKeyNameIndex
== aKeyPressEvent
.mKeyNameIndex
&&
238 mCodeNameIndex
== aKeyPressEvent
.mCodeNameIndex
&&
239 mKeyValue
== aKeyPressEvent
.mKeyValue
&&
240 mModifiers
== aKeyPressEvent
.mModifiers
&&
241 mAlternativeCharCodes
== aKeyPressEvent
.mAlternativeCharCodes
;
244 CopyableTArray
<AlternativeCharCode
> mAlternativeCharCodes
;
247 KeyNameIndex mKeyNameIndex
;
248 CodeNameIndex mCodeNameIndex
;
250 Modifiers mModifiers
;
252 static Maybe
<Data
> sData
;
253 static int32_t sBrowserParentCount
;
255 int32_t RequestingAccessKeyEventData::sBrowserParentCount
= 0;
256 Maybe
<RequestingAccessKeyEventData::Data
> RequestingAccessKeyEventData::sData
;
260 BrowserParent::LayerToBrowserParentTable
*
261 BrowserParent::sLayerToBrowserParentTable
= nullptr;
263 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserParent
)
264 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider
)
265 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
266 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMEventListener
)
268 NS_IMPL_CYCLE_COLLECTION_WEAK(BrowserParent
, mFrameLoader
, mBrowsingContext
)
269 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserParent
)
270 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserParent
)
272 BrowserParent::BrowserParent(ContentParent
* aManager
, const TabId
& aTabId
,
273 const TabContext
& aContext
,
274 CanonicalBrowsingContext
* aBrowsingContext
,
275 uint32_t aChromeFlags
)
276 : TabContext(aContext
),
279 mBrowsingContext(aBrowsingContext
),
280 mFrameElement(nullptr),
281 mBrowserDOMWindow(nullptr),
282 mFrameLoader(nullptr),
283 mChromeFlags(aChromeFlags
),
284 mBrowserBridgeParent(nullptr),
285 mBrowserHost(nullptr),
286 mContentCache(*this),
287 mRemoteLayerTreeOwner
{},
289 mChildToParentConversionMatrix
{},
295 mUpdatedDimensions(false),
296 mSizeMode(nsSizeMode_Normal
),
299 mCreatingWindow(false),
300 mDelayedFrameScripts
{},
301 mVsyncParent(nullptr),
302 mMarkedDestroying(false),
304 mRemoteTargetSetsCursor(false),
305 mIsPreservingLayers(false),
307 mPriorityHint(false),
309 mHasPresented(false),
310 mIsReadyToHandleInputEvents(false),
311 mIsMouseEnterIntoWidgetEventSuppressed(false),
312 mLockedNativePointer(false),
313 mShowingTooltip(false) {
314 MOZ_ASSERT(aManager
);
316 RequestingAccessKeyEventData::OnBrowserParentCreated();
318 // When the input event queue is disabled, we don't need to handle the case
319 // that some input events are dispatched before PBrowserConstructor.
320 mIsReadyToHandleInputEvents
= !ContentParent::IsInputEventQueueSupported();
322 // Make sure to compute our process priority if needed before the block of
323 // code below. This makes sure the block below prioritizes our process if
325 if (aBrowsingContext
->IsTop()) {
326 RecomputeProcessPriority();
329 // If we're in a BC tree that is active with respect to the priority manager,
330 // ensure that this new BrowserParent is marked as active. This ensures that
331 // the process will be prioritized in a cross-site iframe navigation in an
332 // active tab, and also that the process is correctly prioritized if we got
333 // created for a browsing context which was already active.
334 if (aBrowsingContext
->Top()->IsPriorityActive()) {
335 ProcessPriorityManager::BrowserPriorityChanged(this, true);
339 BrowserParent::~BrowserParent() {
340 RequestingAccessKeyEventData::OnBrowserParentDestroyed();
344 BrowserParent
* BrowserParent::GetFocused() { return sFocus
; }
347 BrowserParent
* BrowserParent::GetLastMouseRemoteTarget() {
348 return sLastMouseRemoteTarget
;
352 BrowserParent
* BrowserParent::GetFrom(nsFrameLoader
* aFrameLoader
) {
356 return aFrameLoader
->GetBrowserParent();
360 BrowserParent
* BrowserParent::GetFrom(PBrowserParent
* aBrowserParent
) {
361 return static_cast<BrowserParent
*>(aBrowserParent
);
365 BrowserParent
* BrowserParent::GetFrom(nsIContent
* aContent
) {
366 RefPtr
<nsFrameLoaderOwner
> loaderOwner
= do_QueryObject(aContent
);
370 RefPtr
<nsFrameLoader
> frameLoader
= loaderOwner
->GetFrameLoader();
371 return GetFrom(frameLoader
);
375 BrowserParent
* BrowserParent::GetBrowserParentFromLayersId(
376 layers::LayersId aLayersId
) {
377 if (!sLayerToBrowserParentTable
) {
380 return sLayerToBrowserParentTable
->Get(uint64_t(aLayersId
));
384 TabId
BrowserParent::GetTabIdFrom(nsIDocShell
* docShell
) {
385 nsCOMPtr
<nsIBrowserChild
> browserChild(BrowserChild::GetFrom(docShell
));
387 return static_cast<BrowserChild
*>(browserChild
.get())->GetTabId();
392 void BrowserParent::AddBrowserParentToTable(layers::LayersId aLayersId
,
393 BrowserParent
* aBrowserParent
) {
394 if (!sLayerToBrowserParentTable
) {
395 sLayerToBrowserParentTable
= new LayerToBrowserParentTable();
397 sLayerToBrowserParentTable
->InsertOrUpdate(uint64_t(aLayersId
),
401 void BrowserParent::RemoveBrowserParentFromTable(layers::LayersId aLayersId
) {
402 if (!sLayerToBrowserParentTable
) {
405 sLayerToBrowserParentTable
->Remove(uint64_t(aLayersId
));
406 if (sLayerToBrowserParentTable
->Count() == 0) {
407 delete sLayerToBrowserParentTable
;
408 sLayerToBrowserParentTable
= nullptr;
412 already_AddRefed
<nsILoadContext
> BrowserParent::GetLoadContext() {
413 return do_AddRef(mBrowsingContext
);
417 * Will return nullptr if there is no outer window available for the
418 * document hosting the owner element of this BrowserParent. Also will return
419 * nullptr if that outer window is in the process of closing.
421 already_AddRefed
<nsPIDOMWindowOuter
> BrowserParent::GetParentWindowOuter() {
422 nsCOMPtr
<nsIContent
> frame
= GetOwnerElement();
427 nsCOMPtr
<nsPIDOMWindowOuter
> parent
= frame
->OwnerDoc()->GetWindow();
428 if (!parent
|| parent
->Closed()) {
432 return parent
.forget();
435 already_AddRefed
<nsIWidget
> BrowserParent::GetTopLevelWidget() {
436 if (RefPtr
<Element
> element
= mFrameElement
) {
437 if (PresShell
* presShell
= element
->OwnerDoc()->GetPresShell()) {
438 return do_AddRef(presShell
->GetViewManager()->GetRootWidget());
444 already_AddRefed
<nsIWidget
> BrowserParent::GetTextInputHandlingWidget() const {
445 if (!mFrameElement
) {
448 PresShell
* presShell
= mFrameElement
->OwnerDoc()->GetPresShell();
452 nsPresContext
* presContext
= presShell
->GetPresContext();
456 nsCOMPtr
<nsIWidget
> widget
= presContext
->GetTextInputHandlingWidget();
457 return widget
.forget();
460 already_AddRefed
<nsIWidget
> BrowserParent::GetWidget() const {
461 if (!mFrameElement
) {
464 nsCOMPtr
<nsIWidget
> widget
= nsContentUtils::WidgetForContent(mFrameElement
);
466 widget
= nsContentUtils::WidgetForDocument(mFrameElement
->OwnerDoc());
468 return widget
.forget();
471 already_AddRefed
<nsIWidget
> BrowserParent::GetDocWidget() const {
472 if (!mFrameElement
) {
476 nsContentUtils::WidgetForDocument(mFrameElement
->OwnerDoc()));
479 nsIXULBrowserWindow
* BrowserParent::GetXULBrowserWindow() {
480 if (!mFrameElement
) {
484 nsCOMPtr
<nsIDocShell
> docShell
= mFrameElement
->OwnerDoc()->GetDocShell();
489 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
490 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
495 nsCOMPtr
<nsIAppWindow
> window
= do_GetInterface(treeOwner
);
500 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
;
501 window
->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow
));
502 return xulBrowserWindow
;
505 uint32_t BrowserParent::GetMaxTouchPoints(Element
* aElement
) {
510 if (StaticPrefs::dom_maxtouchpoints_testing_value() >= 0) {
511 return StaticPrefs::dom_maxtouchpoints_testing_value();
514 nsIWidget
* widget
= nsContentUtils::WidgetForDocument(aElement
->OwnerDoc());
515 return widget
? widget
->GetMaxTouchPoints() : 0;
518 a11y::DocAccessibleParent
* BrowserParent::GetTopLevelDocAccessible() const {
520 // XXX Consider managing non top level PDocAccessibles with their parent
521 // document accessible.
522 const ManagedContainer
<PDocAccessibleParent
>& docs
=
523 ManagedPDocAccessibleParent();
524 for (auto* key
: docs
) {
525 auto* doc
= static_cast<a11y::DocAccessibleParent
*>(key
);
526 // We want the document for this BrowserParent even if it's for an
527 // embedded out-of-process iframe. Therefore, we use
528 // IsTopLevelInContentProcess. In contrast, using IsToplevel would only
529 // include documents that aren't embedded; e.g. tab documents.
530 if (doc
->IsTopLevelInContentProcess() && !doc
->IsShutdown()) {
538 LayersId
BrowserParent::GetLayersId() const {
539 if (!mRemoteLayerTreeOwner
.IsInitialized()) {
542 return mRemoteLayerTreeOwner
.GetLayersId();
545 BrowserBridgeParent
* BrowserParent::GetBrowserBridgeParent() const {
546 return mBrowserBridgeParent
;
549 BrowserHost
* BrowserParent::GetBrowserHost() const { return mBrowserHost
; }
551 ParentShowInfo
BrowserParent::GetShowInfo() {
552 TryCacheDPIAndScale();
555 mFrameElement
->GetAttr(nsGkAtoms::name
, name
);
557 nsContentUtils::IsChromeDoc(mFrameElement
->OwnerDoc()) &&
558 mFrameElement
->HasAttr(nsGkAtoms::transparent
);
559 return ParentShowInfo(name
, false, isTransparent
, mDPI
, mRounding
,
560 mDefaultScale
.scale
);
563 return ParentShowInfo(u
""_ns
, false, false, mDPI
, mRounding
,
564 mDefaultScale
.scale
);
567 already_AddRefed
<nsIPrincipal
> BrowserParent::GetContentPrincipal() const {
568 nsCOMPtr
<nsIBrowser
> browser
=
569 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
570 NS_ENSURE_TRUE(browser
, nullptr);
572 RefPtr
<nsIPrincipal
> principal
;
575 rv
= browser
->GetContentPrincipal(getter_AddRefs(principal
));
576 NS_ENSURE_SUCCESS(rv
, nullptr);
578 return principal
.forget();
581 void BrowserParent::SetOwnerElement(Element
* aElement
) {
582 // If we held previous content then unregister for its events.
583 RemoveWindowListeners();
585 // If we change top-level documents then we need to change our
586 // registration with them.
587 RefPtr
<nsPIWindowRoot
> curTopLevelWin
, newTopLevelWin
;
589 curTopLevelWin
= nsContentUtils::GetWindowRoot(mFrameElement
->OwnerDoc());
592 newTopLevelWin
= nsContentUtils::GetWindowRoot(aElement
->OwnerDoc());
594 bool isSameTopLevelWin
= curTopLevelWin
== newTopLevelWin
;
595 if (mBrowserHost
&& curTopLevelWin
&& !isSameTopLevelWin
) {
596 curTopLevelWin
->RemoveBrowser(mBrowserHost
);
599 // Update to the new content, and register to listen for events from it.
600 mFrameElement
= aElement
;
602 if (mBrowserHost
&& newTopLevelWin
&& !isSameTopLevelWin
) {
603 newTopLevelWin
->AddBrowser(mBrowserHost
);
606 #if defined(XP_WIN) && defined(ACCESSIBILITY)
608 uintptr_t newWindowHandle
= 0;
609 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
611 reinterpret_cast<uintptr_t>(widget
->GetNativeData(NS_NATIVE_WINDOW
));
613 Unused
<< SendUpdateNativeWindowHandle(newWindowHandle
);
614 a11y::DocAccessibleParent
* doc
= GetTopLevelDocAccessible();
616 HWND hWnd
= reinterpret_cast<HWND
>(doc
->GetEmulatedWindowHandle());
618 HWND parentHwnd
= reinterpret_cast<HWND
>(newWindowHandle
);
619 if (parentHwnd
!= ::GetParent(hWnd
)) {
620 ::SetParent(hWnd
, parentHwnd
);
627 AddWindowListeners();
629 // The DPI depends on our frame element's widget, so invalidate now in case
630 // we've tried to cache it already.
632 TryCacheDPIAndScale();
634 if (mRemoteLayerTreeOwner
.IsInitialized()) {
635 mRemoteLayerTreeOwner
.OwnerContentChanged();
638 // Set our BrowsingContext's embedder if we're not embedded within a
639 // BrowserBridgeParent.
640 if (!GetBrowserBridgeParent() && mBrowsingContext
&& mFrameElement
) {
641 mBrowsingContext
->SetEmbedderElement(mFrameElement
);
644 UpdateVsyncParentVsyncDispatcher();
646 VisitChildren([aElement
](BrowserBridgeParent
* aBrowser
) {
647 if (auto* browserParent
= aBrowser
->GetBrowserParent()) {
648 browserParent
->SetOwnerElement(aElement
);
653 void BrowserParent::CacheFrameLoader(nsFrameLoader
* aFrameLoader
) {
654 mFrameLoader
= aFrameLoader
;
657 void BrowserParent::AddWindowListeners() {
659 if (nsCOMPtr
<nsPIDOMWindowOuter
> window
=
660 mFrameElement
->OwnerDoc()->GetWindow()) {
661 nsCOMPtr
<EventTarget
> eventTarget
= window
->GetTopWindowRoot();
663 eventTarget
->AddEventListener(u
"MozUpdateWindowPos"_ns
, this, false,
665 eventTarget
->AddEventListener(u
"fullscreenchange"_ns
, this, false,
672 void BrowserParent::RemoveWindowListeners() {
673 if (mFrameElement
&& mFrameElement
->OwnerDoc()->GetWindow()) {
674 nsCOMPtr
<nsPIDOMWindowOuter
> window
=
675 mFrameElement
->OwnerDoc()->GetWindow();
676 nsCOMPtr
<EventTarget
> eventTarget
= window
->GetTopWindowRoot();
678 eventTarget
->RemoveEventListener(u
"MozUpdateWindowPos"_ns
, this, false);
679 eventTarget
->RemoveEventListener(u
"fullscreenchange"_ns
, this, false);
684 void BrowserParent::Deactivated() {
685 if (mShowingTooltip
) {
686 // Reuse the normal tooltip hiding method.
687 mozilla::Unused
<< RecvHideTooltip();
689 UnlockNativePointer();
690 UnsetTopLevelWebFocus(this);
691 UnsetLastMouseRemoteTarget(this);
692 PointerLockManager::ReleaseLockedRemoteTarget(this);
693 PointerEventHandler::ReleasePointerCaptureRemoteTarget(this);
694 PresShell::ReleaseCapturingRemoteTarget(this);
695 ProcessPriorityManager::BrowserPriorityChanged(this, /* aPriority = */ false);
698 void BrowserParent::Destroy() {
699 // Aggressively release the window to avoid leaking the world in shutdown
701 mBrowserDOMWindow
= nullptr;
709 RemoveWindowListeners();
712 if (a11y::DocAccessibleParent
* tabDoc
= GetTopLevelDocAccessible()) {
713 # if defined(ANDROID)
714 MonitorAutoLock
mal(nsAccessibilityService::GetAndroidMonitor());
721 // The following sequence assumes that the keepalive state does not change
722 // between the calls, but our ThreadsafeHandle might be accessed from other
723 // threads in the meantime.
724 RecursiveMutexAutoLock
lock(Manager()->ThreadsafeHandleMutex());
726 // If we are shutting down everything or we know to be the last
727 // BrowserParent, signal the impending shutdown early to the content process
728 // to avoid to run the SendDestroy before we know we are ExpectingShutdown.
729 Manager()->NotifyTabWillDestroy();
731 // If this fails, it's most likely due to a content-process crash, and
732 // auto-cleanup will kick in. Otherwise, the child side will destroy itself
733 // and send back __delete__().
737 Manager()->NotifyTabDestroying();
740 // This `AddKeepAlive` will be cleared if `mMarkedDestroying` is set in
741 // `ActorDestroy`. Out of caution, we don't add the `KeepAlive` if our IPC
742 // actor has somehow already been destroyed, as that would mean `ActorDestroy`
745 mBrowsingContext
->Group()->AddKeepAlive();
748 mMarkedDestroying
= true;
751 mozilla::ipc::IPCResult
BrowserParent::RecvDidUnsuppressPainting() {
752 if (!mFrameElement
) {
755 nsSubDocumentFrame
* subdocFrame
=
756 do_QueryFrame(mFrameElement
->GetPrimaryFrame());
757 if (subdocFrame
&& subdocFrame
->HasRetainedPaintData()) {
758 subdocFrame
->ClearRetainedPaintData();
763 mozilla::ipc::IPCResult
BrowserParent::RecvEnsureLayersConnected(
764 CompositorOptions
* aCompositorOptions
) {
765 if (mRemoteLayerTreeOwner
.IsInitialized()) {
766 mRemoteLayerTreeOwner
.EnsureLayersConnected(aCompositorOptions
);
771 void BrowserParent::ActorDestroy(ActorDestroyReason why
) {
772 Manager()->NotifyTabDestroyed(mTabId
, mMarkedDestroying
);
774 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
776 cpm
->UnregisterRemoteFrame(mTabId
);
779 if (mRemoteLayerTreeOwner
.IsInitialized()) {
780 auto layersId
= mRemoteLayerTreeOwner
.GetLayersId();
782 nsSubDocumentFrame
* f
= do_QueryFrame(mFrameElement
->GetPrimaryFrame());
783 if (f
&& f
->HasRetainedPaintData() &&
784 f
->GetRemotePaintData().mLayersId
== layersId
) {
785 f
->ClearRetainedPaintData();
789 // It's important to unmap layers after the remote browser has been
790 // destroyed, otherwise it may still send messages to the compositor which
791 // will reject them, causing assertions.
792 RemoveBrowserParentFromTable(layersId
);
793 mRemoteLayerTreeOwner
.Destroy();
796 // Even though BrowserParent::Destroy calls this, we need to do it here too in
800 if (why
== AbnormalShutdown
) {
801 // dom_reporting_header must also be enabled for the report to be sent.
802 if (StaticPrefs::dom_reporting_crash_enabled()) {
803 nsCOMPtr
<nsIPrincipal
> principal
= GetContentPrincipal();
806 nsAutoCString crash_reason
;
807 CrashReporter::GetAnnotation(OtherPid(),
808 CrashReporter::Annotation::MozCrashReason
,
810 // FIXME(arenevier): Find a less fragile way to identify that a crash
813 if (crash_reason
== "OOM" || crash_reason
== "OOM!" ||
814 StringBeginsWith(crash_reason
, "[unhandlable oom]"_ns
) ||
815 StringBeginsWith(crash_reason
, "Unhandlable OOM"_ns
)) {
819 CrashReport::Deliver(principal
, is_oom
);
824 // If we were shutting down normally, we held a reference to our
825 // BrowsingContextGroup in `BrowserParent::Destroy`. Clear that reference
827 if (mMarkedDestroying
) {
828 mBrowsingContext
->Group()->RemoveKeepAlive();
831 // Tell our embedder that the tab is now going away unless we're an
832 // out-of-process iframe.
833 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader(true);
835 ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE
, false, nullptr);
837 if (mBrowsingContext
->IsTop()) {
838 // If this is a top-level BrowsingContext, tell the frameloader it's time
839 // to go away. Otherwise, this is a subframe crash, and we can keep the
840 // frameloader around.
841 frameLoader
->DestroyComplete();
844 // If this was a crash, tell our nsFrameLoader to fire crash events.
845 if (why
== AbnormalShutdown
) {
846 frameLoader
->MaybeNotifyCrashed(mBrowsingContext
, Manager()->ChildID(),
848 } else if (why
== ManagedEndpointDropped
) {
849 // If we instead failed due to a constructor error, don't include process
850 // information, as the process did not crash.
851 frameLoader
->MaybeNotifyCrashed(mBrowsingContext
, ContentParentId
{},
856 mFrameLoader
= nullptr;
858 // If we were destroyed due to our ManagedEndpoints being dropped, make a
859 // point of showing the subframe crashed UI. We don't fire the full
860 // `MaybeNotifyCrashed` codepath, as the entire process hasn't crashed on us,
861 // and it may confuse the frontend.
862 mBrowsingContext
->BrowserParentDestroyed(
863 this, why
== AbnormalShutdown
|| why
== ManagedEndpointDropped
);
866 mozilla::ipc::IPCResult
BrowserParent::RecvMoveFocus(
867 const bool& aForward
, const bool& aForDocumentNavigation
) {
868 LOGBROWSERFOCUS(("RecvMoveFocus %p, aForward: %d, aForDocumentNavigation: %d",
869 this, aForward
, aForDocumentNavigation
));
870 BrowserBridgeParent
* bridgeParent
= GetBrowserBridgeParent();
872 mozilla::Unused
<< bridgeParent
->SendMoveFocus(aForward
,
873 aForDocumentNavigation
);
877 RefPtr
<nsFocusManager
> fm
= nsFocusManager::GetFocusManager();
879 RefPtr
<Element
> dummy
;
883 ? (aForDocumentNavigation
884 ? static_cast<uint32_t>(
885 nsIFocusManager::MOVEFOCUS_FORWARDDOC
)
886 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARD
))
887 : (aForDocumentNavigation
888 ? static_cast<uint32_t>(
889 nsIFocusManager::MOVEFOCUS_BACKWARDDOC
)
890 : static_cast<uint32_t>(
891 nsIFocusManager::MOVEFOCUS_BACKWARD
));
892 fm
->MoveFocus(nullptr, mFrameElement
, type
, nsIFocusManager::FLAG_BYKEY
,
893 getter_AddRefs(dummy
));
898 mozilla::ipc::IPCResult
BrowserParent::RecvDropLinks(
899 nsTArray
<nsString
>&& aLinks
) {
900 nsCOMPtr
<nsIBrowser
> browser
=
901 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
903 // Verify that links have not been modified by the child. If links have
904 // not been modified then it's safe to load those links using the
905 // SystemPrincipal. If they have been modified by web content, then
906 // we use a NullPrincipal which still allows to load web links.
907 bool loadUsingSystemPrincipal
= true;
908 if (aLinks
.Length() != mVerifyDropLinks
.Length()) {
909 loadUsingSystemPrincipal
= false;
911 for (uint32_t i
= 0; i
< aLinks
.Length(); i
++) {
912 if (loadUsingSystemPrincipal
) {
913 if (!aLinks
[i
].Equals(mVerifyDropLinks
[i
])) {
914 loadUsingSystemPrincipal
= false;
918 mVerifyDropLinks
.Clear();
919 nsCOMPtr
<nsIPrincipal
> triggeringPrincipal
;
920 if (loadUsingSystemPrincipal
) {
921 triggeringPrincipal
= nsContentUtils::GetSystemPrincipal();
923 triggeringPrincipal
= NullPrincipal::CreateWithoutOriginAttributes();
925 browser
->DropLinks(aLinks
, triggeringPrincipal
);
930 bool BrowserParent::SendLoadRemoteScript(const nsAString
& aURL
,
931 const bool& aRunInGlobalScope
) {
932 if (mCreatingWindow
) {
933 mDelayedFrameScripts
.AppendElement(
934 FrameScriptInfo(nsString(aURL
), aRunInGlobalScope
));
938 MOZ_ASSERT(mDelayedFrameScripts
.IsEmpty());
939 return PBrowserParent::SendLoadRemoteScript(aURL
, aRunInGlobalScope
);
942 void BrowserParent::LoadURL(nsDocShellLoadState
* aLoadState
) {
943 MOZ_ASSERT(aLoadState
);
944 MOZ_ASSERT(aLoadState
->URI());
949 if (mCreatingWindow
) {
950 // Don't send the message if the child wants to load its own URL.
954 Unused
<< SendLoadURL(WrapNotNull(aLoadState
), GetShowInfo());
957 void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID
) {
958 MOZ_ASSERT(aPendingSwitchID
!= 0);
960 if (NS_WARN_IF(mIsDestroyed
)) {
964 Unused
<< SendResumeLoad(aPendingSwitchID
, GetShowInfo());
967 void BrowserParent::InitRendering() {
968 if (mRemoteLayerTreeOwner
.IsInitialized()) {
971 mRemoteLayerTreeOwner
.Initialize(this);
973 layers::LayersId layersId
= mRemoteLayerTreeOwner
.GetLayersId();
974 AddBrowserParentToTable(layersId
, this);
976 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
978 nsIFrame
* frame
= frameLoader
->GetPrimaryFrameOfOwningContent();
980 frame
->InvalidateFrame();
984 TextureFactoryIdentifier textureFactoryIdentifier
;
985 mRemoteLayerTreeOwner
.GetTextureFactoryIdentifier(&textureFactoryIdentifier
);
986 Unused
<< SendInitRendering(textureFactoryIdentifier
, layersId
,
987 mRemoteLayerTreeOwner
.GetCompositorOptions(),
988 mRemoteLayerTreeOwner
.IsLayersConnected());
990 RefPtr
<nsIWidget
> widget
= GetTopLevelWidget();
992 ScreenIntMargin safeAreaInsets
= widget
->GetSafeAreaInsets();
993 Unused
<< SendSafeAreaInsetsChanged(safeAreaInsets
);
996 #if defined(MOZ_WIDGET_ANDROID)
999 if (GetBrowsingContext()->IsTopContent()) {
1000 Unused
<< SendDynamicToolbarMaxHeightChanged(
1001 widget
->GetDynamicToolbarMaxHeight());
1006 bool BrowserParent::AttachWindowRenderer() {
1007 return mRemoteLayerTreeOwner
.AttachWindowRenderer();
1010 void BrowserParent::MaybeShowFrame() {
1011 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
1015 frameLoader
->MaybeShowFrame();
1018 bool BrowserParent::Show(const OwnerShowInfo
& aOwnerInfo
) {
1019 mDimensions
= aOwnerInfo
.size();
1024 MOZ_ASSERT(mRemoteLayerTreeOwner
.IsInitialized());
1025 if (!mRemoteLayerTreeOwner
.AttachWindowRenderer()) {
1029 mSizeMode
= aOwnerInfo
.sizeMode();
1030 Unused
<< SendShow(GetShowInfo(), aOwnerInfo
);
1034 mozilla::ipc::IPCResult
BrowserParent::RecvSetDimensions(
1035 mozilla::DimensionRequest aRequest
, const double& aScale
) {
1036 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
1037 nsCOMPtr
<nsIDocShell
> docShell
= mFrameElement
->OwnerDoc()->GetDocShell();
1038 NS_ENSURE_TRUE(docShell
, IPC_OK());
1039 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
1040 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
1041 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
= do_QueryInterface(treeOwner
);
1042 NS_ENSURE_TRUE(treeOwnerAsWin
, IPC_OK());
1044 // `BrowserChild` only sends the values to actually be changed, see more
1045 // details in `BrowserChild::SetDimensions()`.
1046 // Note that `BrowserChild::SetDimensions()` may be called before receiving
1047 // our `SendUIResolutionChanged()` call. Therefore, if given each coordinate
1048 // shouldn't be ignored, we need to recompute it if DPI has been changed.
1049 // And also note that don't use `mDefaultScale.scale` here since it may be
1050 // different from the result of `GetWidgetCSSToDeviceScale()`.
1051 // NOTE(emilio): We use GetWidgetCSSToDeviceScale() because the old scale is a
1052 // widget scale, and we only use the current scale to scale up/down the
1055 CSSToLayoutDeviceScale
oldScale((float)aScale
);
1056 CSSToLayoutDeviceScale
currentScale(
1057 (float)treeOwnerAsWin
->GetWidgetCSSToDeviceScale());
1059 if (oldScale
!= currentScale
) {
1060 auto rescaleFunc
= [&oldScale
, ¤tScale
](LayoutDeviceIntCoord
& aVal
) {
1061 aVal
= (LayoutDeviceCoord(aVal
) / oldScale
* currentScale
).Rounded();
1063 aRequest
.mX
.apply(rescaleFunc
);
1064 aRequest
.mY
.apply(rescaleFunc
);
1065 aRequest
.mWidth
.apply(rescaleFunc
);
1066 aRequest
.mHeight
.apply(rescaleFunc
);
1069 // treeOwner is the chrome tree owner, but we wan't the content tree owner.
1070 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= do_GetInterface(treeOwner
);
1071 NS_ENSURE_TRUE(webBrowserChrome
, IPC_OK());
1072 webBrowserChrome
->SetDimensions(std::move(aRequest
));
1076 nsresult
BrowserParent::UpdatePosition() {
1077 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
1081 nsIntRect windowDims
;
1082 NS_ENSURE_SUCCESS(frameLoader
->GetWindowDimensions(windowDims
),
1084 // Avoid updating sizes here.
1085 windowDims
.SizeTo(mRect
.Size());
1086 UpdateDimensions(windowDims
, mDimensions
);
1090 void BrowserParent::NotifyPositionUpdatedForContentsInPopup() {
1091 if (CanonicalBrowsingContext
* bc
= GetBrowsingContext()) {
1092 bc
->PreOrderWalk([](BrowsingContext
* aContext
) {
1093 if (WindowGlobalParent
* windowGlobalParent
=
1094 aContext
->Canonical()->GetCurrentWindowGlobal()) {
1095 if (RefPtr
<BrowserParent
> browserParent
=
1096 windowGlobalParent
->GetBrowserParent()) {
1097 browserParent
->UpdatePosition();
1104 void BrowserParent::UpdateDimensions(const nsIntRect
& rect
,
1105 const ScreenIntSize
& size
) {
1109 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1111 NS_WARNING("No widget found in BrowserParent::UpdateDimensions");
1115 LayoutDeviceIntPoint clientOffset
= GetClientOffset();
1116 LayoutDeviceIntPoint chromeOffset
= !GetBrowserBridgeParent()
1117 ? -GetChildProcessOffset()
1118 : LayoutDeviceIntPoint();
1120 if (!mUpdatedDimensions
|| mDimensions
!= size
|| !mRect
.IsEqualEdges(rect
) ||
1121 clientOffset
!= mClientOffset
|| chromeOffset
!= mChromeOffset
) {
1122 mUpdatedDimensions
= true;
1125 mClientOffset
= clientOffset
;
1126 mChromeOffset
= chromeOffset
;
1128 Unused
<< SendUpdateDimensions(GetDimensionInfo());
1129 UpdateNativePointerLockCenter(widget
);
1133 DimensionInfo
BrowserParent::GetDimensionInfo() {
1134 LayoutDeviceIntRect devicePixelRect
= ViewAs
<LayoutDevicePixel
>(
1135 mRect
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
1136 LayoutDeviceIntSize devicePixelSize
= ViewAs
<LayoutDevicePixel
>(
1137 mDimensions
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
1139 CSSRect unscaledRect
= devicePixelRect
/ mDefaultScale
;
1140 CSSSize unscaledSize
= devicePixelSize
/ mDefaultScale
;
1141 DimensionInfo
di(unscaledRect
, unscaledSize
, mClientOffset
, mChromeOffset
);
1145 void BrowserParent::UpdateNativePointerLockCenter(nsIWidget
* aWidget
) {
1146 if (!mLockedNativePointer
) {
1149 LayoutDeviceIntRect
dims(
1151 ViewAs
<LayoutDevicePixel
>(
1152 mDimensions
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
));
1153 aWidget
->SetNativePointerLockCenter((dims
+ mChromeOffset
).Center());
1156 void BrowserParent::SizeModeChanged(const nsSizeMode
& aSizeMode
) {
1157 if (!mIsDestroyed
&& aSizeMode
!= mSizeMode
) {
1158 mSizeMode
= aSizeMode
;
1159 Unused
<< SendSizeModeChanged(aSizeMode
);
1163 #if defined(MOZ_WIDGET_ANDROID)
1164 void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight
) {
1165 if (!mIsDestroyed
) {
1166 Unused
<< SendDynamicToolbarMaxHeightChanged(aHeight
);
1170 void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset
) {
1171 if (!mIsDestroyed
) {
1172 Unused
<< SendDynamicToolbarOffsetChanged(aOffset
);
1177 void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent
& aEvent
,
1178 nsTArray
<uint32_t>& aCharCodes
) {
1179 if (!mIsDestroyed
) {
1180 // Note that we don't need to mark aEvent is posted to a remote process
1181 // because the event may be dispatched to it as normal keyboard event.
1182 // Therefore, we should use local copy to send it.
1183 WidgetKeyboardEvent
localEvent(aEvent
);
1184 RequestingAccessKeyEventData::Set(localEvent
);
1185 Unused
<< SendHandleAccessKey(localEvent
, aCharCodes
);
1189 void BrowserParent::Activate(uint64_t aActionId
) {
1190 LOGBROWSERFOCUS(("Activate %p actionid: %" PRIu64
, this, aActionId
));
1191 if (!mIsDestroyed
) {
1192 SetTopLevelWebFocus(this); // Intentionally inside "if"
1193 Unused
<< SendActivate(aActionId
);
1197 void BrowserParent::Deactivate(bool aWindowLowering
, uint64_t aActionId
) {
1198 LOGBROWSERFOCUS(("Deactivate %p actionid: %" PRIu64
, this, aActionId
));
1199 if (!aWindowLowering
) {
1200 UnsetTopLevelWebFocus(this); // Intentionally outside the next "if"
1202 if (!mIsDestroyed
) {
1203 Unused
<< SendDeactivate(aActionId
);
1207 #ifdef ACCESSIBILITY
1208 a11y::PDocAccessibleParent
* BrowserParent::AllocPDocAccessibleParent(
1209 PDocAccessibleParent
* aParent
, const uint64_t&,
1210 const MaybeDiscardedBrowsingContext
&) {
1211 // Reference freed in DeallocPDocAccessibleParent.
1212 return a11y::DocAccessibleParent::New().take();
1215 bool BrowserParent::DeallocPDocAccessibleParent(PDocAccessibleParent
* aParent
) {
1216 // Free reference from AllocPDocAccessibleParent.
1217 static_cast<a11y::DocAccessibleParent
*>(aParent
)->Release();
1221 mozilla::ipc::IPCResult
BrowserParent::RecvPDocAccessibleConstructor(
1222 PDocAccessibleParent
* aDoc
, PDocAccessibleParent
* aParentDoc
,
1223 const uint64_t& aParentID
,
1224 const MaybeDiscardedBrowsingContext
& aBrowsingContext
) {
1225 # if defined(ANDROID)
1226 MonitorAutoLock
mal(nsAccessibilityService::GetAndroidMonitor());
1228 auto doc
= static_cast<a11y::DocAccessibleParent
*>(aDoc
);
1230 // If this tab is already shutting down just mark the new actor as shutdown
1231 // and ignore it. When the tab actor is destroyed it will be too.
1233 doc
->MarkAsShutdown();
1238 // Iframe document rendered in the same process as its embedder.
1239 // A document should never directly be the parent of another document.
1240 // There should always be an outer doc accessible child of the outer
1241 // document containing the child.
1242 MOZ_ASSERT(aParentID
);
1244 return IPC_FAIL_NO_REASON(this);
1247 auto parentDoc
= static_cast<a11y::DocAccessibleParent
*>(aParentDoc
);
1248 if (parentDoc
->IsShutdown()) {
1249 // This can happen if parentDoc is an OOP iframe, but its embedder has
1250 // been destroyed. (DocAccessibleParent::Destroy destroys any child
1251 // documents.) The OOP iframe (and anything it embeds) will die soon
1252 // anyway, so mark this document as shutdown and ignore it.
1253 doc
->MarkAsShutdown();
1257 if (aBrowsingContext
) {
1258 doc
->SetBrowsingContext(aBrowsingContext
.get_canonical());
1261 mozilla::ipc::IPCResult added
= parentDoc
->AddChildDoc(doc
, aParentID
);
1271 if (a11y::nsWinUtils::IsWindowEmulationStarted()) {
1272 doc
->SetEmulatedWindowHandle(parentDoc
->GetEmulatedWindowHandle());
1279 if (aBrowsingContext
) {
1280 doc
->SetBrowsingContext(aBrowsingContext
.get_canonical());
1283 if (auto* bridge
= GetBrowserBridgeParent()) {
1284 // Iframe document rendered in a different process to its embedder.
1285 // In this case, we don't get aParentDoc and aParentID.
1286 MOZ_ASSERT(!aParentDoc
&& !aParentID
);
1287 doc
->SetTopLevelInContentProcess();
1288 a11y::ProxyCreated(doc
);
1289 // It's possible the embedder accessible hasn't been set yet; e.g.
1290 // a hidden iframe. In that case, embedderDoc will be null and this will
1291 // be handled when the embedder is set.
1292 if (a11y::DocAccessibleParent
* embedderDoc
=
1293 bridge
->GetEmbedderAccessibleDoc()) {
1294 mozilla::ipc::IPCResult added
= embedderDoc
->AddChildDoc(bridge
);
1305 // null aParentDoc means this document is at the top level in the child
1306 // process. That means it makes no sense to get an id for an accessible
1307 // that is its parent.
1308 MOZ_ASSERT(!aParentID
);
1310 return IPC_FAIL_NO_REASON(this);
1313 if (auto* prevTopLevel
= GetTopLevelDocAccessible()) {
1314 // Sometimes, we can get a new top level DocAccessibleParent before the
1315 // old one gets destroyed. The old one will die pretty shortly anyway,
1316 // so just destroy it now. If we don't do this, GetTopLevelDocAccessible()
1317 // might return the wrong document for a short while.
1318 prevTopLevel
->Destroy();
1321 a11y::DocManager::RemoteDocAdded(doc
);
1323 doc
->MaybeInitWindowEmulation();
1330 already_AddRefed
<PFilePickerParent
> BrowserParent::AllocPFilePickerParent(
1331 const nsString
& aTitle
, const nsIFilePicker::Mode
& aMode
) {
1332 return MakeAndAddRef
<FilePickerParent
>(aTitle
, aMode
);
1335 already_AddRefed
<PSessionStoreParent
>
1336 BrowserParent::AllocPSessionStoreParent() {
1337 RefPtr
<BrowserSessionStore
> sessionStore
=
1338 BrowserSessionStore::GetOrCreate(mBrowsingContext
->Top());
1339 if (!sessionStore
) {
1343 return do_AddRef(new SessionStoreParent(mBrowsingContext
, sessionStore
));
1346 IPCResult
BrowserParent::RecvNewWindowGlobal(
1347 ManagedEndpoint
<PWindowGlobalParent
>&& aEndpoint
,
1348 const WindowGlobalInit
& aInit
) {
1349 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
1350 CanonicalBrowsingContext::Get(aInit
.context().mBrowsingContextId
);
1351 if (!browsingContext
) {
1352 return IPC_FAIL(this, "Cannot create for missing BrowsingContext");
1354 if (!aInit
.principal()) {
1355 return IPC_FAIL(this, "Cannot create without valid principal");
1358 // Ensure we never load a document with a content principal in
1359 // the wrong type of webIsolated process
1360 EnumSet
<ContentParent::ValidatePrincipalOptions
> validationOptions
= {};
1361 nsCOMPtr
<nsIURI
> docURI
= aInit
.documentURI();
1362 if (docURI
->SchemeIs("about") || docURI
->SchemeIs("blob") ||
1363 docURI
->SchemeIs("chrome")) {
1364 // XXXckerschb TODO - Do not use SystemPrincipal for:
1365 // Bug 1700639: about:plugins
1366 // Bug 1699385: Remove allowSystem for blobs
1367 // Bug 1698087: chrome://devtools/content/shared/webextension-fallback.html
1368 // chrome reftests, e.g.
1369 // * chrome://reftest/content/writing-mode/ua-style-sheet-button-1a-ref.html
1370 // * chrome://reftest/content/xul-document-load/test003.xhtml
1371 // * chrome://reftest/content/forms/input/text/centering-1.xhtml
1372 validationOptions
= {ContentParent::ValidatePrincipalOptions::AllowSystem
};
1375 if (!mManager
->ValidatePrincipal(aInit
.principal(), validationOptions
)) {
1376 ContentParent::LogAndAssertFailedPrincipalValidationInfo(aInit
.principal(),
1380 // Construct our new WindowGlobalParent, bind, and initialize it.
1381 RefPtr
<WindowGlobalParent
> wgp
=
1382 WindowGlobalParent::CreateDisconnected(aInit
);
1383 BindPWindowGlobalEndpoint(std::move(aEndpoint
), wgp
);
1388 PVsyncParent
* BrowserParent::AllocPVsyncParent() {
1389 MOZ_ASSERT(!mVsyncParent
);
1390 mVsyncParent
= new VsyncParent();
1391 UpdateVsyncParentVsyncDispatcher();
1392 return mVsyncParent
.get();
1395 bool BrowserParent::DeallocPVsyncParent(PVsyncParent
* aActor
) {
1397 mVsyncParent
= nullptr;
1401 void BrowserParent::UpdateVsyncParentVsyncDispatcher() {
1402 if (!mVsyncParent
) {
1406 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
1407 RefPtr
<VsyncDispatcher
> vsyncDispatcher
= widget
->GetVsyncDispatcher();
1408 if (!vsyncDispatcher
) {
1409 vsyncDispatcher
= gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher();
1411 mVsyncParent
->UpdateVsyncDispatcher(vsyncDispatcher
);
1415 void BrowserParent::MouseEnterIntoWidget() {
1416 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
1417 // When we mouseenter the remote target, the remote target's cursor should
1418 // become the current cursor. When we mouseexit, we stop.
1419 mRemoteTargetSetsCursor
= true;
1420 widget
->SetCursor(mCursor
);
1423 // Mark that we have missed a mouse enter event, so that
1424 // the next mouse event will create a replacement mouse
1425 // enter event and send it to the child.
1426 mIsMouseEnterIntoWidgetEventSuppressed
= true;
1429 void BrowserParent::SendRealMouseEvent(WidgetMouseEvent
& aEvent
) {
1434 // XXXedgar, if the synthesized mouse events could deliver to the correct
1435 // process directly (see
1436 // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably don't
1437 // need to check mReason then.
1438 if (aEvent
.mReason
== WidgetMouseEvent::eReal
) {
1439 if (aEvent
.mMessage
== eMouseExitFromWidget
) {
1440 // Since we are leaving this remote target, so don't need to update
1441 // sLastMouseRemoteTarget, and if we are sLastMouseRemoteTarget, reset it
1443 BrowserParent::UnsetLastMouseRemoteTarget(this);
1445 // Last remote target should not be changed without eMouseExitFromWidget.
1446 MOZ_ASSERT_IF(sLastMouseRemoteTarget
, sLastMouseRemoteTarget
== this);
1447 sLastMouseRemoteTarget
= this;
1451 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1453 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1455 // When we mouseenter the remote target, the remote target's cursor should
1456 // become the current cursor. When we mouseexit, we stop.
1457 if (eMouseEnterIntoWidget
== aEvent
.mMessage
) {
1458 mRemoteTargetSetsCursor
= true;
1459 widget
->SetCursor(mCursor
);
1460 } else if (eMouseExitFromWidget
== aEvent
.mMessage
) {
1461 mRemoteTargetSetsCursor
= false;
1464 if (!mIsReadyToHandleInputEvents
) {
1465 if (eMouseEnterIntoWidget
== aEvent
.mMessage
) {
1466 mIsMouseEnterIntoWidgetEventSuppressed
= true;
1467 } else if (eMouseExitFromWidget
== aEvent
.mMessage
) {
1468 mIsMouseEnterIntoWidgetEventSuppressed
= false;
1473 ScrollableLayerGuid guid
;
1475 ApzAwareEventRoutingToChild(&guid
, &blockId
, nullptr);
1477 bool isInputPriorityEventEnabled
= Manager()->IsInputPriorityEventEnabled();
1479 if (mIsMouseEnterIntoWidgetEventSuppressed
) {
1480 // In the case that the BrowserParent suppressed the eMouseEnterWidget event
1481 // due to its corresponding BrowserChild wasn't ready to handle it, we have
1482 // to resend it when the BrowserChild is ready.
1483 mIsMouseEnterIntoWidgetEventSuppressed
= false;
1484 WidgetMouseEvent
localEvent(aEvent
);
1485 localEvent
.mMessage
= eMouseEnterIntoWidget
;
1486 DebugOnly
<bool> ret
=
1487 isInputPriorityEventEnabled
1488 ? SendRealMouseEnterExitWidgetEvent(localEvent
, guid
, blockId
)
1489 : SendNormalPriorityRealMouseEnterExitWidgetEvent(localEvent
, guid
,
1491 NS_WARNING_ASSERTION(ret
, "SendRealMouseEnterExitWidgetEvent() failed");
1492 MOZ_ASSERT(!ret
|| localEvent
.HasBeenPostedToRemoteProcess());
1495 if (eMouseMove
== aEvent
.mMessage
) {
1496 if (aEvent
.mReason
== WidgetMouseEvent::eSynthesized
) {
1497 DebugOnly
<bool> ret
=
1498 isInputPriorityEventEnabled
1499 ? SendSynthMouseMoveEvent(aEvent
, guid
, blockId
)
1500 : SendNormalPrioritySynthMouseMoveEvent(aEvent
, guid
, blockId
);
1501 NS_WARNING_ASSERTION(ret
, "SendSynthMouseMoveEvent() failed");
1502 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1506 if (!aEvent
.mFlags
.mIsSynthesizedForTests
) {
1507 DebugOnly
<bool> ret
=
1508 isInputPriorityEventEnabled
1509 ? SendRealMouseMoveEvent(aEvent
, guid
, blockId
)
1510 : SendNormalPriorityRealMouseMoveEvent(aEvent
, guid
, blockId
);
1511 NS_WARNING_ASSERTION(ret
, "SendRealMouseMoveEvent() failed");
1512 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1516 DebugOnly
<bool> ret
=
1517 isInputPriorityEventEnabled
1518 ? SendRealMouseMoveEventForTests(aEvent
, guid
, blockId
)
1519 : SendNormalPriorityRealMouseMoveEventForTests(aEvent
, guid
,
1521 NS_WARNING_ASSERTION(ret
, "SendRealMouseMoveEventForTests() failed");
1522 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1526 if (eMouseEnterIntoWidget
== aEvent
.mMessage
||
1527 eMouseExitFromWidget
== aEvent
.mMessage
) {
1528 DebugOnly
<bool> ret
=
1529 isInputPriorityEventEnabled
1530 ? SendRealMouseEnterExitWidgetEvent(aEvent
, guid
, blockId
)
1531 : SendNormalPriorityRealMouseEnterExitWidgetEvent(aEvent
, guid
,
1533 NS_WARNING_ASSERTION(ret
, "SendRealMouseEnterExitWidgetEvent() failed");
1534 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1538 DebugOnly
<bool> ret
=
1539 isInputPriorityEventEnabled
1540 ? SendRealMouseButtonEvent(aEvent
, guid
, blockId
)
1541 : SendNormalPriorityRealMouseButtonEvent(aEvent
, guid
, blockId
);
1542 NS_WARNING_ASSERTION(ret
, "SendRealMouseButtonEvent() failed");
1543 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1546 LayoutDeviceToCSSScale
BrowserParent::GetLayoutDeviceToCSSScale() {
1547 Document
* doc
= (mFrameElement
? mFrameElement
->OwnerDoc() : nullptr);
1548 nsPresContext
* ctx
= (doc
? doc
->GetPresContext() : nullptr);
1549 return LayoutDeviceToCSSScale(
1550 ctx
? (float)ctx
->AppUnitsPerDevPixel() / AppUnitsPerCSSPixel() : 0.0f
);
1553 bool BrowserParent::QueryDropLinksForVerification() {
1554 // Before sending the dragEvent, we query the links being dragged and
1555 // store them on the parent, to make sure the child can not modify links.
1556 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
1558 NS_WARNING("No dragSession to query links for verification");
1562 RefPtr
<DataTransfer
> initialDataTransfer
= dragSession
->GetDataTransfer();
1563 if (!initialDataTransfer
) {
1564 NS_WARNING("No initialDataTransfer to query links for verification");
1568 nsCOMPtr
<nsIDroppedLinkHandler
> dropHandler
=
1569 do_GetService("@mozilla.org/content/dropped-link-handler;1");
1571 NS_WARNING("No dropHandler to query links for verification");
1575 // No more than one drop event can happen simultaneously; reset the link
1576 // verification array and store all links that are being dragged.
1577 mVerifyDropLinks
.Clear();
1579 nsTArray
<RefPtr
<nsIDroppedLinkItem
>> droppedLinkItems
;
1580 dropHandler
->QueryLinks(initialDataTransfer
, droppedLinkItems
);
1582 // Since the entire event is cancelled if one of the links is invalid,
1583 // we can store all links on the parent side without any prior
1584 // validation checks.
1585 nsresult rv
= NS_OK
;
1586 for (nsIDroppedLinkItem
* item
: droppedLinkItems
) {
1588 rv
= item
->GetUrl(tmp
);
1589 if (NS_FAILED(rv
)) {
1590 NS_WARNING("Failed to query url for verification");
1593 mVerifyDropLinks
.AppendElement(tmp
);
1595 rv
= item
->GetName(tmp
);
1596 if (NS_FAILED(rv
)) {
1597 NS_WARNING("Failed to query name for verification");
1600 mVerifyDropLinks
.AppendElement(tmp
);
1602 rv
= item
->GetType(tmp
);
1603 if (NS_FAILED(rv
)) {
1604 NS_WARNING("Failed to query type for verification");
1607 mVerifyDropLinks
.AppendElement(tmp
);
1609 if (NS_FAILED(rv
)) {
1610 mVerifyDropLinks
.Clear();
1616 void BrowserParent::SendRealDragEvent(WidgetDragEvent
& aEvent
,
1617 uint32_t aDragAction
,
1618 uint32_t aDropEffect
,
1619 nsIPrincipal
* aPrincipal
,
1620 nsIContentSecurityPolicy
* aCsp
) {
1621 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1624 MOZ_ASSERT(!Manager()->IsInputPriorityEventEnabled());
1625 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1626 if (aEvent
.mMessage
== eDrop
) {
1627 if (!QueryDropLinksForVerification()) {
1631 DebugOnly
<bool> ret
= PBrowserParent::SendRealDragEvent(
1632 aEvent
, aDragAction
, aDropEffect
, aPrincipal
, aCsp
);
1633 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealDragEvent() failed");
1634 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1637 void BrowserParent::SendMouseWheelEvent(WidgetWheelEvent
& aEvent
) {
1638 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1642 ScrollableLayerGuid guid
;
1644 ApzAwareEventRoutingToChild(&guid
, &blockId
, nullptr);
1645 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1646 DebugOnly
<bool> ret
=
1647 Manager()->IsInputPriorityEventEnabled()
1648 ? PBrowserParent::SendMouseWheelEvent(aEvent
, guid
, blockId
)
1649 : PBrowserParent::SendNormalPriorityMouseWheelEvent(aEvent
, guid
,
1652 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendMouseWheelEvent() failed");
1653 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1656 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchWheelEvent(
1657 const mozilla::WidgetWheelEvent
& aEvent
) {
1658 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1660 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1665 WidgetWheelEvent
localEvent(aEvent
);
1666 localEvent
.mWidget
= widget
;
1667 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1669 widget
->DispatchInputEvent(&localEvent
);
1673 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchMouseEvent(
1674 const mozilla::WidgetMouseEvent
& aEvent
) {
1675 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1677 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1682 WidgetMouseEvent
localEvent(aEvent
);
1683 localEvent
.mWidget
= widget
;
1684 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1686 widget
->DispatchInputEvent(&localEvent
);
1690 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchKeyboardEvent(
1691 const mozilla::WidgetKeyboardEvent
& aEvent
) {
1692 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1694 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1699 WidgetKeyboardEvent
localEvent(aEvent
);
1700 localEvent
.mWidget
= widget
;
1701 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1703 widget
->DispatchInputEvent(&localEvent
);
1707 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchTouchEvent(
1708 const mozilla::WidgetTouchEvent
& aEvent
) {
1709 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1711 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1716 WidgetTouchEvent
localEvent(aEvent
);
1717 localEvent
.mWidget
= widget
;
1719 for (uint32_t i
= 0; i
< localEvent
.mTouches
.Length(); i
++) {
1720 localEvent
.mTouches
[i
]->mRefPoint
=
1721 TransformChildToParent(localEvent
.mTouches
[i
]->mRefPoint
);
1724 widget
->DispatchInputEvent(&localEvent
);
1728 mozilla::ipc::IPCResult
BrowserParent::RecvRequestNativeKeyBindings(
1729 const uint32_t& aType
, const WidgetKeyboardEvent
& aEvent
,
1730 nsTArray
<CommandInt
>* aCommands
) {
1731 MOZ_ASSERT(aCommands
);
1732 MOZ_ASSERT(aCommands
->IsEmpty());
1734 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1736 NativeKeyBindingsType keyBindingsType
=
1737 static_cast<NativeKeyBindingsType
>(aType
);
1738 switch (keyBindingsType
) {
1739 case NativeKeyBindingsType::SingleLineEditor
:
1740 case NativeKeyBindingsType::MultiLineEditor
:
1741 case NativeKeyBindingsType::RichTextEditor
:
1744 return IPC_FAIL(this, "Invalid aType value");
1747 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1752 WidgetKeyboardEvent
localEvent(aEvent
);
1753 localEvent
.mWidget
= widget
;
1755 if (NS_FAILED(widget
->AttachNativeKeyEvent(localEvent
))) {
1759 Maybe
<WritingMode
> writingMode
;
1760 if (RefPtr
<widget::TextEventDispatcher
> dispatcher
=
1761 widget
->GetTextEventDispatcher()) {
1762 writingMode
= dispatcher
->MaybeQueryWritingModeAtSelection();
1764 if (localEvent
.InitEditCommandsFor(keyBindingsType
, writingMode
)) {
1765 *aCommands
= localEvent
.EditCommandsConstRef(keyBindingsType
).Clone();
1771 class SynthesizedEventObserver
: public nsIObserver
{
1775 SynthesizedEventObserver(BrowserParent
* aBrowserParent
,
1776 const uint64_t& aObserverId
)
1777 : mBrowserParent(aBrowserParent
), mObserverId(aObserverId
) {
1778 MOZ_ASSERT(mBrowserParent
);
1781 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
,
1782 const char16_t
* aData
) override
{
1783 if (!mBrowserParent
|| !mObserverId
) {
1784 // We already sent the notification, or we don't actually need to
1785 // send any notification at all.
1789 if (mBrowserParent
->IsDestroyed()) {
1790 // If this happens it's probably a bug in the test that's triggering this.
1792 "BrowserParent was unexpectedly destroyed during event "
1794 } else if (!mBrowserParent
->SendNativeSynthesisResponse(
1795 mObserverId
, nsCString(aTopic
))) {
1796 NS_WARNING("Unable to send native event synthesization response!");
1798 // Null out browserParent to indicate we already sent the response
1799 mBrowserParent
= nullptr;
1804 virtual ~SynthesizedEventObserver() = default;
1806 RefPtr
<BrowserParent
> mBrowserParent
;
1807 uint64_t mObserverId
;
1810 NS_IMPL_ISUPPORTS(SynthesizedEventObserver
, nsIObserver
)
1812 class MOZ_STACK_CLASS AutoSynthesizedEventResponder
{
1814 AutoSynthesizedEventResponder(BrowserParent
* aBrowserParent
,
1815 const uint64_t& aObserverId
, const char* aTopic
)
1816 : mObserver(new SynthesizedEventObserver(aBrowserParent
, aObserverId
)),
1819 ~AutoSynthesizedEventResponder() {
1820 // This may be a no-op if the observer already sent a response.
1821 mObserver
->Observe(nullptr, mTopic
, nullptr);
1824 nsIObserver
* GetObserver() { return mObserver
; }
1827 nsCOMPtr
<nsIObserver
> mObserver
;
1831 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeKeyEvent(
1832 const int32_t& aNativeKeyboardLayout
, const int32_t& aNativeKeyCode
,
1833 const uint32_t& aModifierFlags
, const nsString
& aCharacters
,
1834 const nsString
& aUnmodifiedCharacters
, const uint64_t& aObserverId
) {
1835 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1837 AutoSynthesizedEventResponder
responder(this, aObserverId
, "keyevent");
1838 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1840 widget
->SynthesizeNativeKeyEvent(
1841 aNativeKeyboardLayout
, aNativeKeyCode
, aModifierFlags
, aCharacters
,
1842 aUnmodifiedCharacters
, responder
.GetObserver());
1847 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseEvent(
1848 const LayoutDeviceIntPoint
& aPoint
, const uint32_t& aNativeMessage
,
1849 const int16_t& aButton
, const uint32_t& aModifierFlags
,
1850 const uint64_t& aObserverId
) {
1851 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1853 const uint32_t last
=
1854 static_cast<uint32_t>(nsIWidget::NativeMouseMessage::LeaveWindow
);
1855 NS_ENSURE_TRUE(aNativeMessage
<= last
, IPC_FAIL(this, "Bogus message"));
1856 AutoSynthesizedEventResponder
responder(this, aObserverId
, "mouseevent");
1857 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1859 widget
->SynthesizeNativeMouseEvent(
1860 aPoint
, static_cast<nsIWidget::NativeMouseMessage
>(aNativeMessage
),
1861 static_cast<mozilla::MouseButton
>(aButton
),
1862 static_cast<nsIWidget::Modifiers
>(aModifierFlags
),
1863 responder
.GetObserver());
1868 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseMove(
1869 const LayoutDeviceIntPoint
& aPoint
, const uint64_t& aObserverId
) {
1870 // This is used by pointer lock API. So, even if it's not in the automation
1871 // mode, we need to accept the request.
1872 AutoSynthesizedEventResponder
responder(this, aObserverId
, "mousemove");
1873 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1875 widget
->SynthesizeNativeMouseMove(aPoint
, responder
.GetObserver());
1880 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseScrollEvent(
1881 const LayoutDeviceIntPoint
& aPoint
, const uint32_t& aNativeMessage
,
1882 const double& aDeltaX
, const double& aDeltaY
, const double& aDeltaZ
,
1883 const uint32_t& aModifierFlags
, const uint32_t& aAdditionalFlags
,
1884 const uint64_t& aObserverId
) {
1885 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1887 AutoSynthesizedEventResponder
responder(this, aObserverId
,
1888 "mousescrollevent");
1889 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1891 widget
->SynthesizeNativeMouseScrollEvent(
1892 aPoint
, aNativeMessage
, aDeltaX
, aDeltaY
, aDeltaZ
, aModifierFlags
,
1893 aAdditionalFlags
, responder
.GetObserver());
1898 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchPoint(
1899 const uint32_t& aPointerId
, const TouchPointerState
& aPointerState
,
1900 const LayoutDeviceIntPoint
& aPoint
, const double& aPointerPressure
,
1901 const uint32_t& aPointerOrientation
, const uint64_t& aObserverId
) {
1902 // This is used by DevTools to emulate touch events from mouse events in the
1903 // responsive design mode. Therefore, we should accept the IPC messages even
1904 // if it's not in the automation mode but the browsing context is in RDM pane.
1905 // And the IPC message could be just delayed after closing the responsive
1906 // design mode. Therefore, we shouldn't return IPC_FAIL since doing it makes
1908 if (!xpc::IsInAutomation()) {
1909 NS_ENSURE_TRUE(mBrowsingContext
, IPC_OK());
1910 NS_ENSURE_TRUE(mBrowsingContext
->Top()->GetInRDMPane(), IPC_OK());
1913 AutoSynthesizedEventResponder
responder(this, aObserverId
, "touchpoint");
1914 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1916 widget
->SynthesizeNativeTouchPoint(aPointerId
, aPointerState
, aPoint
,
1917 aPointerPressure
, aPointerOrientation
,
1918 responder
.GetObserver());
1923 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchPadPinch(
1924 const TouchpadGesturePhase
& aEventPhase
, const float& aScale
,
1925 const LayoutDeviceIntPoint
& aPoint
, const int32_t& aModifierFlags
) {
1926 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1928 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1930 widget
->SynthesizeNativeTouchPadPinch(aEventPhase
, aScale
, aPoint
,
1936 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchTap(
1937 const LayoutDeviceIntPoint
& aPoint
, const bool& aLongTap
,
1938 const uint64_t& aObserverId
) {
1939 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1941 AutoSynthesizedEventResponder
responder(this, aObserverId
, "touchtap");
1942 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1944 widget
->SynthesizeNativeTouchTap(aPoint
, aLongTap
, responder
.GetObserver());
1949 mozilla::ipc::IPCResult
BrowserParent::RecvClearNativeTouchSequence(
1950 const uint64_t& aObserverId
) {
1951 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1953 AutoSynthesizedEventResponder
responder(this, aObserverId
, "cleartouch");
1954 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1956 widget
->ClearNativeTouchSequence(responder
.GetObserver());
1961 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativePenInput(
1962 const uint32_t& aPointerId
, const TouchPointerState
& aPointerState
,
1963 const LayoutDeviceIntPoint
& aPoint
, const double& aPressure
,
1964 const uint32_t& aRotation
, const int32_t& aTiltX
, const int32_t& aTiltY
,
1965 const int32_t& aButton
, const uint64_t& aObserverId
) {
1966 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1968 AutoSynthesizedEventResponder
responder(this, aObserverId
, "peninput");
1969 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1971 widget
->SynthesizeNativePenInput(aPointerId
, aPointerState
, aPoint
,
1972 aPressure
, aRotation
, aTiltX
, aTiltY
,
1973 aButton
, responder
.GetObserver());
1978 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchpadDoubleTap(
1979 const LayoutDeviceIntPoint
& aPoint
, const uint32_t& aModifierFlags
) {
1980 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1982 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1984 widget
->SynthesizeNativeTouchpadDoubleTap(aPoint
, aModifierFlags
);
1989 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchpadPan(
1990 const TouchpadGesturePhase
& aEventPhase
, const LayoutDeviceIntPoint
& aPoint
,
1991 const double& aDeltaX
, const double& aDeltaY
, const int32_t& aModifierFlags
,
1992 const uint64_t& aObserverId
) {
1993 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event"));
1995 AutoSynthesizedEventResponder
responder(this, aObserverId
,
1996 "touchpadpanevent");
1998 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2000 widget
->SynthesizeNativeTouchpadPan(aEventPhase
, aPoint
, aDeltaX
, aDeltaY
,
2002 responder
.GetObserver());
2007 mozilla::ipc::IPCResult
BrowserParent::RecvLockNativePointer() {
2008 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
2009 mLockedNativePointer
= true; // do before updating the center
2010 UpdateNativePointerLockCenter(widget
);
2011 widget
->LockNativePointer();
2016 void BrowserParent::UnlockNativePointer() {
2017 if (!mLockedNativePointer
) {
2020 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
2021 widget
->UnlockNativePointer();
2022 mLockedNativePointer
= false;
2026 mozilla::ipc::IPCResult
BrowserParent::RecvUnlockNativePointer() {
2027 UnlockNativePointer();
2031 void BrowserParent::SendRealKeyEvent(WidgetKeyboardEvent
& aEvent
) {
2032 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
2035 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
2037 // NOTE: If you call `InitAllEditCommands()` for the other messages too,
2038 // you also need to update
2039 // TextEventDispatcher::DispatchKeyboardEventInternal().
2040 if (aEvent
.mMessage
== eKeyPress
) {
2041 // If current input context is editable, the edit commands are initialized
2042 // by TextEventDispatcher::DispatchKeyboardEventInternal(). Otherwise,
2043 // we need to do it here (they are not necessary for the parent process,
2044 // therefore, we need to do it here for saving the runtime cost).
2045 if (!aEvent
.AreAllEditCommandsInitialized()) {
2046 // XXX Is it good thing that the keypress event will be handled in an
2047 // editor even though the user pressed the key combination before the
2048 // focus change has not been completed in the parent process yet or
2049 // focus change will happen? If no, we can stop doing this.
2050 Maybe
<WritingMode
> writingMode
;
2051 if (aEvent
.mWidget
) {
2052 if (RefPtr
<widget::TextEventDispatcher
> dispatcher
=
2053 aEvent
.mWidget
->GetTextEventDispatcher()) {
2054 writingMode
= dispatcher
->MaybeQueryWritingModeAtSelection();
2057 aEvent
.InitAllEditCommands(writingMode
);
2060 aEvent
.PreventNativeKeyBindings();
2062 SentKeyEventData sendKeyEventData
{
2063 aEvent
.mKeyCode
, aEvent
.mCharCode
, aEvent
.mPseudoCharCode
,
2064 aEvent
.mKeyNameIndex
, aEvent
.mCodeNameIndex
, aEvent
.mModifiers
,
2065 nsID::GenerateUUID()};
2067 Manager()->IsInputPriorityEventEnabled()
2068 ? PBrowserParent::SendRealKeyEvent(aEvent
, sendKeyEventData
.mUUID
)
2069 : PBrowserParent::SendNormalPriorityRealKeyEvent(
2070 aEvent
, sendKeyEventData
.mUUID
);
2072 NS_WARNING_ASSERTION(ok
, "PBrowserParent::SendRealKeyEvent() failed");
2073 MOZ_ASSERT(!ok
|| aEvent
.HasBeenPostedToRemoteProcess());
2074 if (ok
&& aEvent
.IsWaitingReplyFromRemoteProcess()) {
2075 mWaitingReplyKeyboardEvents
.AppendElement(sendKeyEventData
);
2079 void BrowserParent::SendRealTouchEvent(WidgetTouchEvent
& aEvent
) {
2080 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
2084 // PresShell::HandleEventInternal adds touches on touch end/cancel. This
2085 // confuses remote content and the panning and zooming logic into thinking
2086 // that the added touches are part of the touchend/cancel, when actually
2088 if (aEvent
.mMessage
== eTouchEnd
|| aEvent
.mMessage
== eTouchCancel
) {
2089 aEvent
.mTouches
.RemoveElementsBy(
2090 [](const auto& touch
) { return !touch
->mChanged
; });
2094 ApzAwareEventRoutingToChild(&apzData
.guid
, &apzData
.blockId
,
2095 &apzData
.apzResponse
);
2101 for (uint32_t i
= 0; i
< aEvent
.mTouches
.Length(); i
++) {
2102 aEvent
.mTouches
[i
]->mRefPoint
=
2103 TransformParentToChild(aEvent
.mTouches
[i
]->mRefPoint
);
2106 static uint32_t sConsecutiveTouchMoveCount
= 0;
2107 if (aEvent
.mMessage
== eTouchMove
) {
2108 ++sConsecutiveTouchMoveCount
;
2109 SendRealTouchMoveEvent(aEvent
, apzData
, sConsecutiveTouchMoveCount
);
2113 sConsecutiveTouchMoveCount
= 0;
2114 DebugOnly
<bool> ret
=
2115 Manager()->IsInputPriorityEventEnabled()
2116 ? PBrowserParent::SendRealTouchEvent(
2117 aEvent
, apzData
.guid
, apzData
.blockId
, apzData
.apzResponse
)
2118 : PBrowserParent::SendNormalPriorityRealTouchEvent(
2119 aEvent
, apzData
.guid
, apzData
.blockId
, apzData
.apzResponse
);
2121 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealTouchEvent() failed");
2122 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
2125 void BrowserParent::SendRealTouchMoveEvent(
2126 WidgetTouchEvent
& aEvent
, APZData
& aAPZData
,
2127 uint32_t aConsecutiveTouchMoveCount
) {
2128 // Touchmove handling is complicated, since IPC compression should be used
2129 // only when there are consecutive touch objects for the same touch on the
2130 // same BrowserParent. IPC compression can be disabled by switching to
2131 // different IPC message.
2132 static bool sIPCMessageType1
= true;
2133 static TabId
sLastTargetBrowserParent(0);
2134 static Maybe
<APZData
> sPreviousAPZData
;
2135 // Artificially limit max touch points to 10. That should be in practise
2136 // more than enough.
2137 const uint32_t kMaxTouchMoveIdentifiers
= 10;
2138 static Maybe
<int32_t> sLastTouchMoveIdentifiers
[kMaxTouchMoveIdentifiers
];
2140 // Returns true if aIdentifiers contains all the touches in
2141 // sLastTouchMoveIdentifiers.
2142 auto LastTouchMoveIdentifiersContainedIn
=
2143 [&](const nsTArray
<int32_t>& aIdentifiers
) -> bool {
2144 for (Maybe
<int32_t>& entry
: sLastTouchMoveIdentifiers
) {
2145 if (entry
.isSome() && !aIdentifiers
.Contains(entry
.value())) {
2152 // Cache touch identifiers in sLastTouchMoveIdentifiers array to be used
2153 // when checking whether compression can be done for the next touchmove.
2154 auto SetLastTouchMoveIdentifiers
=
2155 [&](const nsTArray
<int32_t>& aIdentifiers
) {
2156 for (Maybe
<int32_t>& entry
: sLastTouchMoveIdentifiers
) {
2160 MOZ_ASSERT(aIdentifiers
.Length() <= kMaxTouchMoveIdentifiers
);
2161 for (uint32_t j
= 0; j
< aIdentifiers
.Length(); ++j
) {
2162 sLastTouchMoveIdentifiers
[j
].emplace(aIdentifiers
[j
]);
2166 AutoTArray
<int32_t, kMaxTouchMoveIdentifiers
> changedTouches
;
2167 bool preventCompression
= !StaticPrefs::dom_events_compress_touchmove() ||
2168 // Ensure the very first touchmove isn't overridden
2169 // by the second one, so that web pages can get
2170 // accurate coordinates for the first touchmove.
2171 aConsecutiveTouchMoveCount
< 3 ||
2172 sPreviousAPZData
.isNothing() ||
2173 sPreviousAPZData
.value() != aAPZData
||
2174 sLastTargetBrowserParent
!= GetTabId() ||
2175 aEvent
.mTouches
.Length() > kMaxTouchMoveIdentifiers
;
2177 if (!preventCompression
) {
2178 for (RefPtr
<Touch
>& touch
: aEvent
.mTouches
) {
2179 if (touch
->mChanged
) {
2180 changedTouches
.AppendElement(touch
->mIdentifier
);
2184 // Prevent compression if the new event has fewer or different touches
2185 // than the old one.
2186 preventCompression
= !LastTouchMoveIdentifiersContainedIn(changedTouches
);
2189 if (preventCompression
) {
2190 sIPCMessageType1
= !sIPCMessageType1
;
2193 // Update the last touch move identifiers always, so that when the next
2194 // event comes in, the new identifiers can be compared to the old ones.
2195 // If the pref is disabled, this just does a quick small loop.
2196 SetLastTouchMoveIdentifiers(changedTouches
);
2197 sPreviousAPZData
.reset();
2198 sPreviousAPZData
.emplace(aAPZData
);
2199 sLastTargetBrowserParent
= GetTabId();
2201 DebugOnly
<bool> ret
= true;
2202 if (sIPCMessageType1
) {
2204 Manager()->IsInputPriorityEventEnabled()
2205 ? PBrowserParent::SendRealTouchMoveEvent(
2206 aEvent
, aAPZData
.guid
, aAPZData
.blockId
, aAPZData
.apzResponse
)
2207 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent(
2208 aEvent
, aAPZData
.guid
, aAPZData
.blockId
,
2209 aAPZData
.apzResponse
);
2212 Manager()->IsInputPriorityEventEnabled()
2213 ? PBrowserParent::SendRealTouchMoveEvent2(
2214 aEvent
, aAPZData
.guid
, aAPZData
.blockId
, aAPZData
.apzResponse
)
2215 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent2(
2216 aEvent
, aAPZData
.guid
, aAPZData
.blockId
,
2217 aAPZData
.apzResponse
);
2220 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealTouchMoveEvent() failed");
2221 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
2224 bool BrowserParent::SendHandleTap(TapType aType
,
2225 const LayoutDevicePoint
& aPoint
,
2226 Modifiers aModifiers
,
2227 const ScrollableLayerGuid
& aGuid
,
2228 uint64_t aInputBlockId
) {
2229 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
2232 if ((aType
== TapType::eSingleTap
|| aType
== TapType::eSecondTap
)) {
2233 if (RefPtr
<nsFocusManager
> fm
= nsFocusManager::GetFocusManager()) {
2234 if (RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader()) {
2235 if (RefPtr
<Element
> element
= frameLoader
->GetOwnerContent()) {
2236 fm
->SetFocus(element
, nsIFocusManager::FLAG_BYMOUSE
|
2237 nsIFocusManager::FLAG_BYTOUCH
|
2238 nsIFocusManager::FLAG_NOSCROLL
);
2243 return Manager()->IsInputPriorityEventEnabled()
2244 ? PBrowserParent::SendHandleTap(aType
,
2245 TransformParentToChild(aPoint
),
2246 aModifiers
, aGuid
, aInputBlockId
)
2247 : PBrowserParent::SendNormalPriorityHandleTap(
2248 aType
, TransformParentToChild(aPoint
), aModifiers
, aGuid
,
2252 mozilla::ipc::IPCResult
BrowserParent::RecvSyncMessage(
2253 const nsString
& aMessage
, const ClonedMessageData
& aData
,
2254 nsTArray
<StructuredCloneData
>* aRetVal
) {
2255 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvSyncMessage",
2257 MMPrinter::Print("BrowserParent::RecvSyncMessage", aMessage
, aData
);
2259 StructuredCloneData data
;
2260 ipc::UnpackClonedMessageData(aData
, data
);
2262 if (!ReceiveMessage(aMessage
, true, &data
, aRetVal
)) {
2263 return IPC_FAIL_NO_REASON(this);
2268 mozilla::ipc::IPCResult
BrowserParent::RecvAsyncMessage(
2269 const nsString
& aMessage
, const ClonedMessageData
& aData
) {
2270 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvAsyncMessage",
2272 MMPrinter::Print("BrowserParent::RecvAsyncMessage", aMessage
, aData
);
2274 StructuredCloneData data
;
2275 ipc::UnpackClonedMessageData(aData
, data
);
2277 if (!ReceiveMessage(aMessage
, false, &data
, nullptr)) {
2278 return IPC_FAIL_NO_REASON(this);
2283 mozilla::ipc::IPCResult
BrowserParent::RecvSetCursor(
2284 const nsCursor
& aCursor
, const bool& aHasCustomCursor
,
2285 Maybe
<BigBuffer
>&& aCursorData
, const uint32_t& aWidth
,
2286 const uint32_t& aHeight
, const float& aResolutionX
,
2287 const float& aResolutionY
, const uint32_t& aStride
,
2288 const gfx::SurfaceFormat
& aFormat
, const uint32_t& aHotspotX
,
2289 const uint32_t& aHotspotY
, const bool& aForce
) {
2290 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2296 widget
->ClearCachedCursor();
2299 nsCOMPtr
<imgIContainer
> cursorImage
;
2300 if (aHasCustomCursor
) {
2301 const bool cursorDataValid
= [&] {
2305 auto expectedSize
= CheckedInt
<uint32_t>(aHeight
) * aStride
;
2306 if (!expectedSize
.isValid() ||
2307 expectedSize
.value() != aCursorData
->Size()) {
2311 CheckedInt
<uint32_t>(aWidth
) * gfx::BytesPerPixel(aFormat
);
2312 if (!minStride
.isValid() || aStride
< minStride
.value()) {
2317 if (!cursorDataValid
) {
2318 return IPC_FAIL(this, "Invalid custom cursor data");
2320 const gfx::IntSize
size(aWidth
, aHeight
);
2321 RefPtr
<gfx::DataSourceSurface
> customCursor
=
2322 gfx::CreateDataSourceSurfaceFromData(size
, aFormat
, aCursorData
->Data(),
2325 RefPtr
<gfxDrawable
> drawable
= new gfxSurfaceDrawable(customCursor
, size
);
2326 cursorImage
= image::ImageOps::CreateFromDrawable(drawable
);
2329 mCursor
= nsIWidget::Cursor
{aCursor
,
2330 std::move(cursorImage
),
2333 {aResolutionX
, aResolutionY
}};
2334 if (!mRemoteTargetSetsCursor
) {
2338 widget
->SetCursor(mCursor
);
2342 mozilla::ipc::IPCResult
BrowserParent::RecvSetLinkStatus(
2343 const nsString
& aStatus
) {
2344 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2345 if (!xulBrowserWindow
) {
2349 xulBrowserWindow
->SetOverLink(aStatus
);
2354 mozilla::ipc::IPCResult
BrowserParent::RecvShowTooltip(
2355 const uint32_t& aX
, const uint32_t& aY
, const nsString
& aTooltip
,
2356 const nsString
& aDirection
) {
2357 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2358 if (!xulBrowserWindow
) {
2362 // ShowTooltip will end up accessing XULElement properties in JS (specifically
2363 // BoxObject). However, to get it to JS, we need to make sure we're a
2364 // nsFrameLoaderOwner, which implies we're a XULFrameElement. We can then
2365 // safely pass Element into JS.
2366 RefPtr
<nsFrameLoaderOwner
> flo
= do_QueryObject(mFrameElement
);
2367 if (!flo
) return IPC_OK();
2369 nsCOMPtr
<Element
> el
= do_QueryInterface(flo
);
2370 if (!el
) return IPC_OK();
2373 xulBrowserWindow
->ShowTooltip(aX
, aY
, aTooltip
, aDirection
, el
))) {
2374 mShowingTooltip
= true;
2379 mozilla::ipc::IPCResult
BrowserParent::RecvHideTooltip() {
2380 mShowingTooltip
= false;
2382 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2383 if (!xulBrowserWindow
) {
2387 xulBrowserWindow
->HideTooltip();
2391 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEFocus(
2392 const ContentCache
& aContentCache
, const IMENotification
& aIMENotification
,
2393 NotifyIMEFocusResolver
&& aResolve
) {
2398 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2400 aResolve(IMENotificationRequests());
2403 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2404 return IPC_FAIL(this, "Invalid content cache data");
2406 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2407 IMEStateManager::NotifyIME(aIMENotification
, widget
, this);
2409 IMENotificationRequests requests
;
2410 if (aIMENotification
.mMessage
== NOTIFY_IME_OF_FOCUS
) {
2411 requests
= widget
->IMENotificationRequestsRef();
2418 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMETextChange(
2419 const ContentCache
& aContentCache
,
2420 const IMENotification
& aIMENotification
) {
2421 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2422 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2425 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2426 return IPC_FAIL(this, "Invalid content cache data");
2428 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2429 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2433 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMECompositionUpdate(
2434 const ContentCache
& aContentCache
,
2435 const IMENotification
& aIMENotification
) {
2436 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2437 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2440 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2441 return IPC_FAIL(this, "Invalid content cache data");
2443 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2444 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2448 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMESelection(
2449 const ContentCache
& aContentCache
,
2450 const IMENotification
& aIMENotification
) {
2451 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2452 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2455 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2456 return IPC_FAIL(this, "Invalid content cache data");
2458 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2459 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2463 mozilla::ipc::IPCResult
BrowserParent::RecvUpdateContentCache(
2464 const ContentCache
& aContentCache
) {
2465 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2466 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2469 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2470 return IPC_FAIL(this, "Invalid content cache data");
2472 mContentCache
.AssignContent(aContentCache
, widget
);
2476 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEMouseButtonEvent(
2477 const IMENotification
& aIMENotification
, bool* aConsumedByIME
) {
2478 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2479 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2480 *aConsumedByIME
= false;
2483 nsresult rv
= IMEStateManager::NotifyIME(aIMENotification
, widget
, this);
2484 *aConsumedByIME
= rv
== NS_SUCCESS_EVENT_CONSUMED
;
2488 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEPositionChange(
2489 const ContentCache
& aContentCache
,
2490 const IMENotification
& aIMENotification
) {
2491 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2492 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2495 if (NS_WARN_IF(!aContentCache
.IsValid())) {
2496 return IPC_FAIL(this, "Invalid content cache data");
2498 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2499 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2503 mozilla::ipc::IPCResult
BrowserParent::RecvOnEventNeedingAckHandled(
2504 const EventMessage
& aMessage
, const uint32_t& aCompositionId
) {
2505 // This is called when the child process receives WidgetCompositionEvent or
2506 // WidgetSelectionEvent.
2507 // FYI: Don't check if widget is nullptr here because it's more important to
2508 // notify mContentCahce of this than handling something in it.
2509 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2511 // While calling OnEventNeedingAckHandled(), BrowserParent *might* be
2512 // destroyed since it may send notifications to IME.
2513 RefPtr
<BrowserParent
> kungFuDeathGrip(this);
2514 mContentCache
.OnEventNeedingAckHandled(widget
, aMessage
, aCompositionId
);
2518 mozilla::ipc::IPCResult
BrowserParent::RecvRequestFocus(
2519 const bool& aCanRaise
, const CallerType aCallerType
) {
2520 LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise
));
2521 if (BrowserBridgeParent
* bridgeParent
= GetBrowserBridgeParent()) {
2522 mozilla::Unused
<< bridgeParent
->SendRequestFocus(aCanRaise
, aCallerType
);
2526 if (!mFrameElement
) {
2530 nsContentUtils::RequestFrameFocus(*mFrameElement
, aCanRaise
, aCallerType
);
2534 mozilla::ipc::IPCResult
BrowserParent::RecvWheelZoomChange(bool aIncrease
) {
2535 RefPtr
<BrowsingContext
> bc
= GetBrowsingContext();
2540 bc
->Canonical()->DispatchWheelZoomChange(aIncrease
);
2544 mozilla::ipc::IPCResult
BrowserParent::RecvEnableDisableCommands(
2545 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsString
& aAction
,
2546 nsTArray
<nsCString
>&& aEnabledCommands
,
2547 nsTArray
<nsCString
>&& aDisabledCommands
) {
2548 if (aContext
.IsNullOrDiscarded()) {
2552 nsCOMPtr
<nsIBrowserController
> browserController
= do_QueryActor(
2553 "Controllers", aContext
.get_canonical()->GetCurrentWindowGlobal());
2554 if (browserController
) {
2555 browserController
->EnableDisableCommands(aAction
, aEnabledCommands
,
2562 LayoutDeviceIntPoint
BrowserParent::TransformPoint(
2563 const LayoutDeviceIntPoint
& aPoint
,
2564 const LayoutDeviceToLayoutDeviceMatrix4x4
& aMatrix
) {
2565 LayoutDevicePoint
floatPoint(aPoint
);
2566 LayoutDevicePoint floatTransformed
= TransformPoint(floatPoint
, aMatrix
);
2567 // The next line loses precision if an out-of-process iframe
2568 // has been scaled or rotated.
2569 return RoundedToInt(floatTransformed
);
2572 LayoutDevicePoint
BrowserParent::TransformPoint(
2573 const LayoutDevicePoint
& aPoint
,
2574 const LayoutDeviceToLayoutDeviceMatrix4x4
& aMatrix
) {
2575 return aMatrix
.TransformPoint(aPoint
);
2578 LayoutDeviceIntPoint
BrowserParent::TransformParentToChild(
2579 const LayoutDeviceIntPoint
& aPoint
) {
2580 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2581 GetChildToParentConversionMatrix();
2582 if (!matrix
.Invert()) {
2583 return LayoutDeviceIntPoint();
2585 auto transformed
= UntransformBy(matrix
, aPoint
);
2587 return LayoutDeviceIntPoint();
2589 return transformed
.ref();
2592 LayoutDevicePoint
BrowserParent::TransformParentToChild(
2593 const LayoutDevicePoint
& aPoint
) {
2594 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2595 GetChildToParentConversionMatrix();
2596 if (!matrix
.Invert()) {
2597 return LayoutDevicePoint();
2599 auto transformed
= UntransformBy(matrix
, aPoint
);
2601 return LayoutDeviceIntPoint();
2603 return transformed
.ref();
2606 LayoutDeviceIntPoint
BrowserParent::TransformChildToParent(
2607 const LayoutDeviceIntPoint
& aPoint
) {
2608 return TransformPoint(aPoint
, GetChildToParentConversionMatrix());
2611 LayoutDevicePoint
BrowserParent::TransformChildToParent(
2612 const LayoutDevicePoint
& aPoint
) {
2613 return TransformPoint(aPoint
, GetChildToParentConversionMatrix());
2616 LayoutDeviceIntRect
BrowserParent::TransformChildToParent(
2617 const LayoutDeviceIntRect
& aRect
) {
2618 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2619 GetChildToParentConversionMatrix();
2620 LayoutDeviceRect
floatRect(aRect
);
2621 // The outcome is not ideal if an out-of-process iframe has been rotated
2622 LayoutDeviceRect floatTransformed
= matrix
.TransformBounds(floatRect
);
2623 // The next line loses precision if an out-of-process iframe
2624 // has been scaled or rotated.
2625 return RoundedToInt(floatTransformed
);
2628 LayoutDeviceToLayoutDeviceMatrix4x4
2629 BrowserParent::GetChildToParentConversionMatrix() {
2630 if (mChildToParentConversionMatrix
) {
2631 return *mChildToParentConversionMatrix
;
2633 LayoutDevicePoint
offset(-GetChildProcessOffset());
2634 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset
);
2637 void BrowserParent::SetChildToParentConversionMatrix(
2638 const Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
>& aMatrix
,
2639 const ScreenRect
& aRemoteDocumentRect
) {
2640 if (mChildToParentConversionMatrix
== aMatrix
&&
2641 mRemoteDocumentRect
.isSome() &&
2642 mRemoteDocumentRect
.value() == aRemoteDocumentRect
) {
2646 mChildToParentConversionMatrix
= aMatrix
;
2647 mRemoteDocumentRect
= Some(aRemoteDocumentRect
);
2651 mozilla::Unused
<< SendChildToParentMatrix(ToUnknownMatrix(aMatrix
),
2652 aRemoteDocumentRect
);
2655 LayoutDeviceIntPoint
BrowserParent::GetChildProcessOffset() {
2656 // The "toplevel widget" in child processes is always at position
2657 // 0,0. Map the event coordinates to match that.
2659 LayoutDeviceIntPoint
offset(0, 0);
2660 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
2664 nsIFrame
* targetFrame
= frameLoader
->GetPrimaryFrameOfOwningContent();
2669 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2674 nsPresContext
* presContext
= targetFrame
->PresContext();
2675 nsIFrame
* rootFrame
= presContext
->PresShell()->GetRootFrame();
2676 nsView
* rootView
= rootFrame
? rootFrame
->GetView() : nullptr;
2681 // Note that we don't want to take into account transforms here:
2684 nsLayoutUtils::TransformPoint(targetFrame
, rootFrame
, pt
);
2686 // In practice, when transforms are applied to this frameLoader, we currently
2687 // get the wrong results whether we take transforms into account here or not.
2688 // But applying transforms here gives us the wrong results in all
2689 // circumstances when transforms are applied, unless they're purely
2690 // translational. It also gives us the wrong results whenever CSS transitions
2691 // are used to apply transforms, since the offeets aren't updated as the
2692 // transition is animated.
2694 // What we actually need to do is apply the transforms to the coordinates of
2695 // any events we send to the child, and reverse them for any screen
2696 // coordinates that we retrieve from the child.
2698 // TODO: Once we take into account transforms here, set viewportType
2699 // correctly. For now we use Visual as this means we don't apply
2700 // the layout-to-visual transform in TranslateViewToWidget().
2701 ViewportType viewportType
= ViewportType::Visual
;
2703 nsPoint pt
= targetFrame
->GetOffsetTo(rootFrame
);
2704 return -nsLayoutUtils::TranslateViewToWidget(presContext
, rootView
, pt
,
2705 viewportType
, widget
);
2708 LayoutDeviceIntPoint
BrowserParent::GetClientOffset() {
2709 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2710 nsCOMPtr
<nsIWidget
> docWidget
= GetDocWidget();
2712 if (widget
== docWidget
) {
2713 return widget
->GetClientOffset();
2716 return (docWidget
->GetClientOffset() +
2717 nsLayoutUtils::WidgetToWidgetOffset(widget
, docWidget
));
2720 void BrowserParent::StopIMEStateManagement() {
2724 Unused
<< SendStopIMEStateManagement();
2727 mozilla::ipc::IPCResult
BrowserParent::RecvReplyKeyEvent(
2728 const WidgetKeyboardEvent
& aEvent
, const nsID
& aUUID
) {
2729 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
2731 // First, verify aEvent is what we've sent to a remote process.
2732 Maybe
<size_t> index
= [&]() -> Maybe
<size_t> {
2733 for (const size_t i
: IntegerRange(mWaitingReplyKeyboardEvents
.Length())) {
2734 const SentKeyEventData
& data
= mWaitingReplyKeyboardEvents
[i
];
2735 if (data
.mUUID
.Equals(aUUID
)) {
2736 if (NS_WARN_IF(data
.mKeyCode
!= aEvent
.mKeyCode
) ||
2737 NS_WARN_IF(data
.mCharCode
!= aEvent
.mCharCode
) ||
2738 NS_WARN_IF(data
.mPseudoCharCode
!= aEvent
.mPseudoCharCode
) ||
2739 NS_WARN_IF(data
.mKeyNameIndex
!= aEvent
.mKeyNameIndex
) ||
2740 NS_WARN_IF(data
.mCodeNameIndex
!= aEvent
.mCodeNameIndex
) ||
2741 NS_WARN_IF(data
.mModifiers
!= aEvent
.mModifiers
)) {
2742 // Got different event data from what we stored before dispatching an
2743 // event with the ID.
2752 if (MOZ_UNLIKELY(index
.isNothing())) {
2753 return IPC_FAIL(this, "Bogus reply keyboard event");
2755 // Don't discard the older keyboard events because the order may be changed if
2756 // the remote process has a event listener which takes too long time and while
2757 // the freezing, user may switch the tab, or if the remote process sends
2758 // synchronous XMLHttpRequest.
2759 mWaitingReplyKeyboardEvents
.RemoveElementAt(*index
);
2761 // If the event propagation was stopped by the child, it means that the event
2762 // was ignored in the child. In the case, we should ignore it too because the
2763 // focused web app didn't have a chance to prevent its default.
2764 if (aEvent
.PropagationStopped()) {
2768 WidgetKeyboardEvent
localEvent(aEvent
);
2769 localEvent
.MarkAsHandledInRemoteProcess();
2771 // Here we convert the WidgetEvent that we received to an Event
2772 // to be able to dispatch it to the <browser> element as the target element.
2773 RefPtr
<nsPresContext
> presContext
=
2774 mFrameElement
->OwnerDoc()->GetPresContext();
2775 NS_ENSURE_TRUE(presContext
, IPC_OK());
2777 AutoHandlingUserInputStatePusher
userInpStatePusher(localEvent
.IsTrusted(),
2780 nsEventStatus status
= nsEventStatus_eIgnore
;
2782 // Handle access key in this process before dispatching reply event because
2783 // ESM handles it before dispatching the event to the DOM tree.
2784 if (localEvent
.mMessage
== eKeyPress
&&
2785 (localEvent
.ModifiersMatchWithAccessKey(AccessKeyType::eChrome
) ||
2786 localEvent
.ModifiersMatchWithAccessKey(AccessKeyType::eContent
))) {
2787 RefPtr
<EventStateManager
> esm
= presContext
->EventStateManager();
2788 AutoTArray
<uint32_t, 10> accessCharCodes
;
2789 localEvent
.GetAccessKeyCandidates(accessCharCodes
);
2790 if (esm
->HandleAccessKey(&localEvent
, presContext
, accessCharCodes
)) {
2791 status
= nsEventStatus_eConsumeNoDefault
;
2795 RefPtr
<Element
> frameElement
= mFrameElement
;
2796 EventDispatcher::Dispatch(frameElement
, presContext
, &localEvent
, nullptr,
2799 if (!localEvent
.DefaultPrevented() &&
2800 !localEvent
.mFlags
.mIsSynthesizedForTests
) {
2801 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2803 widget
->PostHandleKeyEvent(&localEvent
);
2804 localEvent
.StopPropagation();
2811 mozilla::ipc::IPCResult
BrowserParent::RecvAccessKeyNotHandled(
2812 const WidgetKeyboardEvent
& aEvent
) {
2813 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
2815 // This is called only when this process had focus and HandleAccessKey
2816 // message was posted to all remote process and each remote process didn't
2817 // execute any content access keys.
2819 if (MOZ_UNLIKELY(aEvent
.mMessage
!= eKeyPress
|| !aEvent
.IsTrusted())) {
2820 return IPC_FAIL(this, "Called with unexpected event");
2823 // If there is no requesting event, the event may have already been handled
2824 // when it's returned from another remote process.
2825 if (MOZ_UNLIKELY(!RequestingAccessKeyEventData::IsSet())) {
2829 // If the event does not match with the one which we requested a remote
2830 // process to handle access key of (that means that we has already requested
2831 // for another key press), we should ignore this call because user focuses
2832 // to the last key press.
2833 if (MOZ_UNLIKELY(!RequestingAccessKeyEventData::Equals(aEvent
))) {
2837 RequestingAccessKeyEventData::Clear();
2839 WidgetKeyboardEvent
localEvent(aEvent
);
2840 localEvent
.MarkAsHandledInRemoteProcess();
2841 localEvent
.mMessage
= eAccessKeyNotFound
;
2843 // Here we convert the WidgetEvent that we received to an Event
2844 // to be able to dispatch it to the <browser> element as the target element.
2845 Document
* doc
= mFrameElement
->OwnerDoc();
2846 PresShell
* presShell
= doc
->GetPresShell();
2847 NS_ENSURE_TRUE(presShell
, IPC_OK());
2849 if (presShell
->CanDispatchEvent()) {
2850 RefPtr
<nsPresContext
> presContext
= presShell
->GetPresContext();
2851 NS_ENSURE_TRUE(presContext
, IPC_OK());
2853 RefPtr
<Element
> frameElement
= mFrameElement
;
2854 EventDispatcher::Dispatch(frameElement
, presContext
, &localEvent
);
2860 mozilla::ipc::IPCResult
BrowserParent::RecvRegisterProtocolHandler(
2861 const nsString
& aScheme
, nsIURI
* aHandlerURI
, const nsString
& aTitle
,
2863 nsCOMPtr
<nsIWebProtocolHandlerRegistrar
> registrar
=
2864 do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID
);
2866 registrar
->RegisterProtocolHandler(aScheme
, aHandlerURI
, aTitle
, aDocURI
,
2873 mozilla::ipc::IPCResult
BrowserParent::RecvOnStateChange(
2874 const WebProgressData
& aWebProgressData
, const RequestData
& aRequestData
,
2875 const uint32_t aStateFlags
, const nsresult aStatus
,
2876 const Maybe
<WebProgressStateChangeData
>& aStateChangeData
) {
2877 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
2878 BrowsingContextForWebProgress(aWebProgressData
);
2879 if (!browsingContext
) {
2883 nsCOMPtr
<nsIRequest
> request
;
2884 if (aRequestData
.requestURI()) {
2885 request
= MakeAndAddRef
<RemoteWebProgressRequest
>(
2886 aRequestData
.requestURI(), aRequestData
.originalRequestURI(),
2887 aRequestData
.matchedList());
2890 if (aStateChangeData
.isSome()) {
2891 if (!browsingContext
->IsTopContent()) {
2894 "Unexpected WebProgressStateChangeData for non toplevel webProgress");
2897 if (nsCOMPtr
<nsIBrowser
> browser
= GetBrowser()) {
2898 Unused
<< browser
->SetIsNavigating(aStateChangeData
->isNavigating());
2899 Unused
<< browser
->SetMayEnableCharacterEncodingMenu(
2900 aStateChangeData
->mayEnableCharacterEncodingMenu());
2901 Unused
<< browser
->UpdateForStateChange(aStateChangeData
->charset(),
2902 aStateChangeData
->documentURI(),
2903 aStateChangeData
->contentType());
2907 if (auto* listener
= browsingContext
->GetWebProgress()) {
2908 listener
->OnStateChange(listener
, request
, aStateFlags
, aStatus
);
2914 mozilla::ipc::IPCResult
BrowserParent::RecvOnProgressChange(
2915 const int32_t aCurTotalProgress
, const int32_t aMaxTotalProgress
) {
2916 // We only collect progress change notifications for the toplevel
2918 // FIXME: In the future, consider merging in progress change information from
2920 if (!GetBrowsingContext()->IsTopContent() ||
2921 !GetBrowsingContext()->GetWebProgress()) {
2925 GetBrowsingContext()->GetWebProgress()->OnProgressChange(
2926 nullptr, nullptr, 0, 0, aCurTotalProgress
, aMaxTotalProgress
);
2931 mozilla::ipc::IPCResult
BrowserParent::RecvOnLocationChange(
2932 const WebProgressData
& aWebProgressData
, const RequestData
& aRequestData
,
2933 nsIURI
* aLocation
, const uint32_t aFlags
, const bool aCanGoBack
,
2934 const bool aCanGoForward
,
2935 const Maybe
<WebProgressLocationChangeData
>& aLocationChangeData
) {
2936 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
2937 BrowsingContextForWebProgress(aWebProgressData
);
2938 if (!browsingContext
) {
2942 nsCOMPtr
<nsIRequest
> request
;
2943 if (aRequestData
.requestURI()) {
2944 request
= MakeAndAddRef
<RemoteWebProgressRequest
>(
2945 aRequestData
.requestURI(), aRequestData
.originalRequestURI(),
2946 aRequestData
.matchedList());
2949 browsingContext
->SetCurrentRemoteURI(aLocation
);
2951 nsCOMPtr
<nsIBrowser
> browser
= GetBrowser();
2952 if (!mozilla::SessionHistoryInParent() && browser
) {
2953 Unused
<< browser
->UpdateWebNavigationForLocationChange(aCanGoBack
,
2957 if (aLocationChangeData
.isSome()) {
2958 if (!browsingContext
->IsTopContent()) {
2959 return IPC_FAIL(this,
2960 "Unexpected WebProgressLocationChangeData for non "
2961 "toplevel webProgress");
2965 Unused
<< browser
->SetIsNavigating(aLocationChangeData
->isNavigating());
2966 Unused
<< browser
->UpdateForLocationChange(
2967 aLocation
, aLocationChangeData
->charset(),
2968 aLocationChangeData
->mayEnableCharacterEncodingMenu(),
2969 aLocationChangeData
->documentURI(), aLocationChangeData
->title(),
2970 aLocationChangeData
->contentPrincipal(),
2971 aLocationChangeData
->contentPartitionedPrincipal(),
2972 aLocationChangeData
->csp(), aLocationChangeData
->referrerInfo(),
2973 aLocationChangeData
->isSyntheticDocument(),
2974 aLocationChangeData
->requestContextID().isSome(),
2975 aLocationChangeData
->requestContextID().valueOr(0),
2976 aLocationChangeData
->contentType());
2980 if (auto* listener
= browsingContext
->GetWebProgress()) {
2981 listener
->OnLocationChange(listener
, request
, aLocation
, aFlags
);
2984 // Since we've now changed Documents, notify the BrowsingContext that we've
2985 // changed. Ideally we'd just let the BrowsingContext do this when it changes
2986 // the current window global, but that happens before this and we have a lot
2987 // of tests that depend on the specific ordering of messages.
2988 if (browsingContext
->IsTopContent() &&
2989 !(aFlags
& nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT
)) {
2990 browsingContext
->UpdateSecurityState();
2995 mozilla::ipc::IPCResult
BrowserParent::RecvOnStatusChange(
2996 const nsString
& aMessage
) {
2997 // We only collect status change notifications for the toplevel
2999 // FIXME: In the future, consider merging in status change information from
3001 if (!GetBrowsingContext()->IsTopContent() ||
3002 !GetBrowsingContext()->GetWebProgress()) {
3006 GetBrowsingContext()->GetWebProgress()->OnStatusChange(nullptr, nullptr,
3007 NS_OK
, aMessage
.get());
3012 mozilla::ipc::IPCResult
BrowserParent::RecvNavigationFinished() {
3013 nsCOMPtr
<nsIBrowser
> browser
=
3014 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
3017 browser
->SetIsNavigating(false);
3023 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyContentBlockingEvent(
3024 const uint32_t& aEvent
, const RequestData
& aRequestData
,
3025 const bool aBlocked
, const nsACString
& aTrackingOrigin
,
3026 nsTArray
<nsCString
>&& aTrackingFullHashes
,
3028 mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
3030 RefPtr
<BrowsingContext
> bc
= GetBrowsingContext();
3032 if (!bc
|| bc
->IsDiscarded()) {
3036 // Get the top-level browsing context.
3038 RefPtr
<dom::WindowGlobalParent
> wgp
=
3039 bc
->Canonical()->GetCurrentWindowGlobal();
3041 // The WindowGlobalParent would be null while running the test
3042 // browser_339445.js. This is unexpected and we will address this in a
3043 // following bug. For now, we first workaround this issue.
3048 nsCOMPtr
<nsIRequest
> request
= MakeAndAddRef
<RemoteWebProgressRequest
>(
3049 aRequestData
.requestURI(), aRequestData
.originalRequestURI(),
3050 aRequestData
.matchedList());
3052 wgp
->NotifyContentBlockingEvent(aEvent
, request
, aBlocked
, aTrackingOrigin
,
3053 aTrackingFullHashes
, aReason
);
3058 already_AddRefed
<nsIBrowser
> BrowserParent::GetBrowser() {
3059 nsCOMPtr
<nsIBrowser
> browser
;
3060 RefPtr
<Element
> currentElement
= mFrameElement
;
3062 // In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
3063 // but we want the <xul:browser> that it is embedded in.
3064 while (currentElement
) {
3065 browser
= currentElement
->AsBrowser();
3070 BrowsingContext
* browsingContext
=
3071 currentElement
->OwnerDoc()->GetBrowsingContext();
3073 browsingContext
? browsingContext
->GetEmbedderElement() : nullptr;
3076 return browser
.forget();
3079 already_AddRefed
<CanonicalBrowsingContext
>
3080 BrowserParent::BrowsingContextForWebProgress(
3081 const WebProgressData
& aWebProgressData
) {
3082 // Look up the BrowsingContext which this notification was fired for.
3083 if (aWebProgressData
.browsingContext().IsNullOrDiscarded()) {
3084 NS_WARNING("WebProgress Ignored: BrowsingContext is null or discarded");
3087 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
3088 aWebProgressData
.browsingContext().get_canonical();
3090 // Double-check that we actually manage this BrowsingContext, and are not
3091 // receiving a malformed or out-of-date request. browsingContext should either
3092 // be the toplevel one managed by this BrowserParent, or embedded within a
3093 // WindowGlobalParent managed by this BrowserParent.
3094 if (browsingContext
!= mBrowsingContext
) {
3095 WindowGlobalParent
* embedder
= browsingContext
->GetParentWindowContext();
3096 if (!embedder
|| embedder
->GetBrowserParent() != this) {
3097 NS_WARNING("WebProgress Ignored: wrong embedder process");
3102 // The current process for this BrowsingContext may have changed since the
3103 // notification was fired. Don't fire events for it anymore, as ownership of
3104 // the BrowsingContext has been moved elsewhere.
3105 if (RefPtr
<WindowGlobalParent
> current
=
3106 browsingContext
->GetCurrentWindowGlobal();
3107 current
&& current
->GetBrowserParent() != this) {
3108 NS_WARNING("WebProgress Ignored: no longer current window global");
3112 if (RefPtr
<BrowsingContextWebProgress
> progress
=
3113 browsingContext
->GetWebProgress()) {
3114 progress
->SetLoadType(aWebProgressData
.loadType());
3117 return browsingContext
.forget();
3120 mozilla::ipc::IPCResult
BrowserParent::RecvIntrinsicSizeOrRatioChanged(
3121 const Maybe
<IntrinsicSize
>& aIntrinsicSize
,
3122 const Maybe
<AspectRatio
>& aIntrinsicRatio
) {
3123 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
3124 if (!bridge
|| !bridge
->CanSend()) {
3128 Unused
<< bridge
->SendIntrinsicSizeOrRatioChanged(aIntrinsicSize
,
3134 mozilla::ipc::IPCResult
BrowserParent::RecvImageLoadComplete(
3135 const nsresult
& aResult
) {
3136 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
3137 if (!bridge
|| !bridge
->CanSend()) {
3141 Unused
<< bridge
->SendImageLoadComplete(aResult
);
3146 bool BrowserParent::HandleQueryContentEvent(WidgetQueryContentEvent
& aEvent
) {
3147 nsCOMPtr
<nsIWidget
> textInputHandlingWidget
= GetTextInputHandlingWidget();
3148 if (!textInputHandlingWidget
) {
3151 if (!mContentCache
.HandleQueryContentEvent(aEvent
, textInputHandlingWidget
) ||
3152 NS_WARN_IF(aEvent
.Failed())) {
3155 switch (aEvent
.mMessage
) {
3156 case eQueryTextRect
:
3157 case eQueryCaretRect
:
3158 case eQueryEditorRect
: {
3159 nsCOMPtr
<nsIWidget
> browserWidget
= GetWidget();
3160 if (browserWidget
!= textInputHandlingWidget
) {
3161 aEvent
.mReply
->mRect
+= nsLayoutUtils::WidgetToWidgetOffset(
3162 browserWidget
, textInputHandlingWidget
);
3164 aEvent
.mReply
->mRect
= TransformChildToParent(aEvent
.mReply
->mRect
);
3173 bool BrowserParent::SendCompositionEvent(WidgetCompositionEvent
& aEvent
,
3174 uint32_t aCompositionId
) {
3179 // When the composition is handled in a remote process, we need to handle
3180 // commit/cancel result for composition with the composition ID to avoid
3181 // to abort newer composition. Therefore, we need to let the remote process
3182 // know the composition ID.
3183 MOZ_ASSERT(aCompositionId
!= 0);
3184 aEvent
.mCompositionId
= aCompositionId
;
3186 if (!mContentCache
.OnCompositionEvent(aEvent
)) {
3190 bool ret
= Manager()->IsInputPriorityEventEnabled()
3191 ? PBrowserParent::SendCompositionEvent(aEvent
)
3192 : PBrowserParent::SendNormalPriorityCompositionEvent(aEvent
);
3193 if (NS_WARN_IF(!ret
)) {
3196 MOZ_ASSERT(aEvent
.HasBeenPostedToRemoteProcess());
3200 bool BrowserParent::SendSelectionEvent(WidgetSelectionEvent
& aEvent
) {
3204 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3208 mContentCache
.OnSelectionEvent(aEvent
);
3209 bool ret
= Manager()->IsInputPriorityEventEnabled()
3210 ? PBrowserParent::SendSelectionEvent(aEvent
)
3211 : PBrowserParent::SendNormalPrioritySelectionEvent(aEvent
);
3212 if (NS_WARN_IF(!ret
)) {
3215 MOZ_ASSERT(aEvent
.HasBeenPostedToRemoteProcess());
3216 aEvent
.mSucceeded
= true;
3220 bool BrowserParent::SendInsertText(const nsString
& aStringToInsert
) {
3224 return Manager()->IsInputPriorityEventEnabled()
3225 ? PBrowserParent::SendInsertText(aStringToInsert
)
3226 : PBrowserParent::SendNormalPriorityInsertText(aStringToInsert
);
3229 bool BrowserParent::SendPasteTransferable(
3230 IPCTransferableData
&& aTransferableData
, const bool& aIsPrivateData
,
3231 nsIPrincipal
* aRequestingPrincipal
,
3232 const nsContentPolicyType
& aContentPolicyType
) {
3233 return PBrowserParent::SendPasteTransferable(
3234 std::move(aTransferableData
), aIsPrivateData
, aRequestingPrincipal
,
3235 aContentPolicyType
);
3239 void BrowserParent::SetTopLevelWebFocus(BrowserParent
* aBrowserParent
) {
3240 BrowserParent
* old
= GetFocused();
3241 if (aBrowserParent
&& !aBrowserParent
->GetBrowserBridgeParent()) {
3242 // top-level Web content
3243 sTopLevelWebFocus
= aBrowserParent
;
3244 BrowserParent
* bp
= UpdateFocus();
3247 ("SetTopLevelWebFocus updated focus; old: %p, new: %p", old
, bp
));
3248 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, bp
);
3254 void BrowserParent::UnsetTopLevelWebFocus(BrowserParent
* aBrowserParent
) {
3255 BrowserParent
* old
= GetFocused();
3256 if (sTopLevelWebFocus
== aBrowserParent
) {
3257 // top-level Web content
3258 sTopLevelWebFocus
= nullptr;
3262 ("UnsetTopLevelWebFocus moved focus to chrome; old: %p", old
));
3263 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, nullptr);
3269 void BrowserParent::UpdateFocusFromBrowsingContext() {
3270 BrowserParent
* old
= GetFocused();
3271 BrowserParent
* bp
= UpdateFocus();
3274 ("UpdateFocusFromBrowsingContext updated focus; old: %p, new: %p", old
,
3276 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, bp
);
3281 BrowserParent
* BrowserParent::UpdateFocus() {
3282 if (!sTopLevelWebFocus
) {
3286 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
3288 BrowsingContext
* bc
= fm
->GetFocusedBrowsingContextInChrome();
3290 BrowsingContext
* top
= bc
->Top();
3291 MOZ_ASSERT(top
, "Should always have a top BrowsingContext.");
3292 CanonicalBrowsingContext
* canonicalTop
= top
->Canonical();
3293 MOZ_ASSERT(canonicalTop
,
3294 "Casting to canonical should always be possible in the parent "
3295 "process (top case).");
3296 WindowGlobalParent
* globalTop
= canonicalTop
->GetCurrentWindowGlobal();
3298 RefPtr
<BrowserParent
> globalTopParent
= globalTop
->GetBrowserParent();
3299 if (sTopLevelWebFocus
== globalTopParent
) {
3300 CanonicalBrowsingContext
* canonical
= bc
->Canonical();
3303 "Casting to canonical should always be possible in the parent "
3305 WindowGlobalParent
* global
= canonical
->GetCurrentWindowGlobal();
3307 RefPtr
<BrowserParent
> parent
= global
->GetBrowserParent();
3312 ("Focused BrowsingContext did not have WindowGlobalParent."));
3316 ("Top-level BrowsingContext did not have WindowGlobalParent."));
3320 sFocus
= sTopLevelWebFocus
;
3325 void BrowserParent::UnsetTopLevelWebFocusAll() {
3326 if (sTopLevelWebFocus
) {
3327 UnsetTopLevelWebFocus(sTopLevelWebFocus
);
3332 void BrowserParent::UnsetLastMouseRemoteTarget(BrowserParent
* aBrowserParent
) {
3333 if (sLastMouseRemoteTarget
== aBrowserParent
) {
3334 sLastMouseRemoteTarget
= nullptr;
3338 mozilla::ipc::IPCResult
BrowserParent::RecvRequestIMEToCommitComposition(
3339 const bool& aCancel
, const uint32_t& aCompositionId
, bool* aIsCommitted
,
3340 nsString
* aCommittedString
) {
3341 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
3343 *aIsCommitted
= false;
3347 *aIsCommitted
= mContentCache
.RequestIMEToCommitComposition(
3348 widget
, aCancel
, aCompositionId
, *aCommittedString
);
3352 mozilla::ipc::IPCResult
BrowserParent::RecvGetInputContext(
3353 widget::IMEState
* aState
) {
3354 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3356 *aState
= widget::IMEState(IMEEnabled::Disabled
,
3357 IMEState::OPEN_STATE_NOT_SUPPORTED
);
3361 *aState
= widget
->GetInputContext().mIMEState
;
3365 mozilla::ipc::IPCResult
BrowserParent::RecvSetInputContext(
3366 const InputContext
& aContext
, const InputContextAction
& aAction
) {
3367 IMEStateManager::SetInputContextForChildProcess(this, aContext
, aAction
);
3371 bool BrowserParent::ReceiveMessage(const nsString
& aMessage
, bool aSync
,
3372 StructuredCloneData
* aData
,
3373 nsTArray
<StructuredCloneData
>* aRetVal
) {
3374 // If we're for an oop iframe, don't deliver messages to the wrong place.
3375 if (mBrowserBridgeParent
) {
3379 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader(true);
3380 if (frameLoader
&& frameLoader
->GetFrameMessageManager()) {
3381 RefPtr
<nsFrameMessageManager
> manager
=
3382 frameLoader
->GetFrameMessageManager();
3384 manager
->ReceiveMessage(mFrameElement
, frameLoader
, aMessage
, aSync
, aData
,
3385 aRetVal
, IgnoreErrors());
3390 // nsIAuthPromptProvider
3392 // This method is largely copied from nsDocShell::GetAuthPrompt
3394 BrowserParent::GetAuthPrompt(uint32_t aPromptReason
, const nsIID
& iid
,
3396 // we're either allowing auth, or it's a proxy request
3398 nsCOMPtr
<nsIPromptFactory
> wwatch
=
3399 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
3400 NS_ENSURE_SUCCESS(rv
, rv
);
3402 nsCOMPtr
<nsPIDOMWindowOuter
> window
;
3403 RefPtr
<Element
> frame
= mFrameElement
;
3404 if (frame
) window
= frame
->OwnerDoc()->GetWindow();
3406 // Get an auth prompter for our window so that the parenting
3407 // of the dialogs works as it should when using tabs.
3408 nsCOMPtr
<nsISupports
> prompt
;
3409 rv
= wwatch
->GetPrompt(window
, iid
, getter_AddRefs(prompt
));
3410 NS_ENSURE_SUCCESS(rv
, rv
);
3412 nsCOMPtr
<nsILoginManagerAuthPrompter
> prompter
= do_QueryInterface(prompt
);
3414 prompter
->SetBrowser(mFrameElement
);
3417 *aResult
= prompt
.forget().take();
3421 already_AddRefed
<PColorPickerParent
> BrowserParent::AllocPColorPickerParent(
3422 const nsString
& aTitle
, const nsString
& aInitialColor
,
3423 const nsTArray
<nsString
>& aDefaultColors
) {
3424 return MakeAndAddRef
<ColorPickerParent
>(aTitle
, aInitialColor
,
3428 already_AddRefed
<nsFrameLoader
> BrowserParent::GetFrameLoader(
3429 bool aUseCachedFrameLoaderAfterDestroy
) const {
3430 if (mIsDestroyed
&& !aUseCachedFrameLoaderAfterDestroy
) {
3435 RefPtr
<nsFrameLoader
> fl
= mFrameLoader
;
3438 RefPtr
<Element
> frameElement(mFrameElement
);
3439 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(frameElement
);
3440 return frameLoaderOwner
? frameLoaderOwner
->GetFrameLoader() : nullptr;
3443 void BrowserParent::TryCacheDPIAndScale() {
3448 const auto oldDefaultScale
= mDefaultScale
;
3449 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3450 mDPI
= widget
? widget
->GetDPI() : nsIWidget::GetFallbackDPI();
3451 mRounding
= widget
? widget
->RoundsWidgetCoordinatesTo() : 1;
3453 widget
? widget
->GetDefaultScale() : nsIWidget::GetFallbackDefaultScale();
3455 if (mDefaultScale
!= oldDefaultScale
) {
3456 // The change of the default scale factor will affect the child dimensions
3457 // so we need to invalidate it.
3458 mUpdatedDimensions
= false;
3462 void BrowserParent::ApzAwareEventRoutingToChild(
3463 ScrollableLayerGuid
* aOutTargetGuid
, uint64_t* aOutInputBlockId
,
3464 nsEventStatus
* aOutApzResponse
) {
3465 // Let the widget know that the event will be sent to the child process,
3466 // which will (hopefully) send a confirmation notice back to APZ.
3467 // Do this even if APZ is off since we need it for swipe gesture support on
3468 // OS X without APZ.
3469 InputAPZContext::SetRoutedToChildProcess();
3471 if (AsyncPanZoomEnabled()) {
3472 if (aOutTargetGuid
) {
3473 *aOutTargetGuid
= InputAPZContext::GetTargetLayerGuid();
3475 // There may be cases where the APZ hit-testing code came to a different
3476 // conclusion than the main-thread hit-testing code as to where the event
3477 // is destined. In such cases the layersId of the APZ result may not match
3478 // the layersId of this RemoteLayerTreeOwner. In such cases the
3479 // main-thread hit- testing code "wins" so we need to update the guid to
3481 if (mRemoteLayerTreeOwner
.IsInitialized()) {
3482 if (aOutTargetGuid
->mLayersId
!= mRemoteLayerTreeOwner
.GetLayersId()) {
3484 ScrollableLayerGuid(mRemoteLayerTreeOwner
.GetLayersId(), 0,
3485 ScrollableLayerGuid::NULL_SCROLL_ID
);
3489 if (aOutInputBlockId
) {
3490 *aOutInputBlockId
= InputAPZContext::GetInputBlockId();
3492 if (aOutApzResponse
) {
3493 *aOutApzResponse
= InputAPZContext::GetApzResponse();
3495 // We can get here without there being an InputAPZContext on the stack
3496 // if a non-native event synthesization function (such as
3497 // nsIDOMWindowUtils.sendTouchEvent()) was used in the parent process to
3498 // synthesize an event that's targeting a content process. Such events do
3499 // not go through APZ. Without an InputAPZContext on the stack we pick up
3500 // the default value "eSentinel" which cannot be sent over IPC, so replace
3501 // it with "eIgnore" instead, which what APZ uses when it ignores an
3502 // event. If a caller needs the ability to synthesize a event with a
3503 // different APZ response, a native event synthesization function (such as
3504 // sendNativeTouchPoint()) can be used.
3505 if (*aOutApzResponse
== nsEventStatus_eSentinel
) {
3506 *aOutApzResponse
= nsEventStatus_eIgnore
;
3510 if (aOutInputBlockId
) {
3511 *aOutInputBlockId
= 0;
3513 if (aOutApzResponse
) {
3514 *aOutApzResponse
= nsEventStatus_eIgnore
;
3519 mozilla::ipc::IPCResult
BrowserParent::RecvRespondStartSwipeEvent(
3520 const uint64_t& aInputBlockId
, const bool& aStartSwipe
) {
3521 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
3522 widget
->ReportSwipeStarted(aInputBlockId
, aStartSwipe
);
3527 bool BrowserParent::GetDocShellIsActive() {
3528 return mBrowsingContext
&& mBrowsingContext
->IsActive();
3531 bool BrowserParent::GetHasPresented() { return mHasPresented
; }
3533 bool BrowserParent::GetHasLayers() { return mHasLayers
; }
3535 bool BrowserParent::GetRenderLayers() { return mRenderLayers
; }
3537 void BrowserParent::SetRenderLayers(bool aEnabled
) {
3538 if (aEnabled
== mRenderLayers
) {
3539 if (aEnabled
&& mHasLayers
&& mIsPreservingLayers
) {
3540 // RenderLayers might be called when we've been preserving layers,
3541 // and already had layers uploaded. In that case, the MozLayerTreeReady
3542 // event will not naturally arrive, which can confuse the front-end
3543 // layer. So we fire the event here.
3544 RefPtr
<BrowserParent
> self
= this;
3545 LayersObserverEpoch epoch
= mLayerTreeEpoch
;
3546 NS_DispatchToMainThread(NS_NewRunnableFunction(
3547 "dom::BrowserParent::RenderLayers", [self
, epoch
]() {
3548 MOZ_ASSERT(NS_IsMainThread());
3549 self
->LayerTreeUpdate(epoch
, true);
3556 // Preserve layers means that attempts to stop rendering layers
3558 if (!aEnabled
&& mIsPreservingLayers
) {
3562 mRenderLayers
= aEnabled
;
3564 SetRenderLayersInternal(aEnabled
);
3567 void BrowserParent::SetRenderLayersInternal(bool aEnabled
) {
3568 // Increment the epoch so that layer tree updates from previous
3569 // RenderLayers requests are ignored.
3570 mLayerTreeEpoch
= mLayerTreeEpoch
.Next();
3572 Unused
<< SendRenderLayers(aEnabled
, mLayerTreeEpoch
);
3574 // Ask the child to repaint/unload layers using the PHangMonitor
3575 // channel/thread (which may be less congested).
3577 Manager()->PaintTabWhileInterruptingJS(this, mLayerTreeEpoch
);
3579 Manager()->UnloadLayersWhileInterruptingJS(this, mLayerTreeEpoch
);
3583 bool BrowserParent::GetPriorityHint() { return mPriorityHint
; }
3585 void BrowserParent::SetPriorityHint(bool aPriorityHint
) {
3586 mPriorityHint
= aPriorityHint
;
3587 RecomputeProcessPriority();
3590 void BrowserParent::RecomputeProcessPriority() {
3591 auto* bc
= GetBrowsingContext();
3592 ProcessPriorityManager::BrowserPriorityChanged(
3593 bc
, bc
->IsActive() || mPriorityHint
);
3596 void BrowserParent::PreserveLayers(bool aPreserveLayers
) {
3597 if (mIsPreservingLayers
== aPreserveLayers
) {
3600 mIsPreservingLayers
= aPreserveLayers
;
3601 Unused
<< SendPreserveLayers(aPreserveLayers
);
3604 void BrowserParent::NotifyResolutionChanged() {
3608 // TryCacheDPIAndScale()'s cache is keyed off of
3609 // mDPI being greater than 0, so this invalidates it.
3611 TryCacheDPIAndScale();
3612 // If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
3613 // fails to cache the values, then mDefaultScale.scale might be invalid.
3614 // We don't want to send that value to content. Just send -1 for it too in
3616 Unused
<< SendUIResolutionChanged(mDPI
, mRounding
,
3617 mDPI
< 0 ? -1.0 : mDefaultScale
.scale
);
3620 bool BrowserParent::CanCancelContentJS(
3621 nsIRemoteTab::NavigationType aNavigationType
, int32_t aNavigationIndex
,
3622 nsIURI
* aNavigationURI
) const {
3623 // Pre-checking if we can cancel content js in the parent is only
3624 // supported when session history in the parent is enabled.
3625 if (!mozilla::SessionHistoryInParent()) {
3626 // If session history in the parent isn't enabled, this check will
3627 // be fully done in BrowserChild::CanCancelContentJS
3631 nsCOMPtr
<nsISHistory
> history
= mBrowsingContext
->GetSessionHistory();
3634 // If there is no history we can't possibly know if it's ok to
3635 // cancel content js.
3640 NS_ENSURE_SUCCESS(history
->GetIndex(¤t
), false);
3642 if (current
== -1) {
3643 // This tab has no history! Just return.
3647 nsCOMPtr
<nsISHEntry
> entry
;
3648 NS_ENSURE_SUCCESS(history
->GetEntryAtIndex(current
, getter_AddRefs(entry
)),
3651 nsCOMPtr
<nsIURI
> currentURI
= entry
->GetURI();
3652 if (!currentURI
->SchemeIs("http") && !currentURI
->SchemeIs("https") &&
3653 !currentURI
->SchemeIs("file")) {
3654 // Only cancel content JS for http(s) and file URIs. Other URIs are probably
3655 // internal and we should just let them run to completion.
3659 if (aNavigationType
== nsIRemoteTab::NAVIGATE_BACK
) {
3660 aNavigationIndex
= current
- 1;
3661 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_FORWARD
) {
3662 aNavigationIndex
= current
+ 1;
3663 } else if (aNavigationType
== nsIRemoteTab::NAVIGATE_URL
) {
3664 if (!aNavigationURI
) {
3668 if (aNavigationURI
->SchemeIs("javascript")) {
3669 // "javascript:" URIs don't (necessarily) trigger navigation to a
3670 // different page, so don't allow the current page's JS to terminate.
3674 // If navigating directly to a URL (e.g. via hitting Enter in the location
3675 // bar), then we can cancel anytime the next URL is different from the
3676 // current, *excluding* the ref ("#").
3678 NS_ENSURE_SUCCESS(currentURI
->EqualsExceptRef(aNavigationURI
, &equals
),
3682 // Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't
3683 // need to do anything special.
3685 int32_t delta
= aNavigationIndex
> current
? 1 : -1;
3686 for (int32_t i
= current
+ delta
; i
!= aNavigationIndex
+ delta
; i
+= delta
) {
3687 nsCOMPtr
<nsISHEntry
> nextEntry
;
3688 // If `i` happens to be negative, this call will fail (which is what we
3689 // would want to happen).
3690 NS_ENSURE_SUCCESS(history
->GetEntryAtIndex(i
, getter_AddRefs(nextEntry
)),
3693 nsCOMPtr
<nsISHEntry
> laterEntry
= delta
== 1 ? nextEntry
: entry
;
3694 nsCOMPtr
<nsIURI
> thisURI
= entry
->GetURI();
3695 nsCOMPtr
<nsIURI
> nextURI
= nextEntry
->GetURI();
3697 // If we changed origin and the load wasn't in a subframe, we know it was
3698 // a full document load, so we can cancel the content JS safely.
3699 if (!laterEntry
->GetIsSubFrame()) {
3700 nsAutoCString thisHost
;
3701 NS_ENSURE_SUCCESS(thisURI
->GetPrePath(thisHost
), false);
3703 nsAutoCString nextHost
;
3704 NS_ENSURE_SUCCESS(nextURI
->GetPrePath(nextHost
), false);
3706 if (!thisHost
.Equals(nextHost
)) {
3717 void BrowserParent::SuppressDisplayport(bool aEnabled
) {
3718 if (IsDestroyed()) {
3724 mActiveSupressDisplayportCount
++;
3726 mActiveSupressDisplayportCount
--;
3728 MOZ_ASSERT(mActiveSupressDisplayportCount
>= 0);
3731 Unused
<< SendSuppressDisplayport(aEnabled
);
3734 void BrowserParent::NavigateByKey(bool aForward
, bool aForDocumentNavigation
) {
3735 Unused
<< SendNavigateByKey(aForward
, aForDocumentNavigation
);
3738 void BrowserParent::LayerTreeUpdate(const LayersObserverEpoch
& aEpoch
,
3740 // Ignore updates if we're an out-of-process iframe. For oop iframes, our
3741 // |mFrameElement| is that of the top-level document, and so AsyncTabSwitcher
3742 // will treat MozLayerTreeReady / MozLayerTreeCleared events as if they came
3743 // from the top-level tab, which is wrong.
3745 // XXX: Should we still be updating |mHasLayers|?
3746 if (GetBrowserBridgeParent()) {
3750 // Ignore updates from old epochs. They might tell us that layers are
3751 // available when we've already sent a message to clear them. We can't trust
3752 // the update in that case since layers could disappear anytime after that.
3753 if (aEpoch
!= mLayerTreeEpoch
|| mIsDestroyed
) {
3757 RefPtr
<Element
> frameElement
= mFrameElement
;
3758 if (!frameElement
) {
3759 NS_WARNING("Could not locate target for layer tree message.");
3763 mHasLayers
= aActive
;
3765 RefPtr
<Event
> event
= NS_NewDOMEvent(frameElement
, nullptr, nullptr);
3767 mHasPresented
= true;
3768 event
->InitEvent(u
"MozLayerTreeReady"_ns
, true, false);
3770 event
->InitEvent(u
"MozLayerTreeCleared"_ns
, true, false);
3772 event
->SetTrusted(true);
3773 event
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
3774 frameElement
->DispatchEvent(*event
);
3777 mozilla::ipc::IPCResult
BrowserParent::RecvPaintWhileInterruptingJSNoOp(
3778 const LayersObserverEpoch
& aEpoch
) {
3779 // We sent a PaintWhileInterruptingJS message when layers were already
3780 // visible. In this case, we should act as if an update occurred even though
3781 // we already have the layers.
3782 LayerTreeUpdate(aEpoch
, true);
3786 mozilla::ipc::IPCResult
BrowserParent::RecvRemoteIsReadyToHandleInputEvents() {
3787 // When enabling input event prioritization, input events may preempt other
3788 // normal priority IPC messages. To prevent the input events preempt
3789 // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
3790 // notify the parent that BrowserChild is created and ready to handle input
3792 SetReadyToHandleInputEvents();
3796 PPaymentRequestParent
* BrowserParent::AllocPPaymentRequestParent() {
3797 RefPtr
<PaymentRequestParent
> actor
= new PaymentRequestParent();
3798 return actor
.forget().take();
3801 bool BrowserParent::DeallocPPaymentRequestParent(
3802 PPaymentRequestParent
* aActor
) {
3803 RefPtr
<PaymentRequestParent
> actor
=
3804 dont_AddRef(static_cast<PaymentRequestParent
*>(aActor
));
3808 nsresult
BrowserParent::HandleEvent(Event
* aEvent
) {
3813 nsAutoString eventType
;
3814 aEvent
->GetType(eventType
);
3815 if (eventType
.EqualsLiteral("MozUpdateWindowPos") ||
3816 eventType
.EqualsLiteral("fullscreenchange")) {
3817 // Events that signify the window moving are used to update the position
3818 // and notify the BrowserChild.
3819 return UpdatePosition();
3824 mozilla::ipc::IPCResult
BrowserParent::RecvInvokeDragSession(
3825 nsTArray
<IPCTransferableData
>&& aTransferables
, const uint32_t& aAction
,
3826 Maybe
<BigBuffer
>&& aVisualDnDData
, const uint32_t& aStride
,
3827 const gfx::SurfaceFormat
& aFormat
, const LayoutDeviceIntRect
& aDragRect
,
3828 nsIPrincipal
* aPrincipal
, nsIContentSecurityPolicy
* aCsp
,
3829 const CookieJarSettingsArgs
& aCookieJarSettingsArgs
,
3830 const MaybeDiscarded
<WindowContext
>& aSourceWindowContext
,
3831 const MaybeDiscarded
<WindowContext
>& aSourceTopWindowContext
) {
3832 PresShell
* presShell
= mFrameElement
->OwnerDoc()->GetPresShell();
3834 Unused
<< Manager()->SendEndDragSession(
3835 true, true, LayoutDeviceIntPoint(), 0,
3836 nsIDragService::DRAGDROP_ACTION_NONE
);
3837 // Continue sending input events with input priority when stopping the dnd
3839 Manager()->SetInputPriorityEventEnabled(true);
3843 nsCOMPtr
<nsICookieJarSettings
> cookieJarSettings
;
3844 net::CookieJarSettings::Deserialize(aCookieJarSettingsArgs
,
3845 getter_AddRefs(cookieJarSettings
));
3847 RefPtr
<RemoteDragStartData
> dragStartData
= new RemoteDragStartData(
3848 this, std::move(aTransferables
), aDragRect
, aPrincipal
, aCsp
,
3849 cookieJarSettings
, aSourceWindowContext
.GetMaybeDiscarded(),
3850 aSourceTopWindowContext
.GetMaybeDiscarded());
3852 if (aVisualDnDData
) {
3853 const auto checkedSize
= CheckedInt
<size_t>(aDragRect
.height
) * aStride
;
3854 if (checkedSize
.isValid() &&
3855 aVisualDnDData
->Size() >= checkedSize
.value()) {
3856 dragStartData
->SetVisualization(gfx::CreateDataSourceSurfaceFromData(
3857 gfx::IntSize(aDragRect
.width
, aDragRect
.height
), aFormat
,
3858 aVisualDnDData
->Data(), aStride
));
3862 nsCOMPtr
<nsIDragService
> dragService
=
3863 do_GetService("@mozilla.org/widget/dragservice;1");
3865 dragService
->MaybeAddChildProcess(Manager());
3868 presShell
->GetPresContext()
3869 ->EventStateManager()
3870 ->BeginTrackingRemoteDragGesture(mFrameElement
, dragStartData
);
3875 bool BrowserParent::AsyncPanZoomEnabled() const {
3876 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3877 return widget
&& widget
->AsyncPanZoomEnabled();
3880 void BrowserParent::StartPersistence(
3881 CanonicalBrowsingContext
* aContext
,
3882 nsIWebBrowserPersistDocumentReceiver
* aRecv
, ErrorResult
& aRv
) {
3883 auto* actor
= new WebBrowserPersistDocumentParent();
3884 actor
->SetOnReady(aRecv
);
3885 bool ok
= Manager()->SendPWebBrowserPersistDocumentConstructor(actor
, this,
3888 aRv
.Throw(NS_ERROR_FAILURE
);
3890 // (The actor will be destroyed on constructor failure.)
3893 mozilla::ipc::IPCResult
BrowserParent::RecvLookUpDictionary(
3894 const nsString
& aText
, nsTArray
<FontRange
>&& aFontRangeArray
,
3895 const bool& aIsVertical
, const LayoutDeviceIntPoint
& aPoint
) {
3896 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3901 widget
->LookUpDictionary(aText
, aFontRangeArray
, aIsVertical
,
3902 TransformChildToParent(aPoint
));
3906 mozilla::ipc::IPCResult
BrowserParent::RecvShowCanvasPermissionPrompt(
3907 const nsCString
& aOrigin
, const bool& aHideDoorHanger
) {
3908 nsCOMPtr
<nsIBrowser
> browser
=
3909 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
3911 // If the tab is being closed, the browser may not be available.
3912 // In this case we can ignore the request.
3915 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
3917 return IPC_FAIL_NO_REASON(this);
3919 nsresult rv
= os
->NotifyObservers(
3921 aHideDoorHanger
? "canvas-permissions-prompt-hide-doorhanger"
3922 : "canvas-permissions-prompt",
3923 NS_ConvertUTF8toUTF16(aOrigin
).get());
3924 if (NS_FAILED(rv
)) {
3925 return IPC_FAIL_NO_REASON(this);
3930 mozilla::ipc::IPCResult
BrowserParent::RecvVisitURI(
3931 nsIURI
* aURI
, nsIURI
* aLastVisitedURI
, const uint32_t& aFlags
,
3932 const uint64_t& aBrowserId
) {
3934 return IPC_FAIL_NO_REASON(this);
3936 RefPtr
<nsIWidget
> widget
= GetWidget();
3937 if (NS_WARN_IF(!widget
)) {
3940 nsCOMPtr
<IHistory
> history
= components::History::Service();
3942 Unused
<< history
->VisitURI(widget
, aURI
, aLastVisitedURI
, aFlags
,
3948 mozilla::ipc::IPCResult
BrowserParent::RecvQueryVisitedState(
3949 nsTArray
<RefPtr
<nsIURI
>>&& aURIs
) {
3950 #ifdef MOZ_ANDROID_HISTORY
3951 nsCOMPtr
<IHistory
> history
= components::History::Service();
3952 if (NS_WARN_IF(!history
)) {
3955 RefPtr
<nsIWidget
> widget
= GetWidget();
3956 if (NS_WARN_IF(!widget
)) {
3960 // FIXME(emilio): Is this check really needed?
3961 for (nsIURI
* uri
: aURIs
) {
3963 return IPC_FAIL(this, "Received null URI");
3967 auto* gvHistory
= static_cast<GeckoViewHistory
*>(history
.get());
3968 gvHistory
->QueryVisitedState(widget
, mManager
, std::move(aURIs
));
3971 return IPC_FAIL(this, "QueryVisitedState is Android-only");
3975 void BrowserParent::LiveResizeStarted() { SuppressDisplayport(true); }
3977 void BrowserParent::LiveResizeStopped() { SuppressDisplayport(false); }
3979 void BrowserParent::SetBrowserBridgeParent(BrowserBridgeParent
* aBrowser
) {
3980 // We should either be clearing out our reference to a browser bridge, or not
3981 // have either a browser bridge, browser host, or owner content yet.
3982 MOZ_ASSERT(!aBrowser
||
3983 (!mBrowserBridgeParent
&& !mBrowserHost
&& !mFrameElement
));
3984 mBrowserBridgeParent
= aBrowser
;
3987 void BrowserParent::SetBrowserHost(BrowserHost
* aBrowser
) {
3988 // We should either be clearing out our reference to a browser host, or not
3989 // have either a browser bridge, browser host, or owner content yet.
3990 MOZ_ASSERT(!aBrowser
||
3991 (!mBrowserBridgeParent
&& !mBrowserHost
&& !mFrameElement
));
3992 mBrowserHost
= aBrowser
;
3995 mozilla::ipc::IPCResult
BrowserParent::RecvSetSystemFont(
3996 const nsCString
& aFontName
) {
3997 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3999 widget
->SetSystemFont(aFontName
);
4004 mozilla::ipc::IPCResult
BrowserParent::RecvGetSystemFont(nsCString
* aFontName
) {
4005 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4007 widget
->GetSystemFont(*aFontName
);
4012 mozilla::ipc::IPCResult
BrowserParent::RecvMaybeFireEmbedderLoadEvents(
4013 EmbedderElementEventType aFireEventAtEmbeddingElement
) {
4014 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
4016 NS_WARNING("Received `load` event on unbridged BrowserParent!");
4020 Unused
<< bridge
->SendMaybeFireEmbedderLoadEvents(
4021 aFireEventAtEmbeddingElement
);
4025 mozilla::ipc::IPCResult
BrowserParent::RecvScrollRectIntoView(
4026 const nsRect
& aRect
, const ScrollAxis
& aVertical
,
4027 const ScrollAxis
& aHorizontal
, const ScrollFlags
& aScrollFlags
,
4028 const int32_t& aAppUnitsPerDevPixel
) {
4029 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
4030 if (!bridge
|| !bridge
->CanSend()) {
4034 Unused
<< bridge
->SendScrollRectIntoView(aRect
, aVertical
, aHorizontal
,
4035 aScrollFlags
, aAppUnitsPerDevPixel
);
4039 mozilla::ipc::IPCResult
BrowserParent::RecvIsWindowSupportingProtectedMedia(
4040 const uint64_t& aOuterWindowID
,
4041 IsWindowSupportingProtectedMediaResolver
&& aResolve
) {
4044 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID
);
4045 aResolve(!isFxrWindow
);
4047 # ifdef FUZZING_SNAPSHOT
4048 return IPC_FAIL(this, "Should only be called on Windows");
4050 MOZ_CRASH("Should only be called on Windows");
4056 mozilla::ipc::IPCResult
BrowserParent::RecvIsWindowSupportingWebVR(
4057 const uint64_t& aOuterWindowID
,
4058 IsWindowSupportingWebVRResolver
&& aResolve
) {
4061 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID
);
4062 aResolve(!isFxrWindow
);
4070 static BrowserParent
* GetTopLevelBrowserParent(BrowserParent
* aBrowserParent
) {
4071 MOZ_ASSERT(aBrowserParent
);
4072 BrowserParent
* parent
= aBrowserParent
;
4073 while (BrowserBridgeParent
* bridge
= parent
->GetBrowserBridgeParent()) {
4074 parent
= bridge
->Manager();
4079 mozilla::ipc::IPCResult
BrowserParent::RecvRequestPointerLock(
4080 RequestPointerLockResolver
&& aResolve
) {
4082 if (sTopLevelWebFocus
!= GetTopLevelBrowserParent(this)) {
4083 error
= "PointerLockDeniedNotFocused";
4084 } else if (!PointerLockManager::SetLockedRemoteTarget(this)) {
4085 error
= "PointerLockDeniedInUse";
4087 PointerEventHandler::ReleaseAllPointerCaptureRemoteTarget();
4093 mozilla::ipc::IPCResult
BrowserParent::RecvReleasePointerLock() {
4094 MOZ_ASSERT_IF(PointerLockManager::GetLockedRemoteTarget(),
4095 PointerLockManager::GetLockedRemoteTarget() == this);
4096 PointerLockManager::ReleaseLockedRemoteTarget(this);
4100 mozilla::ipc::IPCResult
BrowserParent::RecvRequestPointerCapture(
4101 const uint32_t& aPointerId
, RequestPointerCaptureResolver
&& aResolve
) {
4103 PointerEventHandler::SetPointerCaptureRemoteTarget(aPointerId
, this));
4107 mozilla::ipc::IPCResult
BrowserParent::RecvReleasePointerCapture(
4108 const uint32_t& aPointerId
) {
4109 PointerEventHandler::ReleasePointerCaptureRemoteTarget(aPointerId
);
4113 mozilla::ipc::IPCResult
BrowserParent::RecvShowDynamicToolbar() {
4114 #if defined(MOZ_WIDGET_ANDROID)
4115 nsCOMPtr
<nsIWidget
> widget
= GetTopLevelWidget();
4120 RefPtr
<nsWindow
> window
= nsWindow::From(widget
);
4125 window
->ShowDynamicToolbar();
4126 #endif // defined(MOZ_WIDGET_ANDROID)
4131 } // namespace mozilla