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"
12 # include "mozilla/a11y/DocAccessibleParent.h"
13 # include "mozilla/a11y/Platform.h"
14 # include "mozilla/a11y/ProxyAccessibleBase.h"
15 # include "nsAccessibilityService.h"
17 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
18 #include "mozilla/dom/ChromeMessageSender.h"
19 #include "mozilla/dom/ContentParent.h"
20 #include "mozilla/dom/DataTransfer.h"
21 #include "mozilla/dom/DataTransferItemList.h"
22 #include "mozilla/dom/Event.h"
23 #include "mozilla/dom/indexedDB/ActorsParent.h"
24 #include "mozilla/dom/PaymentRequestParent.h"
25 #include "mozilla/dom/BrowserBridgeParent.h"
26 #include "mozilla/dom/RemoteDragStartData.h"
27 #include "mozilla/dom/RemoteWebProgress.h"
28 #include "mozilla/dom/RemoteWebProgressRequest.h"
29 #include "mozilla/dom/SessionStoreUtils.h"
30 #include "mozilla/dom/SessionStoreUtilsBinding.h"
31 #include "mozilla/dom/UserActivation.h"
32 #include "mozilla/EventStateManager.h"
33 #include "mozilla/gfx/2D.h"
34 #include "mozilla/gfx/DataSurfaceHelpers.h"
35 #include "mozilla/gfx/GPUProcessManager.h"
36 #include "mozilla/Hal.h"
37 #include "mozilla/IMEStateManager.h"
38 #include "mozilla/layers/AsyncDragMetrics.h"
39 #include "mozilla/layers/InputAPZContext.h"
40 #include "mozilla/layout/RemoteLayerTreeOwner.h"
41 #include "mozilla/plugins/PPluginWidgetParent.h"
42 #include "mozilla/LookAndFeel.h"
43 #include "mozilla/MouseEvents.h"
44 #include "mozilla/net/NeckoChild.h"
45 #include "mozilla/Preferences.h"
46 #include "mozilla/PresShell.h"
47 #include "mozilla/ProcessHangMonitor.h"
48 #include "mozilla/StaticPrefs_dom.h"
49 #include "mozilla/TextEvents.h"
50 #include "mozilla/TouchEvents.h"
51 #include "mozilla/UniquePtr.h"
52 #include "mozilla/Unused.h"
54 #include "nsContentUtils.h"
56 #include "nsFocusManager.h"
57 #include "nsFrameLoader.h"
58 #include "nsFrameLoaderOwner.h"
59 #include "nsFrameManager.h"
60 #include "nsIBaseWindow.h"
61 #include "nsIBrowser.h"
62 #include "nsIBrowserController.h"
63 #include "nsIContent.h"
64 #include "nsIDocShell.h"
65 #include "nsIDocShellTreeOwner.h"
66 #include "nsImportModule.h"
67 #include "nsIInterfaceRequestorUtils.h"
68 #include "nsILoadInfo.h"
69 #include "nsIPromptFactory.h"
71 #include "nsIWebBrowserChrome.h"
72 #include "nsIWebProtocolHandlerRegistrar.h"
73 #include "nsIXPConnect.h"
74 #include "nsIXULBrowserWindow.h"
75 #include "nsIAppWindow.h"
76 #include "nsViewManager.h"
77 #include "nsVariant.h"
78 #include "nsIWidget.h"
79 #include "nsNetUtil.h"
81 # include "nsJARProtocolHandler.h"
83 #include "nsPIDOMWindow.h"
84 #include "nsPrintfCString.h"
85 #include "nsQueryObject.h"
86 #include "nsServiceManagerUtils.h"
87 #include "nsThreadUtils.h"
88 #include "PermissionMessageUtils.h"
89 #include "StructuredCloneData.h"
90 #include "ColorPickerParent.h"
91 #include "FilePickerParent.h"
92 #include "BrowserChild.h"
94 #include "nsIAuthInformation.h"
95 #include "nsIAuthPromptCallback.h"
96 #include "nsAuthInformationHolder.h"
97 #include "nsICancelable.h"
99 #include "nsILoginManagerAuthPrompter.h"
100 #include "nsPIWindowRoot.h"
101 #include "nsReadableUtils.h"
102 #include "nsIAuthPrompt2.h"
103 #include "gfxDrawable.h"
104 #include "ImageOps.h"
105 #include "UnitTransforms.h"
107 #include "mozilla/NullPrincipal.h"
108 #include "mozilla/WebBrowserPersistDocumentParent.h"
109 #include "ProcessPriorityManager.h"
110 #include "nsString.h"
111 #include "IHistory.h"
112 #include "mozilla/dom/WindowGlobalParent.h"
113 #include "mozilla/dom/CanonicalBrowsingContext.h"
114 #include "MMPrinter.h"
115 #include "SessionStoreFunctions.h"
116 #include "mozilla/dom/CrashReport.h"
119 # include "mozilla/plugins/PluginWidgetParent.h"
120 # include "FxRWindowManager.h"
123 #if defined(XP_WIN) && defined(ACCESSIBILITY)
124 # include "mozilla/a11y/AccessibleWrap.h"
125 # include "mozilla/a11y/Compatibility.h"
126 # include "mozilla/a11y/nsWinUtils.h"
129 #ifdef MOZ_ANDROID_HISTORY
130 # include "GeckoViewHistory.h"
133 using namespace mozilla::dom
;
134 using namespace mozilla::ipc
;
135 using namespace mozilla::layers
;
136 using namespace mozilla::layout
;
137 using namespace mozilla::services
;
138 using namespace mozilla::widget
;
139 using namespace mozilla::gfx
;
141 using mozilla::LazyLogModule
;
142 using mozilla::StaticAutoPtr
;
143 using mozilla::Unused
;
145 LazyLogModule
gBrowserFocusLog("BrowserFocus");
147 #define LOGBROWSERFOCUS(args) \
148 MOZ_LOG(gBrowserFocusLog, mozilla::LogLevel::Debug, args)
151 BrowserParent
* BrowserParent::sFocus
= nullptr;
153 BrowserParent
* BrowserParent::sTopLevelWebFocus
= nullptr;
155 BrowserParent
* BrowserParent::sLastMouseRemoteTarget
= nullptr;
157 // The flags passed by the webProgress notifications are 16 bits shifted
158 // from the ones registered by webProgressListeners.
159 #define NOTIFY_FLAG_SHIFT 16
164 BrowserParent::LayerToBrowserParentTable
*
165 BrowserParent::sLayerToBrowserParentTable
= nullptr;
167 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserParent
)
168 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider
)
169 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
170 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMEventListener
)
172 NS_IMPL_CYCLE_COLLECTION_WEAK(BrowserParent
, mFrameLoader
, mBrowsingContext
)
173 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserParent
)
174 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserParent
)
176 BrowserParent::BrowserParent(ContentParent
* aManager
, const TabId
& aTabId
,
177 const TabContext
& aContext
,
178 CanonicalBrowsingContext
* aBrowsingContext
,
179 uint32_t aChromeFlags
)
180 : TabContext(aContext
),
183 mBrowsingContext(aBrowsingContext
),
184 mFrameElement(nullptr),
185 mBrowserDOMWindow(nullptr),
186 mFrameLoader(nullptr),
187 mChromeFlags(aChromeFlags
),
188 mBrowserBridgeParent(nullptr),
189 mBrowserHost(nullptr),
190 mContentCache(*this),
191 mRemoteLayerTreeOwner
{},
193 mChildToParentConversionMatrix
{},
200 mUpdatedDimensions(false),
201 mSizeMode(nsSizeMode_Normal
),
204 mCreatingWindow(false),
206 mDelayedFrameScripts
{},
207 mCursor(eCursorInvalid
),
209 mCustomCursorHotspotX(0),
210 mCustomCursorHotspotY(0),
212 mDocShellIsActive(false),
213 mMarkedDestroying(false),
215 mTabSetsCursor(false),
216 mPreserveLayers(false),
218 mActiveInPriorityManager(false),
220 mHasPresented(false),
221 mIsReadyToHandleInputEvents(false),
222 mIsMouseEnterIntoWidgetEventSuppressed(false),
223 mSuspendedProgressEvents(false),
224 mSuspendMediaWhenInactive(false) {
225 MOZ_ASSERT(aManager
);
226 // When the input event queue is disabled, we don't need to handle the case
227 // that some input events are dispatched before PBrowserConstructor.
228 mIsReadyToHandleInputEvents
= !ContentParent::IsInputEventQueueSupported();
231 BrowserParent::~BrowserParent() = default;
234 void BrowserParent::InitializeStatics() { MOZ_ASSERT(XRE_IsParentProcess()); }
237 BrowserParent
* BrowserParent::GetFocused() { return sFocus
; }
240 BrowserParent
* BrowserParent::GetLastMouseRemoteTarget() {
241 return sLastMouseRemoteTarget
;
245 BrowserParent
* BrowserParent::GetFrom(nsFrameLoader
* aFrameLoader
) {
249 return aFrameLoader
->GetBrowserParent();
253 BrowserParent
* BrowserParent::GetFrom(PBrowserParent
* aBrowserParent
) {
254 return static_cast<BrowserParent
*>(aBrowserParent
);
258 BrowserParent
* BrowserParent::GetFrom(nsIContent
* aContent
) {
259 RefPtr
<nsFrameLoaderOwner
> loaderOwner
= do_QueryObject(aContent
);
263 RefPtr
<nsFrameLoader
> frameLoader
= loaderOwner
->GetFrameLoader();
264 return GetFrom(frameLoader
);
268 BrowserParent
* BrowserParent::GetBrowserParentFromLayersId(
269 layers::LayersId aLayersId
) {
270 if (!sLayerToBrowserParentTable
) {
273 return sLayerToBrowserParentTable
->Get(uint64_t(aLayersId
));
277 TabId
BrowserParent::GetTabIdFrom(nsIDocShell
* docShell
) {
278 nsCOMPtr
<nsIBrowserChild
> browserChild(BrowserChild::GetFrom(docShell
));
280 return static_cast<BrowserChild
*>(browserChild
.get())->GetTabId();
285 void BrowserParent::AddBrowserParentToTable(layers::LayersId aLayersId
,
286 BrowserParent
* aBrowserParent
) {
287 if (!sLayerToBrowserParentTable
) {
288 sLayerToBrowserParentTable
= new LayerToBrowserParentTable();
290 sLayerToBrowserParentTable
->Put(uint64_t(aLayersId
), aBrowserParent
);
293 void BrowserParent::RemoveBrowserParentFromTable(layers::LayersId aLayersId
) {
294 if (!sLayerToBrowserParentTable
) {
297 sLayerToBrowserParentTable
->Remove(uint64_t(aLayersId
));
298 if (sLayerToBrowserParentTable
->Count() == 0) {
299 delete sLayerToBrowserParentTable
;
300 sLayerToBrowserParentTable
= nullptr;
304 already_AddRefed
<nsILoadContext
> BrowserParent::GetLoadContext() {
305 return do_AddRef(mBrowsingContext
);
309 * Will return nullptr if there is no outer window available for the
310 * document hosting the owner element of this BrowserParent. Also will return
311 * nullptr if that outer window is in the process of closing.
313 already_AddRefed
<nsPIDOMWindowOuter
> BrowserParent::GetParentWindowOuter() {
314 nsCOMPtr
<nsIContent
> frame
= GetOwnerElement();
319 nsCOMPtr
<nsPIDOMWindowOuter
> parent
= frame
->OwnerDoc()->GetWindow();
320 if (!parent
|| parent
->Closed()) {
324 return parent
.forget();
327 already_AddRefed
<nsIWidget
> BrowserParent::GetTopLevelWidget() {
328 if (RefPtr
<Element
> element
= mFrameElement
) {
329 if (PresShell
* presShell
= element
->OwnerDoc()->GetPresShell()) {
330 nsViewManager
* vm
= presShell
->GetViewManager();
331 nsCOMPtr
<nsIWidget
> widget
;
332 vm
->GetRootWidget(getter_AddRefs(widget
));
333 return widget
.forget();
339 already_AddRefed
<nsIWidget
> BrowserParent::GetTextInputHandlingWidget() const {
340 if (!mFrameElement
) {
343 PresShell
* presShell
= mFrameElement
->OwnerDoc()->GetPresShell();
347 nsPresContext
* presContext
= presShell
->GetPresContext();
351 nsCOMPtr
<nsIWidget
> widget
= presContext
->GetTextInputHandlingWidget();
352 return widget
.forget();
355 already_AddRefed
<nsIWidget
> BrowserParent::GetWidget() const {
356 if (!mFrameElement
) {
359 nsCOMPtr
<nsIWidget
> widget
= nsContentUtils::WidgetForContent(mFrameElement
);
361 widget
= nsContentUtils::WidgetForDocument(mFrameElement
->OwnerDoc());
363 return widget
.forget();
366 already_AddRefed
<nsIWidget
> BrowserParent::GetDocWidget() const {
367 if (!mFrameElement
) {
371 nsContentUtils::WidgetForDocument(mFrameElement
->OwnerDoc()));
374 nsIXULBrowserWindow
* BrowserParent::GetXULBrowserWindow() {
375 if (!mFrameElement
) {
379 nsCOMPtr
<nsIDocShell
> docShell
= mFrameElement
->OwnerDoc()->GetDocShell();
384 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
385 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
390 nsCOMPtr
<nsIAppWindow
> window
= do_GetInterface(treeOwner
);
395 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
;
396 window
->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow
));
397 return xulBrowserWindow
;
400 uint32_t BrowserParent::GetMaxTouchPoints(Element
* aElement
) {
405 if (StaticPrefs::dom_maxtouchpoints_testing_value() >= 0) {
406 return StaticPrefs::dom_maxtouchpoints_testing_value();
409 nsIWidget
* widget
= nsContentUtils::WidgetForDocument(aElement
->OwnerDoc());
410 return widget
? widget
->GetMaxTouchPoints() : 0;
413 a11y::DocAccessibleParent
* BrowserParent::GetTopLevelDocAccessible() const {
415 // XXX Consider managing non top level PDocAccessibles with their parent
416 // document accessible.
417 const ManagedContainer
<PDocAccessibleParent
>& docs
=
418 ManagedPDocAccessibleParent();
419 for (auto iter
= docs
.ConstIter(); !iter
.Done(); iter
.Next()) {
420 auto doc
= static_cast<a11y::DocAccessibleParent
*>(iter
.Get()->GetKey());
421 // We want the document for this BrowserParent even if it's for an
422 // embedded out-of-process iframe. Therefore, we use
423 // IsTopLevelInContentProcess. In contrast, using IsToplevel would only
424 // include documents that aren't embedded; e.g. tab documents.
425 if (doc
->IsTopLevelInContentProcess()) {
430 MOZ_ASSERT(docs
.Count() == 0,
431 "If there isn't a top level accessible doc "
432 "there shouldn't be an accessible doc at all!");
437 LayersId
BrowserParent::GetLayersId() const {
438 if (!mRemoteLayerTreeOwner
.IsInitialized()) {
441 return mRemoteLayerTreeOwner
.GetLayersId();
444 BrowserBridgeParent
* BrowserParent::GetBrowserBridgeParent() const {
445 return mBrowserBridgeParent
;
448 BrowserHost
* BrowserParent::GetBrowserHost() const { return mBrowserHost
; }
450 ParentShowInfo
BrowserParent::GetShowInfo() {
451 TryCacheDPIAndScale();
454 mFrameElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::name
, name
);
455 // FIXME(emilio, bug 1606660): allowfullscreen should probably move to
457 bool allowFullscreen
=
458 mFrameElement
->HasAttr(kNameSpaceID_None
, nsGkAtoms::allowfullscreen
) ||
459 mFrameElement
->HasAttr(kNameSpaceID_None
,
460 nsGkAtoms::mozallowfullscreen
);
462 nsContentUtils::IsChromeDoc(mFrameElement
->OwnerDoc()) &&
463 mFrameElement
->HasAttr(kNameSpaceID_None
, nsGkAtoms::transparent
);
464 return ParentShowInfo(name
, allowFullscreen
, false, isTransparent
, mDPI
,
465 mRounding
, mDefaultScale
.scale
);
468 return ParentShowInfo(EmptyString(), false, false, false, mDPI
, mRounding
,
469 mDefaultScale
.scale
);
472 already_AddRefed
<nsIPrincipal
> BrowserParent::GetContentPrincipal() const {
473 nsCOMPtr
<nsIBrowser
> browser
=
474 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
475 NS_ENSURE_TRUE(browser
, nullptr);
477 RefPtr
<nsIPrincipal
> principal
;
480 rv
= browser
->GetContentPrincipal(getter_AddRefs(principal
));
481 NS_ENSURE_SUCCESS(rv
, nullptr);
483 return principal
.forget();
486 void BrowserParent::SetOwnerElement(Element
* aElement
) {
487 // If we held previous content then unregister for its events.
488 RemoveWindowListeners();
490 // If we change top-level documents then we need to change our
491 // registration with them.
492 RefPtr
<nsPIWindowRoot
> curTopLevelWin
, newTopLevelWin
;
494 curTopLevelWin
= nsContentUtils::GetWindowRoot(mFrameElement
->OwnerDoc());
497 newTopLevelWin
= nsContentUtils::GetWindowRoot(aElement
->OwnerDoc());
499 bool isSameTopLevelWin
= curTopLevelWin
== newTopLevelWin
;
500 if (mBrowserHost
&& curTopLevelWin
&& !isSameTopLevelWin
) {
501 curTopLevelWin
->RemoveBrowser(mBrowserHost
);
504 // Update to the new content, and register to listen for events from it.
505 mFrameElement
= aElement
;
507 if (mBrowserHost
&& newTopLevelWin
&& !isSameTopLevelWin
) {
508 newTopLevelWin
->AddBrowser(mBrowserHost
);
511 #if defined(XP_WIN) && defined(ACCESSIBILITY)
513 uintptr_t newWindowHandle
= 0;
514 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
516 reinterpret_cast<uintptr_t>(widget
->GetNativeData(NS_NATIVE_WINDOW
));
518 Unused
<< SendUpdateNativeWindowHandle(newWindowHandle
);
519 a11y::DocAccessibleParent
* doc
= GetTopLevelDocAccessible();
521 HWND hWnd
= reinterpret_cast<HWND
>(doc
->GetEmulatedWindowHandle());
523 HWND parentHwnd
= reinterpret_cast<HWND
>(newWindowHandle
);
524 if (parentHwnd
!= ::GetParent(hWnd
)) {
525 ::SetParent(hWnd
, parentHwnd
);
532 AddWindowListeners();
533 TryCacheDPIAndScale();
535 // Try to send down WidgetNativeData, now that this BrowserParent is
536 // associated with a widget.
537 nsCOMPtr
<nsIWidget
> widget
= GetTopLevelWidget();
539 WindowsHandle widgetNativeData
= reinterpret_cast<WindowsHandle
>(
540 widget
->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW
));
541 if (widgetNativeData
) {
542 Unused
<< SendSetWidgetNativeData(widgetNativeData
);
546 if (mRemoteLayerTreeOwner
.IsInitialized()) {
547 mRemoteLayerTreeOwner
.OwnerContentChanged();
550 // Set our BrowsingContext's embedder if we're not embedded within a
551 // BrowserBridgeParent.
552 if (!GetBrowserBridgeParent() && mBrowsingContext
&& mFrameElement
) {
553 mBrowsingContext
->SetEmbedderElement(mFrameElement
);
556 VisitChildren([aElement
](BrowserBridgeParent
* aBrowser
) {
557 if (auto* browserParent
= aBrowser
->GetBrowserParent()) {
558 browserParent
->SetOwnerElement(aElement
);
563 void BrowserParent::CacheFrameLoader(nsFrameLoader
* aFrameLoader
) {
564 mFrameLoader
= aFrameLoader
;
567 void BrowserParent::AddWindowListeners() {
569 if (nsCOMPtr
<nsPIDOMWindowOuter
> window
=
570 mFrameElement
->OwnerDoc()->GetWindow()) {
571 nsCOMPtr
<EventTarget
> eventTarget
= window
->GetTopWindowRoot();
573 eventTarget
->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
575 eventTarget
->AddEventListener(NS_LITERAL_STRING("fullscreenchange"),
582 void BrowserParent::RemoveWindowListeners() {
583 if (mFrameElement
&& mFrameElement
->OwnerDoc()->GetWindow()) {
584 nsCOMPtr
<nsPIDOMWindowOuter
> window
=
585 mFrameElement
->OwnerDoc()->GetWindow();
586 nsCOMPtr
<EventTarget
> eventTarget
= window
->GetTopWindowRoot();
588 eventTarget
->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
590 eventTarget
->RemoveEventListener(NS_LITERAL_STRING("fullscreenchange"),
596 void BrowserParent::DestroyInternal() {
597 UnsetTopLevelWebFocus(this);
598 UnsetLastMouseRemoteTarget(this);
600 RemoveWindowListeners();
603 if (a11y::DocAccessibleParent
* tabDoc
= GetTopLevelDocAccessible()) {
608 // If this fails, it's most likely due to a content-process crash,
609 // and auto-cleanup will kick in. Otherwise, the child side will
610 // destroy itself and send back __delete__().
611 Unused
<< SendDestroy();
614 // Let all PluginWidgets know we are tearing down. Prevents
615 // these objects from sending async events after the child side
617 const ManagedContainer
<PPluginWidgetParent
>& kids
=
618 ManagedPPluginWidgetParent();
619 for (auto iter
= kids
.ConstIter(); !iter
.Done(); iter
.Next()) {
620 static_cast<mozilla::plugins::PluginWidgetParent
*>(iter
.Get()->GetKey())
626 void BrowserParent::Destroy() {
627 // Aggressively release the window to avoid leaking the world in shutdown
629 mBrowserDOMWindow
= nullptr;
639 Manager()->NotifyTabDestroying();
641 mMarkedDestroying
= true;
644 mozilla::ipc::IPCResult
BrowserParent::RecvEnsureLayersConnected(
645 CompositorOptions
* aCompositorOptions
) {
646 if (mRemoteLayerTreeOwner
.IsInitialized()) {
647 mRemoteLayerTreeOwner
.EnsureLayersConnected(aCompositorOptions
);
652 mozilla::ipc::IPCResult
BrowserParent::Recv__delete__() {
653 MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
654 Manager()->NotifyTabDestroyed(mTabId
, mMarkedDestroying
);
658 void BrowserParent::ActorDestroy(ActorDestroyReason why
) {
659 ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(mTabId
);
661 if (mRemoteLayerTreeOwner
.IsInitialized()) {
662 // It's important to unmap layers after the remote browser has been
663 // destroyed, otherwise it may still send messages to the compositor which
664 // will reject them, causing assertions.
665 RemoveBrowserParentFromTable(mRemoteLayerTreeOwner
.GetLayersId());
666 mRemoteLayerTreeOwner
.Destroy();
669 // Even though BrowserParent::Destroy calls this, we need to do it here too in
671 BrowserParent::UnsetTopLevelWebFocus(this);
672 BrowserParent::UnsetLastMouseRemoteTarget(this);
674 if (why
== AbnormalShutdown
) {
675 // dom_reporting_header must also be enabled for the report to be sent.
676 if (StaticPrefs::dom_reporting_crash_enabled()) {
677 nsCOMPtr
<nsIPrincipal
> principal
= GetContentPrincipal();
680 nsAutoCString crash_reason
;
681 CrashReporter::GetAnnotation(OtherPid(),
682 CrashReporter::Annotation::MozCrashReason
,
684 // FIXME(arenevier): Find a less fragile way to identify that a crash
687 if (crash_reason
== "OOM" || crash_reason
== "OOM!" ||
688 StringBeginsWith(crash_reason
,
689 NS_LITERAL_CSTRING("[unhandlable oom]")) ||
690 StringBeginsWith(crash_reason
,
691 NS_LITERAL_CSTRING("Unhandlable OOM"))) {
695 CrashReport::Deliver(principal
, is_oom
);
700 // Prevent executing ContentParent::NotifyTabDestroying in
701 // BrowserParent::Destroy() called by frameLoader->DestroyComplete() below
702 // when tab crashes in contentprocess because ContentParent::ActorDestroy()
703 // in main process will be triggered before this function
704 // and remove the process information that
705 // ContentParent::NotifyTabDestroying need from mContentParentMap.
707 // When tab crashes in content process,
708 // there is no need to call ContentParent::NotifyTabDestroying
709 // because the jobs in ContentParent::NotifyTabDestroying
710 // will be done by ContentParent::ActorDestroy.
711 if (XRE_IsContentProcess() && why
== AbnormalShutdown
&& !mIsDestroyed
) {
716 // Tell our embedder that the tab is now going away unless we're an
717 // out-of-process iframe.
718 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader(true);
720 ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE
, false, nullptr);
722 if (mBrowsingContext
->IsTop()) {
723 // If this is a top-level BrowsingContext, tell the frameloader it's time
724 // to go away. Otherwise, this is a subframe crash, and we can keep the
725 // frameloader around.
726 frameLoader
->DestroyComplete();
729 // If this was a crash, tell our nsFrameLoader to fire crash events.
730 if (why
== AbnormalShutdown
) {
731 frameLoader
->MaybeNotifyCrashed(mBrowsingContext
, GetIPCChannel());
733 auto* bridge
= GetBrowserBridgeParent();
734 if (bridge
&& bridge
->CanSend() && !mBrowsingContext
->IsDiscarded()) {
735 MOZ_ASSERT(!mBrowsingContext
->IsTop());
737 // Set the owner process of the root context belonging to a crashed
738 // process to the embedding process, since we'll be showing the crashed
739 // page in that process.
740 mBrowsingContext
->SetOwnerProcessId(
741 bridge
->Manager()->Manager()->ChildID());
742 mBrowsingContext
->SetCurrentInnerWindowId(0);
744 // Tell the browser bridge to show the subframe crashed page.
745 Unused
<< bridge
->SendSubFrameCrashed();
750 mFrameLoader
= nullptr;
753 mozilla::ipc::IPCResult
BrowserParent::RecvMoveFocus(
754 const bool& aForward
, const bool& aForDocumentNavigation
) {
755 LOGBROWSERFOCUS(("RecvMoveFocus %p, aForward: %d, aForDocumentNavigation: %d",
756 this, aForward
, aForDocumentNavigation
));
757 BrowserBridgeParent
* bridgeParent
= GetBrowserBridgeParent();
759 mozilla::Unused
<< bridgeParent
->SendMoveFocus(aForward
,
760 aForDocumentNavigation
);
764 nsCOMPtr
<nsIFocusManager
> fm
= nsFocusManager::GetFocusManager();
766 RefPtr
<Element
> dummy
;
770 ? (aForDocumentNavigation
771 ? static_cast<uint32_t>(
772 nsIFocusManager::MOVEFOCUS_FORWARDDOC
)
773 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARD
))
774 : (aForDocumentNavigation
775 ? static_cast<uint32_t>(
776 nsIFocusManager::MOVEFOCUS_BACKWARDDOC
)
777 : static_cast<uint32_t>(
778 nsIFocusManager::MOVEFOCUS_BACKWARD
));
779 fm
->MoveFocus(nullptr, mFrameElement
, type
, nsIFocusManager::FLAG_BYKEY
,
780 getter_AddRefs(dummy
));
785 mozilla::ipc::IPCResult
BrowserParent::RecvSizeShellTo(
786 const uint32_t& aFlags
, const int32_t& aWidth
, const int32_t& aHeight
,
787 const int32_t& aShellItemWidth
, const int32_t& aShellItemHeight
) {
788 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
790 nsCOMPtr
<nsIDocShell
> docShell
= mFrameElement
->OwnerDoc()->GetDocShell();
791 NS_ENSURE_TRUE(docShell
, IPC_OK());
793 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
794 nsresult rv
= docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
795 NS_ENSURE_SUCCESS(rv
, IPC_OK());
797 int32_t width
= aWidth
;
798 int32_t height
= aHeight
;
800 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX
) {
801 width
= mDimensions
.width
;
804 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY
) {
805 height
= mDimensions
.height
;
808 nsCOMPtr
<nsIAppWindow
> appWin(do_GetInterface(treeOwner
));
809 NS_ENSURE_TRUE(appWin
, IPC_OK());
810 appWin
->SizeShellToWithLimit(width
, height
, aShellItemWidth
,
816 mozilla::ipc::IPCResult
BrowserParent::RecvDropLinks(
817 nsTArray
<nsString
>&& aLinks
) {
818 nsCOMPtr
<nsIBrowser
> browser
=
819 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
821 // Verify that links have not been modified by the child. If links have
822 // not been modified then it's safe to load those links using the
823 // SystemPrincipal. If they have been modified by web content, then
824 // we use a NullPrincipal which still allows to load web links.
825 bool loadUsingSystemPrincipal
= true;
826 if (aLinks
.Length() != mVerifyDropLinks
.Length()) {
827 loadUsingSystemPrincipal
= false;
829 for (uint32_t i
= 0; i
< aLinks
.Length(); i
++) {
830 if (loadUsingSystemPrincipal
) {
831 if (!aLinks
[i
].Equals(mVerifyDropLinks
[i
])) {
832 loadUsingSystemPrincipal
= false;
836 mVerifyDropLinks
.Clear();
837 nsCOMPtr
<nsIPrincipal
> triggeringPrincipal
;
838 if (loadUsingSystemPrincipal
) {
839 triggeringPrincipal
= nsContentUtils::GetSystemPrincipal();
841 triggeringPrincipal
= NullPrincipal::CreateWithoutOriginAttributes();
843 browser
->DropLinks(aLinks
, triggeringPrincipal
);
848 mozilla::ipc::IPCResult
BrowserParent::RecvEvent(const RemoteDOMEvent
& aEvent
) {
849 RefPtr
<Event
> event
= aEvent
.mEvent
;
850 NS_ENSURE_TRUE(event
, IPC_OK());
852 RefPtr
<EventTarget
> target
= mFrameElement
;
853 NS_ENSURE_TRUE(target
, IPC_OK());
855 event
->SetOwner(target
);
857 target
->DispatchEvent(*event
);
861 bool BrowserParent::SendLoadRemoteScript(const nsString
& aURL
,
862 const bool& aRunInGlobalScope
) {
863 if (mCreatingWindow
) {
864 mDelayedFrameScripts
.AppendElement(
865 FrameScriptInfo(aURL
, aRunInGlobalScope
));
869 MOZ_ASSERT(mDelayedFrameScripts
.IsEmpty());
870 return PBrowserParent::SendLoadRemoteScript(aURL
, aRunInGlobalScope
);
873 void BrowserParent::LoadURL(nsIURI
* aURI
) {
883 if (mCreatingWindow
) {
884 // Don't send the message if the child wants to load its own URL.
885 MOZ_ASSERT(mDelayedURL
.IsEmpty());
890 Unused
<< SendLoadURL(spec
, GetShowInfo());
893 void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID
) {
894 MOZ_ASSERT(aPendingSwitchID
!= 0);
896 if (NS_WARN_IF(mIsDestroyed
)) {
900 Unused
<< SendResumeLoad(aPendingSwitchID
, GetShowInfo());
903 void BrowserParent::InitRendering() {
904 if (mRemoteLayerTreeOwner
.IsInitialized()) {
907 mRemoteLayerTreeOwner
.Initialize(this);
909 layers::LayersId layersId
= mRemoteLayerTreeOwner
.GetLayersId();
910 AddBrowserParentToTable(layersId
, this);
912 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
914 nsIFrame
* frame
= frameLoader
->GetPrimaryFrameOfOwningContent();
916 frame
->InvalidateFrame();
920 TextureFactoryIdentifier textureFactoryIdentifier
;
921 mRemoteLayerTreeOwner
.GetTextureFactoryIdentifier(&textureFactoryIdentifier
);
922 Unused
<< SendInitRendering(textureFactoryIdentifier
, layersId
,
923 mRemoteLayerTreeOwner
.GetCompositorOptions(),
924 mRemoteLayerTreeOwner
.IsLayersConnected());
926 RefPtr
<nsIWidget
> widget
= GetTopLevelWidget();
928 ScreenIntMargin safeAreaInsets
= widget
->GetSafeAreaInsets();
929 Unused
<< SendSafeAreaInsetsChanged(safeAreaInsets
);
932 #if defined(MOZ_WIDGET_ANDROID)
933 if (XRE_IsParentProcess()) {
936 Unused
<< SendDynamicToolbarMaxHeightChanged(
937 widget
->GetDynamicToolbarMaxHeight());
942 bool BrowserParent::AttachLayerManager() {
943 return !!mRemoteLayerTreeOwner
.AttachLayerManager();
946 void BrowserParent::MaybeShowFrame() {
947 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
951 frameLoader
->MaybeShowFrame();
954 bool BrowserParent::Show(const OwnerShowInfo
& aOwnerInfo
) {
955 mDimensions
= aOwnerInfo
.size();
960 MOZ_ASSERT(mRemoteLayerTreeOwner
.IsInitialized());
961 if (!mRemoteLayerTreeOwner
.AttachLayerManager()) {
965 mSizeMode
= aOwnerInfo
.sizeMode();
966 Unused
<< SendShow(GetShowInfo(), aOwnerInfo
);
970 mozilla::ipc::IPCResult
BrowserParent::RecvSetDimensions(
971 const uint32_t& aFlags
, const int32_t& aX
, const int32_t& aY
,
972 const int32_t& aCx
, const int32_t& aCy
, const double& aScale
) {
973 MOZ_ASSERT(!(aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER
),
974 "We should never see DIM_FLAGS_SIZE_INNER here!");
976 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
977 nsCOMPtr
<nsIDocShell
> docShell
= mFrameElement
->OwnerDoc()->GetDocShell();
978 NS_ENSURE_TRUE(docShell
, IPC_OK());
979 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
980 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
981 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
= do_QueryInterface(treeOwner
);
982 NS_ENSURE_TRUE(treeOwnerAsWin
, IPC_OK());
984 // We only care about the parameters that actually changed, see more details
985 // in `BrowserChild::SetDimensions()`.
986 // Note that `BrowserChild::SetDimensions()` may be called before receiving
987 // our `SendUIResolutionChanged()` call. Therefore, if given each cordinate
988 // shouldn't be ignored, we need to recompute it if DPI has been changed.
989 // And also note that don't use `mDefaultScale.scale` here since it may be
990 // different from the result of `GetUnscaledDevicePixelsPerCSSPixel()`.
992 treeOwnerAsWin
->GetUnscaledDevicePixelsPerCSSPixel(¤tScale
);
996 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
) {
997 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X
) {
999 treeOwnerAsWin
->GetPosition(&x
, &unused
);
1000 } else if (aScale
!= currentScale
) {
1001 x
= x
* currentScale
/ aScale
;
1004 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y
) {
1006 treeOwnerAsWin
->GetPosition(&unused
, &y
);
1007 } else if (aScale
!= currentScale
) {
1008 y
= y
* currentScale
/ aScale
;
1014 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
) {
1015 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX
) {
1017 treeOwnerAsWin
->GetSize(&cx
, &unused
);
1018 } else if (aScale
!= currentScale
) {
1019 cx
= cx
* currentScale
/ aScale
;
1022 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY
) {
1024 treeOwnerAsWin
->GetSize(&unused
, &cy
);
1025 } else if (aScale
!= currentScale
) {
1026 cy
= cy
* currentScale
/ aScale
;
1030 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
&&
1031 aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
) {
1032 treeOwnerAsWin
->SetPositionAndSize(x
, y
, cx
, cy
, nsIBaseWindow::eRepaint
);
1036 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
) {
1037 treeOwnerAsWin
->SetPosition(x
, y
);
1038 mUpdatedDimensions
= false;
1043 if (aFlags
& nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
) {
1044 treeOwnerAsWin
->SetSize(cx
, cy
, true);
1048 MOZ_ASSERT(false, "Unknown flags!");
1049 return IPC_FAIL_NO_REASON(this);
1052 nsresult
BrowserParent::UpdatePosition() {
1053 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
1057 nsIntRect windowDims
;
1058 NS_ENSURE_SUCCESS(frameLoader
->GetWindowDimensions(windowDims
),
1060 UpdateDimensions(windowDims
, mDimensions
);
1064 void BrowserParent::UpdateDimensions(const nsIntRect
& rect
,
1065 const ScreenIntSize
& size
) {
1069 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1071 NS_WARNING("No widget found in BrowserParent::UpdateDimensions");
1075 hal::ScreenConfiguration config
;
1076 hal::GetCurrentScreenConfiguration(&config
);
1077 hal::ScreenOrientation orientation
= config
.orientation();
1078 LayoutDeviceIntPoint clientOffset
= GetClientOffset();
1079 LayoutDeviceIntPoint chromeOffset
= -GetChildProcessOffset();
1081 if (!mUpdatedDimensions
|| mOrientation
!= orientation
||
1082 mDimensions
!= size
|| !mRect
.IsEqualEdges(rect
) ||
1083 clientOffset
!= mClientOffset
|| chromeOffset
!= mChromeOffset
) {
1084 mUpdatedDimensions
= true;
1087 mOrientation
= orientation
;
1088 mClientOffset
= clientOffset
;
1089 mChromeOffset
= chromeOffset
;
1091 Unused
<< SendUpdateDimensions(GetDimensionInfo());
1095 DimensionInfo
BrowserParent::GetDimensionInfo() {
1096 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1098 CSSToLayoutDeviceScale widgetScale
= widget
->GetDefaultScale();
1100 LayoutDeviceIntRect devicePixelRect
= ViewAs
<LayoutDevicePixel
>(
1101 mRect
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
1102 LayoutDeviceIntSize devicePixelSize
= ViewAs
<LayoutDevicePixel
>(
1103 mDimensions
, PixelCastJustification::LayoutDeviceIsScreenForTabDims
);
1105 CSSRect unscaledRect
= devicePixelRect
/ widgetScale
;
1106 CSSSize unscaledSize
= devicePixelSize
/ widgetScale
;
1107 DimensionInfo
di(unscaledRect
, unscaledSize
, mOrientation
, mClientOffset
,
1112 void BrowserParent::SizeModeChanged(const nsSizeMode
& aSizeMode
) {
1113 if (!mIsDestroyed
&& aSizeMode
!= mSizeMode
) {
1114 mSizeMode
= aSizeMode
;
1115 Unused
<< SendSizeModeChanged(aSizeMode
);
1119 void BrowserParent::ThemeChanged() {
1120 if (!mIsDestroyed
) {
1121 // The theme has changed, and any cached values we had sent down
1122 // to the child have been invalidated. When this method is called,
1123 // LookAndFeel should have the up-to-date values, which we now
1124 // send down to the child. We do this for every remote tab for now,
1125 // but bug 1156934 has been filed to do it once per content process.
1126 Unused
<< SendThemeChanged(LookAndFeel::GetIntCache());
1130 #if defined(MOZ_WIDGET_ANDROID)
1131 void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight
) {
1132 if (!mIsDestroyed
) {
1133 Unused
<< SendDynamicToolbarMaxHeightChanged(aHeight
);
1137 void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset
) {
1138 if (!mIsDestroyed
) {
1139 Unused
<< SendDynamicToolbarOffsetChanged(aOffset
);
1144 void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent
& aEvent
,
1145 nsTArray
<uint32_t>& aCharCodes
) {
1146 if (!mIsDestroyed
) {
1147 // Note that we don't need to mark aEvent is posted to a remote process
1148 // because the event may be dispatched to it as normal keyboard event.
1149 // Therefore, we should use local copy to send it.
1150 WidgetKeyboardEvent
localEvent(aEvent
);
1151 Unused
<< SendHandleAccessKey(localEvent
, aCharCodes
);
1155 void BrowserParent::Activate() {
1156 LOGBROWSERFOCUS(("Activate %p", this));
1157 if (!mIsDestroyed
) {
1158 SetTopLevelWebFocus(this); // Intentionally inside "if"
1159 Unused
<< Manager()->SendActivate(this);
1163 void BrowserParent::Deactivate(bool aWindowLowering
) {
1164 LOGBROWSERFOCUS(("Deactivate %p", this));
1165 if (!aWindowLowering
) {
1166 UnsetTopLevelWebFocus(this); // Intentionally outside the next "if"
1168 if (!mIsDestroyed
) {
1169 BrowserParent::UnsetLastMouseRemoteTarget(this);
1170 Unused
<< Manager()->SendDeactivate(this);
1174 #ifdef ACCESSIBILITY
1175 a11y::PDocAccessibleParent
* BrowserParent::AllocPDocAccessibleParent(
1176 PDocAccessibleParent
* aParent
, const uint64_t&, const uint32_t&,
1177 const IAccessibleHolder
&) {
1178 // Reference freed in DeallocPDocAccessibleParent.
1179 return do_AddRef(new a11y::DocAccessibleParent()).take();
1182 bool BrowserParent::DeallocPDocAccessibleParent(PDocAccessibleParent
* aParent
) {
1183 // Free reference from AllocPDocAccessibleParent.
1184 static_cast<a11y::DocAccessibleParent
*>(aParent
)->Release();
1188 mozilla::ipc::IPCResult
BrowserParent::RecvPDocAccessibleConstructor(
1189 PDocAccessibleParent
* aDoc
, PDocAccessibleParent
* aParentDoc
,
1190 const uint64_t& aParentID
, const uint32_t& aMsaaID
,
1191 const IAccessibleHolder
& aDocCOMProxy
) {
1192 auto doc
= static_cast<a11y::DocAccessibleParent
*>(aDoc
);
1194 // If this tab is already shutting down just mark the new actor as shutdown
1195 // and ignore it. When the tab actor is destroyed it will be too.
1197 doc
->MarkAsShutdown();
1202 // A document should never directly be the parent of another document.
1203 // There should always be an outer doc accessible child of the outer
1204 // document containing the child.
1205 MOZ_ASSERT(aParentID
);
1207 return IPC_FAIL_NO_REASON(this);
1210 auto parentDoc
= static_cast<a11y::DocAccessibleParent
*>(aParentDoc
);
1211 mozilla::ipc::IPCResult added
= parentDoc
->AddChildDoc(doc
, aParentID
);
1221 MOZ_ASSERT(aDocCOMProxy
.IsNull());
1222 a11y::WrapperFor(doc
)->SetID(aMsaaID
);
1223 if (a11y::nsWinUtils::IsWindowEmulationStarted()) {
1224 doc
->SetEmulatedWindowHandle(parentDoc
->GetEmulatedWindowHandle());
1231 if (GetBrowserBridgeParent()) {
1232 // Iframe document rendered in a different process to its embedder.
1233 // In this case, we don't get aParentDoc and aParentID.
1234 MOZ_ASSERT(!aParentDoc
&& !aParentID
);
1235 doc
->SetTopLevelInContentProcess();
1237 MOZ_ASSERT(!aDocCOMProxy
.IsNull());
1238 RefPtr
<IAccessible
> proxy(aDocCOMProxy
.Get());
1239 doc
->SetCOMInterface(proxy
);
1242 doc
, a11y::Interfaces::DOCUMENT
| a11y::Interfaces::HYPERTEXT
);
1244 // This *must* be called after ProxyCreated because WrapperFor will fail
1246 a11y::AccessibleWrap
* wrapper
= a11y::WrapperFor(doc
);
1247 MOZ_ASSERT(wrapper
);
1248 wrapper
->SetID(aMsaaID
);
1250 a11y::DocAccessibleParent
* embedderDoc
;
1251 uint64_t embedderID
;
1252 Tie(embedderDoc
, embedderID
) = doc
->GetRemoteEmbedder();
1253 // It's possible the embedder accessible hasn't been set yet; e.g.
1254 // a hidden iframe. In that case, embedderDoc will be null and this will
1255 // be handled when the embedder is set.
1257 MOZ_ASSERT(embedderID
);
1258 mozilla::ipc::IPCResult added
=
1259 embedderDoc
->AddChildDoc(doc
, embedderID
,
1260 /* aCreating */ false);
1271 // null aParentDoc means this document is at the top level in the child
1272 // process. That means it makes no sense to get an id for an accessible
1273 // that is its parent.
1274 MOZ_ASSERT(!aParentID
);
1276 return IPC_FAIL_NO_REASON(this);
1280 a11y::DocManager::RemoteDocAdded(doc
);
1282 a11y::WrapperFor(doc
)->SetID(aMsaaID
);
1283 MOZ_ASSERT(!aDocCOMProxy
.IsNull());
1285 RefPtr
<IAccessible
> proxy(aDocCOMProxy
.Get());
1286 doc
->SetCOMInterface(proxy
);
1287 doc
->MaybeInitWindowEmulation();
1288 if (a11y::Accessible
* outerDoc
= doc
->OuterDocOfRemoteBrowser()) {
1289 doc
->SendParentCOMProxy(outerDoc
);
1297 PFilePickerParent
* BrowserParent::AllocPFilePickerParent(const nsString
& aTitle
,
1298 const int16_t& aMode
) {
1299 return new FilePickerParent(aTitle
, aMode
);
1302 bool BrowserParent::DeallocPFilePickerParent(PFilePickerParent
* actor
) {
1307 IPCResult
BrowserParent::RecvIndexedDBPermissionRequest(
1308 nsIPrincipal
* aPrincipal
, IndexedDBPermissionRequestResolver
&& aResolve
) {
1309 MOZ_ASSERT(NS_IsMainThread());
1311 nsCOMPtr
<nsIPrincipal
> principal(aPrincipal
);
1313 return IPC_FAIL_NO_REASON(this);
1316 if (NS_WARN_IF(!mFrameElement
)) {
1317 return IPC_FAIL_NO_REASON(this);
1320 RefPtr
<indexedDB::PermissionRequestHelper
> actor
=
1321 new indexedDB::PermissionRequestHelper(mFrameElement
, principal
,
1324 indexedDB::PermissionRequestBase::PermissionValue permission
;
1325 nsresult rv
= actor
->PromptIfNeeded(&permission
);
1326 if (NS_FAILED(rv
)) {
1327 return IPC_FAIL_NO_REASON(this);
1330 if (permission
!= indexedDB::PermissionRequestBase::kPermissionPrompt
) {
1331 aResolve(permission
);
1337 IPCResult
BrowserParent::RecvNewWindowGlobal(
1338 ManagedEndpoint
<PWindowGlobalParent
>&& aEndpoint
,
1339 const WindowGlobalInit
& aInit
) {
1340 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
1341 CanonicalBrowsingContext::Get(aInit
.context().mBrowsingContextId
);
1342 if (!browsingContext
) {
1343 return IPC_FAIL(this, "Cannot create for missing BrowsingContext");
1345 if (!aInit
.principal()) {
1346 return IPC_FAIL(this, "Cannot create without valid principal");
1349 // Construct our new WindowGlobalParent, bind, and initialize it.
1350 RefPtr
<WindowGlobalParent
> wgp
=
1351 WindowGlobalParent::CreateDisconnected(aInit
);
1352 BindPWindowGlobalEndpoint(std::move(aEndpoint
), wgp
);
1357 void BrowserParent::SendMouseEvent(const nsAString
& aType
, float aX
, float aY
,
1358 int32_t aButton
, int32_t aClickCount
,
1359 int32_t aModifiers
) {
1360 if (!mIsDestroyed
) {
1361 Unused
<< PBrowserParent::SendMouseEvent(nsString(aType
), aX
, aY
, aButton
,
1362 aClickCount
, aModifiers
);
1366 void BrowserParent::MouseEnterIntoWidget() {
1367 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1369 // When we mouseenter the tab, the tab's cursor should
1370 // become the current cursor. When we mouseexit, we stop.
1371 mTabSetsCursor
= true;
1372 if (mCursor
!= eCursorInvalid
) {
1373 widget
->SetCursor(mCursor
, mCustomCursor
, mCustomCursorHotspotX
,
1374 mCustomCursorHotspotY
);
1378 // Mark that we have missed a mouse enter event, so that
1379 // the next mouse event will create a replacement mouse
1380 // enter event and send it to the child.
1381 mIsMouseEnterIntoWidgetEventSuppressed
= true;
1384 void BrowserParent::SendRealMouseEvent(WidgetMouseEvent
& aEvent
) {
1389 // XXXedgar, if the synthesized mouse events could deliver to the correct
1390 // process directly (see
1391 // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably don't
1392 // need to check mReason then.
1393 if (aEvent
.mReason
== WidgetMouseEvent::eReal
) {
1394 sLastMouseRemoteTarget
= this;
1397 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1399 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1401 // When we mouseenter the tab, the tab's cursor should
1402 // become the current cursor. When we mouseexit, we stop.
1403 if (eMouseEnterIntoWidget
== aEvent
.mMessage
) {
1404 mTabSetsCursor
= true;
1405 if (mCursor
!= eCursorInvalid
) {
1406 widget
->SetCursor(mCursor
, mCustomCursor
, mCustomCursorHotspotX
,
1407 mCustomCursorHotspotY
);
1409 } else if (eMouseExitFromWidget
== aEvent
.mMessage
) {
1410 mTabSetsCursor
= false;
1413 if (!mIsReadyToHandleInputEvents
) {
1414 if (eMouseEnterIntoWidget
== aEvent
.mMessage
) {
1415 mIsMouseEnterIntoWidgetEventSuppressed
= true;
1416 } else if (eMouseExitFromWidget
== aEvent
.mMessage
) {
1417 mIsMouseEnterIntoWidgetEventSuppressed
= false;
1422 ScrollableLayerGuid guid
;
1424 ApzAwareEventRoutingToChild(&guid
, &blockId
, nullptr);
1426 bool isInputPriorityEventEnabled
= Manager()->IsInputPriorityEventEnabled();
1428 if (mIsMouseEnterIntoWidgetEventSuppressed
) {
1429 // In the case that the BrowserParent suppressed the eMouseEnterWidget event
1430 // due to its corresponding BrowserChild wasn't ready to handle it, we have
1431 // to resend it when the BrowserChild is ready.
1432 mIsMouseEnterIntoWidgetEventSuppressed
= false;
1433 WidgetMouseEvent
localEvent(aEvent
);
1434 localEvent
.mMessage
= eMouseEnterIntoWidget
;
1435 DebugOnly
<bool> ret
=
1436 isInputPriorityEventEnabled
1437 ? SendRealMouseButtonEvent(localEvent
, guid
, blockId
)
1438 : SendNormalPriorityRealMouseButtonEvent(localEvent
, guid
, blockId
);
1439 NS_WARNING_ASSERTION(
1440 ret
, "SendRealMouseButtonEvent(eMouseEnterIntoWidget) failed");
1441 MOZ_ASSERT(!ret
|| localEvent
.HasBeenPostedToRemoteProcess());
1444 if (eMouseMove
== aEvent
.mMessage
) {
1445 if (aEvent
.mReason
== WidgetMouseEvent::eSynthesized
) {
1446 DebugOnly
<bool> ret
=
1447 isInputPriorityEventEnabled
1448 ? SendSynthMouseMoveEvent(aEvent
, guid
, blockId
)
1449 : SendNormalPrioritySynthMouseMoveEvent(aEvent
, guid
, blockId
);
1450 NS_WARNING_ASSERTION(ret
, "SendSynthMouseMoveEvent() failed");
1451 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1454 DebugOnly
<bool> ret
=
1455 isInputPriorityEventEnabled
1456 ? SendRealMouseMoveEvent(aEvent
, guid
, blockId
)
1457 : SendNormalPriorityRealMouseMoveEvent(aEvent
, guid
, blockId
);
1458 NS_WARNING_ASSERTION(ret
, "SendRealMouseMoveEvent() failed");
1459 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1463 DebugOnly
<bool> ret
=
1464 isInputPriorityEventEnabled
1465 ? SendRealMouseButtonEvent(aEvent
, guid
, blockId
)
1466 : SendNormalPriorityRealMouseButtonEvent(aEvent
, guid
, blockId
);
1467 NS_WARNING_ASSERTION(ret
, "SendRealMouseButtonEvent() failed");
1468 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1471 LayoutDeviceToCSSScale
BrowserParent::GetLayoutDeviceToCSSScale() {
1472 Document
* doc
= (mFrameElement
? mFrameElement
->OwnerDoc() : nullptr);
1473 nsPresContext
* ctx
= (doc
? doc
->GetPresContext() : nullptr);
1474 return LayoutDeviceToCSSScale(
1475 ctx
? (float)ctx
->AppUnitsPerDevPixel() / AppUnitsPerCSSPixel() : 0.0f
);
1478 bool BrowserParent::QueryDropLinksForVerification() {
1479 // Before sending the dragEvent, we query the links being dragged and
1480 // store them on the parent, to make sure the child can not modify links.
1481 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
1483 NS_WARNING("No dragSession to query links for verification");
1487 RefPtr
<DataTransfer
> initialDataTransfer
= dragSession
->GetDataTransfer();
1488 if (!initialDataTransfer
) {
1489 NS_WARNING("No initialDataTransfer to query links for verification");
1493 nsCOMPtr
<nsIDroppedLinkHandler
> dropHandler
=
1494 do_GetService("@mozilla.org/content/dropped-link-handler;1");
1496 NS_WARNING("No dropHandler to query links for verification");
1500 // No more than one drop event can happen simultaneously; reset the link
1501 // verification array and store all links that are being dragged.
1502 mVerifyDropLinks
.Clear();
1504 nsTArray
<RefPtr
<nsIDroppedLinkItem
>> droppedLinkItems
;
1505 dropHandler
->QueryLinks(initialDataTransfer
, droppedLinkItems
);
1507 // Since the entire event is cancelled if one of the links is invalid,
1508 // we can store all links on the parent side without any prior
1509 // validation checks.
1510 nsresult rv
= NS_OK
;
1511 for (nsIDroppedLinkItem
* item
: droppedLinkItems
) {
1513 rv
= item
->GetUrl(tmp
);
1514 if (NS_FAILED(rv
)) {
1515 NS_WARNING("Failed to query url for verification");
1518 mVerifyDropLinks
.AppendElement(tmp
);
1520 rv
= item
->GetName(tmp
);
1521 if (NS_FAILED(rv
)) {
1522 NS_WARNING("Failed to query name for verification");
1525 mVerifyDropLinks
.AppendElement(tmp
);
1527 rv
= item
->GetType(tmp
);
1528 if (NS_FAILED(rv
)) {
1529 NS_WARNING("Failed to query type for verification");
1532 mVerifyDropLinks
.AppendElement(tmp
);
1534 if (NS_FAILED(rv
)) {
1535 mVerifyDropLinks
.Clear();
1541 void BrowserParent::SendRealDragEvent(WidgetDragEvent
& aEvent
,
1542 uint32_t aDragAction
,
1543 uint32_t aDropEffect
,
1544 nsIPrincipal
* aPrincipal
,
1545 nsIContentSecurityPolicy
* aCsp
) {
1546 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1549 MOZ_ASSERT(!Manager()->IsInputPriorityEventEnabled());
1550 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1551 if (aEvent
.mMessage
== eDrop
) {
1552 if (!QueryDropLinksForVerification()) {
1556 DebugOnly
<bool> ret
= PBrowserParent::SendRealDragEvent(
1557 aEvent
, aDragAction
, aDropEffect
, aPrincipal
, aCsp
);
1558 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealDragEvent() failed");
1559 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1562 void BrowserParent::SendMouseWheelEvent(WidgetWheelEvent
& aEvent
) {
1563 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1567 ScrollableLayerGuid guid
;
1569 ApzAwareEventRoutingToChild(&guid
, &blockId
, nullptr);
1570 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1571 DebugOnly
<bool> ret
=
1572 Manager()->IsInputPriorityEventEnabled()
1573 ? PBrowserParent::SendMouseWheelEvent(aEvent
, guid
, blockId
)
1574 : PBrowserParent::SendNormalPriorityMouseWheelEvent(aEvent
, guid
,
1577 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendMouseWheelEvent() failed");
1578 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1581 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchWheelEvent(
1582 const mozilla::WidgetWheelEvent
& aEvent
) {
1583 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1588 WidgetWheelEvent
localEvent(aEvent
);
1589 localEvent
.mWidget
= widget
;
1590 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1592 widget
->DispatchInputEvent(&localEvent
);
1596 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchMouseEvent(
1597 const mozilla::WidgetMouseEvent
& aEvent
) {
1598 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1603 WidgetMouseEvent
localEvent(aEvent
);
1604 localEvent
.mWidget
= widget
;
1605 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1607 widget
->DispatchInputEvent(&localEvent
);
1611 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchKeyboardEvent(
1612 const mozilla::WidgetKeyboardEvent
& aEvent
) {
1613 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1618 WidgetKeyboardEvent
localEvent(aEvent
);
1619 localEvent
.mWidget
= widget
;
1620 localEvent
.mRefPoint
= TransformChildToParent(localEvent
.mRefPoint
);
1622 widget
->DispatchInputEvent(&localEvent
);
1626 mozilla::ipc::IPCResult
BrowserParent::RecvRequestNativeKeyBindings(
1627 const uint32_t& aType
, const WidgetKeyboardEvent
& aEvent
,
1628 nsTArray
<CommandInt
>* aCommands
) {
1629 MOZ_ASSERT(aCommands
);
1630 MOZ_ASSERT(aCommands
->IsEmpty());
1632 nsIWidget::NativeKeyBindingsType keyBindingsType
=
1633 static_cast<nsIWidget::NativeKeyBindingsType
>(aType
);
1634 switch (keyBindingsType
) {
1635 case nsIWidget::NativeKeyBindingsForSingleLineEditor
:
1636 case nsIWidget::NativeKeyBindingsForMultiLineEditor
:
1637 case nsIWidget::NativeKeyBindingsForRichTextEditor
:
1640 return IPC_FAIL(this, "Invalid aType value");
1643 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1648 WidgetKeyboardEvent
localEvent(aEvent
);
1649 localEvent
.mWidget
= widget
;
1651 if (NS_FAILED(widget
->AttachNativeKeyEvent(localEvent
))) {
1655 if (localEvent
.InitEditCommandsFor(keyBindingsType
)) {
1656 *aCommands
= localEvent
.EditCommandsConstRef(keyBindingsType
).Clone();
1662 class SynthesizedEventObserver
: public nsIObserver
{
1666 SynthesizedEventObserver(BrowserParent
* aBrowserParent
,
1667 const uint64_t& aObserverId
)
1668 : mBrowserParent(aBrowserParent
), mObserverId(aObserverId
) {
1669 MOZ_ASSERT(mBrowserParent
);
1672 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
,
1673 const char16_t
* aData
) override
{
1674 if (!mBrowserParent
|| !mObserverId
) {
1675 // We already sent the notification, or we don't actually need to
1676 // send any notification at all.
1680 if (mBrowserParent
->IsDestroyed()) {
1681 // If this happens it's probably a bug in the test that's triggering this.
1683 "BrowserParent was unexpectedly destroyed during event "
1685 } else if (!mBrowserParent
->SendNativeSynthesisResponse(
1686 mObserverId
, nsCString(aTopic
))) {
1687 NS_WARNING("Unable to send native event synthesization response!");
1689 // Null out browserParent to indicate we already sent the response
1690 mBrowserParent
= nullptr;
1695 virtual ~SynthesizedEventObserver() = default;
1697 RefPtr
<BrowserParent
> mBrowserParent
;
1698 uint64_t mObserverId
;
1701 NS_IMPL_ISUPPORTS(SynthesizedEventObserver
, nsIObserver
)
1703 class MOZ_STACK_CLASS AutoSynthesizedEventResponder
{
1705 AutoSynthesizedEventResponder(BrowserParent
* aBrowserParent
,
1706 const uint64_t& aObserverId
, const char* aTopic
)
1707 : mObserver(new SynthesizedEventObserver(aBrowserParent
, aObserverId
)),
1710 ~AutoSynthesizedEventResponder() {
1711 // This may be a no-op if the observer already sent a response.
1712 mObserver
->Observe(nullptr, mTopic
, nullptr);
1715 nsIObserver
* GetObserver() { return mObserver
; }
1718 nsCOMPtr
<nsIObserver
> mObserver
;
1722 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeKeyEvent(
1723 const int32_t& aNativeKeyboardLayout
, const int32_t& aNativeKeyCode
,
1724 const uint32_t& aModifierFlags
, const nsString
& aCharacters
,
1725 const nsString
& aUnmodifiedCharacters
, const uint64_t& aObserverId
) {
1726 AutoSynthesizedEventResponder
responder(this, aObserverId
, "keyevent");
1727 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1729 widget
->SynthesizeNativeKeyEvent(
1730 aNativeKeyboardLayout
, aNativeKeyCode
, aModifierFlags
, aCharacters
,
1731 aUnmodifiedCharacters
, responder
.GetObserver());
1736 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseEvent(
1737 const LayoutDeviceIntPoint
& aPoint
, const uint32_t& aNativeMessage
,
1738 const uint32_t& aModifierFlags
, const uint64_t& aObserverId
) {
1739 AutoSynthesizedEventResponder
responder(this, aObserverId
, "mouseevent");
1740 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1742 widget
->SynthesizeNativeMouseEvent(aPoint
, aNativeMessage
, aModifierFlags
,
1743 responder
.GetObserver());
1748 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseMove(
1749 const LayoutDeviceIntPoint
& aPoint
, const uint64_t& aObserverId
) {
1750 AutoSynthesizedEventResponder
responder(this, aObserverId
, "mousemove");
1751 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1753 widget
->SynthesizeNativeMouseMove(aPoint
, responder
.GetObserver());
1758 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeMouseScrollEvent(
1759 const LayoutDeviceIntPoint
& aPoint
, const uint32_t& aNativeMessage
,
1760 const double& aDeltaX
, const double& aDeltaY
, const double& aDeltaZ
,
1761 const uint32_t& aModifierFlags
, const uint32_t& aAdditionalFlags
,
1762 const uint64_t& aObserverId
) {
1763 AutoSynthesizedEventResponder
responder(this, aObserverId
,
1764 "mousescrollevent");
1765 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1767 widget
->SynthesizeNativeMouseScrollEvent(
1768 aPoint
, aNativeMessage
, aDeltaX
, aDeltaY
, aDeltaZ
, aModifierFlags
,
1769 aAdditionalFlags
, responder
.GetObserver());
1774 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchPoint(
1775 const uint32_t& aPointerId
, const TouchPointerState
& aPointerState
,
1776 const LayoutDeviceIntPoint
& aPoint
, const double& aPointerPressure
,
1777 const uint32_t& aPointerOrientation
, const uint64_t& aObserverId
) {
1778 AutoSynthesizedEventResponder
responder(this, aObserverId
, "touchpoint");
1779 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1781 widget
->SynthesizeNativeTouchPoint(aPointerId
, aPointerState
, aPoint
,
1782 aPointerPressure
, aPointerOrientation
,
1783 responder
.GetObserver());
1788 mozilla::ipc::IPCResult
BrowserParent::RecvSynthesizeNativeTouchTap(
1789 const LayoutDeviceIntPoint
& aPoint
, const bool& aLongTap
,
1790 const uint64_t& aObserverId
) {
1791 AutoSynthesizedEventResponder
responder(this, aObserverId
, "touchtap");
1792 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1794 widget
->SynthesizeNativeTouchTap(aPoint
, aLongTap
, responder
.GetObserver());
1799 mozilla::ipc::IPCResult
BrowserParent::RecvClearNativeTouchSequence(
1800 const uint64_t& aObserverId
) {
1801 AutoSynthesizedEventResponder
responder(this, aObserverId
, "cleartouch");
1802 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1804 widget
->ClearNativeTouchSequence(responder
.GetObserver());
1809 mozilla::ipc::IPCResult
1810 BrowserParent::RecvSetPrefersReducedMotionOverrideForTest(const bool& aValue
) {
1811 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1813 widget
->SetPrefersReducedMotionOverrideForTest(aValue
);
1818 mozilla::ipc::IPCResult
1819 BrowserParent::RecvResetPrefersReducedMotionOverrideForTest() {
1820 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1822 widget
->ResetPrefersReducedMotionOverrideForTest();
1827 void BrowserParent::SendRealKeyEvent(WidgetKeyboardEvent
& aEvent
) {
1828 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1831 aEvent
.mRefPoint
= TransformParentToChild(aEvent
.mRefPoint
);
1833 if (aEvent
.mMessage
== eKeyPress
) {
1834 // XXX Should we do this only when input context indicates an editor having
1835 // focus and the key event won't cause inputting text?
1836 aEvent
.InitAllEditCommands();
1838 aEvent
.PreventNativeKeyBindings();
1840 DebugOnly
<bool> ret
=
1841 Manager()->IsInputPriorityEventEnabled()
1842 ? PBrowserParent::SendRealKeyEvent(aEvent
)
1843 : PBrowserParent::SendNormalPriorityRealKeyEvent(aEvent
);
1845 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealKeyEvent() failed");
1846 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1849 void BrowserParent::SendRealTouchEvent(WidgetTouchEvent
& aEvent
) {
1850 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
1854 // PresShell::HandleEventInternal adds touches on touch end/cancel. This
1855 // confuses remote content and the panning and zooming logic into thinking
1856 // that the added touches are part of the touchend/cancel, when actually
1858 if (aEvent
.mMessage
== eTouchEnd
|| aEvent
.mMessage
== eTouchCancel
) {
1859 for (int i
= aEvent
.mTouches
.Length() - 1; i
>= 0; i
--) {
1860 if (!aEvent
.mTouches
[i
]->mChanged
) {
1861 aEvent
.mTouches
.RemoveElementAt(i
);
1867 ApzAwareEventRoutingToChild(&apzData
.guid
, &apzData
.blockId
,
1868 &apzData
.apzResponse
);
1874 for (uint32_t i
= 0; i
< aEvent
.mTouches
.Length(); i
++) {
1875 aEvent
.mTouches
[i
]->mRefPoint
=
1876 TransformParentToChild(aEvent
.mTouches
[i
]->mRefPoint
);
1879 static uint32_t sConsecutiveTouchMoveCount
= 0;
1880 if (aEvent
.mMessage
== eTouchMove
) {
1881 ++sConsecutiveTouchMoveCount
;
1882 SendRealTouchMoveEvent(aEvent
, apzData
, sConsecutiveTouchMoveCount
);
1886 sConsecutiveTouchMoveCount
= 0;
1887 DebugOnly
<bool> ret
=
1888 Manager()->IsInputPriorityEventEnabled()
1889 ? PBrowserParent::SendRealTouchEvent(
1890 aEvent
, apzData
.guid
, apzData
.blockId
, apzData
.apzResponse
)
1891 : PBrowserParent::SendNormalPriorityRealTouchEvent(
1892 aEvent
, apzData
.guid
, apzData
.blockId
, apzData
.apzResponse
);
1894 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealTouchEvent() failed");
1895 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1898 void BrowserParent::SendRealTouchMoveEvent(
1899 WidgetTouchEvent
& aEvent
, APZData
& aAPZData
,
1900 uint32_t aConsecutiveTouchMoveCount
) {
1901 // Touchmove handling is complicated, since IPC compression should be used
1902 // only when there are consecutive touch objects for the same touch on the
1903 // same BrowserParent. IPC compression can be disabled by switching to
1904 // different IPC message.
1905 static bool sIPCMessageType1
= true;
1906 static TabId
sLastTargetBrowserParent(0);
1907 static Maybe
<APZData
> sPreviousAPZData
;
1908 // Artificially limit max touch points to 10. That should be in practise
1909 // more than enough.
1910 const uint32_t kMaxTouchMoveIdentifiers
= 10;
1911 static Maybe
<int32_t> sLastTouchMoveIdentifiers
[kMaxTouchMoveIdentifiers
];
1913 // Returns true if aIdentifiers contains all the touches in
1914 // sLastTouchMoveIdentifiers.
1915 auto LastTouchMoveIdentifiersContainedIn
=
1916 [&](const nsTArray
<int32_t>& aIdentifiers
) -> bool {
1917 for (Maybe
<int32_t>& entry
: sLastTouchMoveIdentifiers
) {
1918 if (entry
.isSome() && !aIdentifiers
.Contains(entry
.value())) {
1925 // Cache touch identifiers in sLastTouchMoveIdentifiers array to be used
1926 // when checking whether compression can be done for the next touchmove.
1927 auto SetLastTouchMoveIdentifiers
=
1928 [&](const nsTArray
<int32_t>& aIdentifiers
) {
1929 for (Maybe
<int32_t>& entry
: sLastTouchMoveIdentifiers
) {
1933 MOZ_ASSERT(aIdentifiers
.Length() <= kMaxTouchMoveIdentifiers
);
1934 for (uint32_t j
= 0; j
< aIdentifiers
.Length(); ++j
) {
1935 sLastTouchMoveIdentifiers
[j
].emplace(aIdentifiers
[j
]);
1939 AutoTArray
<int32_t, kMaxTouchMoveIdentifiers
> changedTouches
;
1940 bool preventCompression
= !StaticPrefs::dom_events_compress_touchmove() ||
1941 // Ensure the very first touchmove isn't overridden
1942 // by the second one, so that web pages can get
1943 // accurate coordinates for the first touchmove.
1944 aConsecutiveTouchMoveCount
< 3 ||
1945 sPreviousAPZData
.isNothing() ||
1946 sPreviousAPZData
.value() != aAPZData
||
1947 sLastTargetBrowserParent
!= GetTabId() ||
1948 aEvent
.mTouches
.Length() > kMaxTouchMoveIdentifiers
;
1950 if (!preventCompression
) {
1951 for (RefPtr
<Touch
>& touch
: aEvent
.mTouches
) {
1952 if (touch
->mChanged
) {
1953 changedTouches
.AppendElement(touch
->mIdentifier
);
1957 // Prevent compression if the new event has fewer or different touches
1958 // than the old one.
1959 preventCompression
= !LastTouchMoveIdentifiersContainedIn(changedTouches
);
1962 if (preventCompression
) {
1963 sIPCMessageType1
= !sIPCMessageType1
;
1966 // Update the last touch move identifiers always, so that when the next
1967 // event comes in, the new identifiers can be compared to the old ones.
1968 // If the pref is disabled, this just does a quick small loop.
1969 SetLastTouchMoveIdentifiers(changedTouches
);
1970 sPreviousAPZData
.reset();
1971 sPreviousAPZData
.emplace(aAPZData
);
1972 sLastTargetBrowserParent
= GetTabId();
1974 DebugOnly
<bool> ret
= true;
1975 if (sIPCMessageType1
) {
1977 Manager()->IsInputPriorityEventEnabled()
1978 ? PBrowserParent::SendRealTouchMoveEvent(
1979 aEvent
, aAPZData
.guid
, aAPZData
.blockId
, aAPZData
.apzResponse
)
1980 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent(
1981 aEvent
, aAPZData
.guid
, aAPZData
.blockId
,
1982 aAPZData
.apzResponse
);
1985 Manager()->IsInputPriorityEventEnabled()
1986 ? PBrowserParent::SendRealTouchMoveEvent2(
1987 aEvent
, aAPZData
.guid
, aAPZData
.blockId
, aAPZData
.apzResponse
)
1988 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent2(
1989 aEvent
, aAPZData
.guid
, aAPZData
.blockId
,
1990 aAPZData
.apzResponse
);
1993 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendRealTouchMoveEvent() failed");
1994 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
1997 void BrowserParent::SendPluginEvent(WidgetPluginEvent
& aEvent
) {
1998 DebugOnly
<bool> ret
= PBrowserParent::SendPluginEvent(aEvent
);
1999 NS_WARNING_ASSERTION(ret
, "PBrowserParent::SendPluginEvent() failed");
2000 MOZ_ASSERT(!ret
|| aEvent
.HasBeenPostedToRemoteProcess());
2003 bool BrowserParent::SendHandleTap(TapType aType
,
2004 const LayoutDevicePoint
& aPoint
,
2005 Modifiers aModifiers
,
2006 const ScrollableLayerGuid
& aGuid
,
2007 uint64_t aInputBlockId
) {
2008 if (mIsDestroyed
|| !mIsReadyToHandleInputEvents
) {
2011 if ((aType
== TapType::eSingleTap
|| aType
== TapType::eSecondTap
)) {
2012 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
2014 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
2016 RefPtr
<Element
> element
= frameLoader
->GetOwnerContent();
2018 fm
->SetFocus(element
, nsIFocusManager::FLAG_BYMOUSE
|
2019 nsIFocusManager::FLAG_BYTOUCH
|
2020 nsIFocusManager::FLAG_NOSCROLL
);
2025 return Manager()->IsInputPriorityEventEnabled()
2026 ? PBrowserParent::SendHandleTap(aType
,
2027 TransformParentToChild(aPoint
),
2028 aModifiers
, aGuid
, aInputBlockId
)
2029 : PBrowserParent::SendNormalPriorityHandleTap(
2030 aType
, TransformParentToChild(aPoint
), aModifiers
, aGuid
,
2034 mozilla::ipc::IPCResult
BrowserParent::RecvSyncMessage(
2035 const nsString
& aMessage
, const ClonedMessageData
& aData
,
2036 nsTArray
<StructuredCloneData
>* aRetVal
) {
2037 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvSyncMessage",
2039 MMPrinter::Print("BrowserParent::RecvSyncMessage", aMessage
, aData
);
2041 StructuredCloneData data
;
2042 ipc::UnpackClonedMessageDataForParent(aData
, data
);
2044 if (!ReceiveMessage(aMessage
, true, &data
, aRetVal
)) {
2045 return IPC_FAIL_NO_REASON(this);
2050 mozilla::ipc::IPCResult
BrowserParent::RecvAsyncMessage(
2051 const nsString
& aMessage
, const ClonedMessageData
& aData
) {
2052 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvAsyncMessage",
2054 MMPrinter::Print("BrowserParent::RecvAsyncMessage", aMessage
, aData
);
2056 StructuredCloneData data
;
2057 ipc::UnpackClonedMessageDataForParent(aData
, data
);
2059 if (!ReceiveMessage(aMessage
, false, &data
, nullptr)) {
2060 return IPC_FAIL_NO_REASON(this);
2065 mozilla::ipc::IPCResult
BrowserParent::RecvSetCursor(
2066 const nsCursor
& aCursor
, const bool& aHasCustomCursor
,
2067 const nsCString
& aCursorData
, const uint32_t& aWidth
,
2068 const uint32_t& aHeight
, const uint32_t& aStride
,
2069 const gfx::SurfaceFormat
& aFormat
, const uint32_t& aHotspotX
,
2070 const uint32_t& aHotspotY
, const bool& aForce
) {
2071 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2077 widget
->ClearCachedCursor();
2080 if (!mTabSetsCursor
) {
2084 nsCOMPtr
<imgIContainer
> cursorImage
;
2085 if (aHasCustomCursor
) {
2086 if (aHeight
* aStride
!= aCursorData
.Length() ||
2087 aStride
< aWidth
* gfx::BytesPerPixel(aFormat
)) {
2088 return IPC_FAIL(this, "Invalid custom cursor data");
2090 const gfx::IntSize
size(aWidth
, aHeight
);
2091 RefPtr
<gfx::DataSourceSurface
> customCursor
=
2092 gfx::CreateDataSourceSurfaceFromData(
2094 reinterpret_cast<const uint8_t*>(aCursorData
.BeginReading()),
2097 RefPtr
<gfxDrawable
> drawable
= new gfxSurfaceDrawable(customCursor
, size
);
2098 cursorImage
= image::ImageOps::CreateFromDrawable(drawable
);
2101 widget
->SetCursor(aCursor
, cursorImage
, aHotspotX
, aHotspotY
);
2103 mCustomCursor
= cursorImage
;
2104 mCustomCursorHotspotX
= aHotspotX
;
2105 mCustomCursorHotspotY
= aHotspotY
;
2110 mozilla::ipc::IPCResult
BrowserParent::RecvSetLinkStatus(
2111 const nsString
& aStatus
) {
2112 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2113 if (!xulBrowserWindow
) {
2117 xulBrowserWindow
->SetOverLink(aStatus
);
2122 mozilla::ipc::IPCResult
BrowserParent::RecvShowTooltip(
2123 const uint32_t& aX
, const uint32_t& aY
, const nsString
& aTooltip
,
2124 const nsString
& aDirection
) {
2125 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2126 if (!xulBrowserWindow
) {
2130 // ShowTooltip will end up accessing XULElement properties in JS (specifically
2131 // BoxObject). However, to get it to JS, we need to make sure we're a
2132 // nsFrameLoaderOwner, which implies we're a XULFrameElement. We can then
2133 // safely pass Element into JS.
2134 RefPtr
<nsFrameLoaderOwner
> flo
= do_QueryObject(mFrameElement
);
2135 if (!flo
) return IPC_OK();
2137 nsCOMPtr
<Element
> el
= do_QueryInterface(flo
);
2138 if (!el
) return IPC_OK();
2140 xulBrowserWindow
->ShowTooltip(aX
, aY
, aTooltip
, aDirection
, el
);
2144 mozilla::ipc::IPCResult
BrowserParent::RecvHideTooltip() {
2145 nsCOMPtr
<nsIXULBrowserWindow
> xulBrowserWindow
= GetXULBrowserWindow();
2146 if (!xulBrowserWindow
) {
2150 xulBrowserWindow
->HideTooltip();
2154 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEFocus(
2155 const ContentCache
& aContentCache
, const IMENotification
& aIMENotification
,
2156 NotifyIMEFocusResolver
&& aResolve
) {
2161 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2163 aResolve(IMENotificationRequests());
2167 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2168 IMEStateManager::NotifyIME(aIMENotification
, widget
, this);
2170 IMENotificationRequests requests
;
2171 if (aIMENotification
.mMessage
== NOTIFY_IME_OF_FOCUS
) {
2172 requests
= widget
->IMENotificationRequestsRef();
2179 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMETextChange(
2180 const ContentCache
& aContentCache
,
2181 const IMENotification
& aIMENotification
) {
2182 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2183 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2186 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2187 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2191 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMECompositionUpdate(
2192 const ContentCache
& aContentCache
,
2193 const IMENotification
& aIMENotification
) {
2194 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2195 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2198 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2199 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2203 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMESelection(
2204 const ContentCache
& aContentCache
,
2205 const IMENotification
& aIMENotification
) {
2206 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2207 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2210 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2211 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2215 mozilla::ipc::IPCResult
BrowserParent::RecvUpdateContentCache(
2216 const ContentCache
& aContentCache
) {
2217 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2218 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2222 mContentCache
.AssignContent(aContentCache
, widget
);
2226 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEMouseButtonEvent(
2227 const IMENotification
& aIMENotification
, bool* aConsumedByIME
) {
2228 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2229 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2230 *aConsumedByIME
= false;
2233 nsresult rv
= IMEStateManager::NotifyIME(aIMENotification
, widget
, this);
2234 *aConsumedByIME
= rv
== NS_SUCCESS_EVENT_CONSUMED
;
2238 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyIMEPositionChange(
2239 const ContentCache
& aContentCache
,
2240 const IMENotification
& aIMENotification
) {
2241 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2242 if (!widget
|| !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2245 mContentCache
.AssignContent(aContentCache
, widget
, &aIMENotification
);
2246 mContentCache
.MaybeNotifyIME(widget
, aIMENotification
);
2250 mozilla::ipc::IPCResult
BrowserParent::RecvOnEventNeedingAckHandled(
2251 const EventMessage
& aMessage
) {
2252 // This is called when the child process receives WidgetCompositionEvent or
2253 // WidgetSelectionEvent.
2254 // FYI: Don't check if widget is nullptr here because it's more important to
2255 // notify mContentCahce of this than handling something in it.
2256 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
2258 // While calling OnEventNeedingAckHandled(), BrowserParent *might* be
2259 // destroyed since it may send notifications to IME.
2260 RefPtr
<BrowserParent
> kungFuDeathGrip(this);
2261 mContentCache
.OnEventNeedingAckHandled(widget
, aMessage
);
2265 void BrowserParent::HandledWindowedPluginKeyEvent(
2266 const NativeEventData
& aKeyEventData
, bool aIsConsumed
) {
2267 DebugOnly
<bool> ok
=
2268 SendHandledWindowedPluginKeyEvent(aKeyEventData
, aIsConsumed
);
2269 NS_WARNING_ASSERTION(ok
, "SendHandledWindowedPluginKeyEvent failed");
2272 mozilla::ipc::IPCResult
BrowserParent::RecvOnWindowedPluginKeyEvent(
2273 const NativeEventData
& aKeyEventData
) {
2274 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2275 if (NS_WARN_IF(!widget
)) {
2276 // Notifies the plugin process of the key event being not consumed by us.
2277 HandledWindowedPluginKeyEvent(aKeyEventData
, false);
2280 nsresult rv
= widget
->OnWindowedPluginKeyEvent(aKeyEventData
, this);
2281 if (NS_WARN_IF(NS_FAILED(rv
))) {
2282 // Notifies the plugin process of the key event being not consumed by us.
2283 HandledWindowedPluginKeyEvent(aKeyEventData
, false);
2287 // If the key event is posted to another process, we need to wait a call
2288 // of HandledWindowedPluginKeyEvent(). So, nothing to do here in this case.
2289 if (rv
== NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY
) {
2293 // Otherwise, the key event is handled synchronously. Let's notify the
2294 // plugin process of the key event's result.
2295 bool consumed
= (rv
== NS_SUCCESS_EVENT_CONSUMED
);
2296 HandledWindowedPluginKeyEvent(aKeyEventData
, consumed
);
2301 mozilla::ipc::IPCResult
BrowserParent::RecvRequestFocus(
2302 const bool& aCanRaise
, const CallerType aCallerType
) {
2303 LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise
));
2304 if (BrowserBridgeParent
* bridgeParent
= GetBrowserBridgeParent()) {
2305 mozilla::Unused
<< bridgeParent
->SendRequestFocus(aCanRaise
, aCallerType
);
2309 if (!mFrameElement
) {
2313 nsContentUtils::RequestFrameFocus(*mFrameElement
, aCanRaise
, aCallerType
);
2317 mozilla::ipc::IPCResult
BrowserParent::RecvWheelZoomChange(bool aIncrease
) {
2318 RefPtr
<BrowsingContext
> bc
= GetBrowsingContext();
2323 bc
->Canonical()->DispatchWheelZoomChange(aIncrease
);
2327 mozilla::ipc::IPCResult
BrowserParent::RecvEnableDisableCommands(
2328 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsString
& aAction
,
2329 nsTArray
<nsCString
>&& aEnabledCommands
,
2330 nsTArray
<nsCString
>&& aDisabledCommands
) {
2331 if (aContext
.IsNullOrDiscarded()) {
2335 nsCOMPtr
<nsIBrowserController
> browserController
=
2336 do_QueryActor("Controllers", aContext
.get_canonical());
2337 if (browserController
) {
2338 browserController
->EnableDisableCommands(aAction
, aEnabledCommands
,
2345 LayoutDeviceIntPoint
BrowserParent::TransformPoint(
2346 const LayoutDeviceIntPoint
& aPoint
,
2347 const LayoutDeviceToLayoutDeviceMatrix4x4
& aMatrix
) {
2348 LayoutDevicePoint
floatPoint(aPoint
);
2349 LayoutDevicePoint floatTransformed
= TransformPoint(floatPoint
, aMatrix
);
2350 // The next line loses precision if an out-of-process iframe
2351 // has been scaled or rotated.
2352 return RoundedToInt(floatTransformed
);
2355 LayoutDevicePoint
BrowserParent::TransformPoint(
2356 const LayoutDevicePoint
& aPoint
,
2357 const LayoutDeviceToLayoutDeviceMatrix4x4
& aMatrix
) {
2358 return aMatrix
.TransformPoint(aPoint
);
2361 LayoutDeviceIntPoint
BrowserParent::TransformParentToChild(
2362 const LayoutDeviceIntPoint
& aPoint
) {
2363 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2364 GetChildToParentConversionMatrix();
2365 if (!matrix
.Invert()) {
2366 return LayoutDeviceIntPoint(0, 0);
2368 return TransformPoint(aPoint
, matrix
);
2371 LayoutDevicePoint
BrowserParent::TransformParentToChild(
2372 const LayoutDevicePoint
& aPoint
) {
2373 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2374 GetChildToParentConversionMatrix();
2375 if (!matrix
.Invert()) {
2376 return LayoutDevicePoint(0.0, 0.0);
2378 return TransformPoint(aPoint
, matrix
);
2381 LayoutDeviceIntPoint
BrowserParent::TransformChildToParent(
2382 const LayoutDeviceIntPoint
& aPoint
) {
2383 return TransformPoint(aPoint
, GetChildToParentConversionMatrix());
2386 LayoutDevicePoint
BrowserParent::TransformChildToParent(
2387 const LayoutDevicePoint
& aPoint
) {
2388 return TransformPoint(aPoint
, GetChildToParentConversionMatrix());
2391 LayoutDeviceIntRect
BrowserParent::TransformChildToParent(
2392 const LayoutDeviceIntRect
& aRect
) {
2393 LayoutDeviceToLayoutDeviceMatrix4x4 matrix
=
2394 GetChildToParentConversionMatrix();
2395 LayoutDeviceRect
floatRect(aRect
);
2396 // The outcome is not ideal if an out-of-process iframe has been rotated
2397 LayoutDeviceRect floatTransformed
= matrix
.TransformBounds(floatRect
);
2398 // The next line loses precision if an out-of-process iframe
2399 // has been scaled or rotated.
2400 return RoundedToInt(floatTransformed
);
2403 LayoutDeviceToLayoutDeviceMatrix4x4
2404 BrowserParent::GetChildToParentConversionMatrix() {
2405 if (mChildToParentConversionMatrix
) {
2406 return *mChildToParentConversionMatrix
;
2408 LayoutDevicePoint
offset(-GetChildProcessOffset());
2409 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset
);
2412 void BrowserParent::SetChildToParentConversionMatrix(
2413 const Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
>& aMatrix
,
2414 const ScreenRect
& aRemoteDocumentRect
) {
2415 mChildToParentConversionMatrix
= aMatrix
;
2419 mozilla::Unused
<< SendChildToParentMatrix(ToUnknownMatrix(aMatrix
),
2420 aRemoteDocumentRect
);
2423 LayoutDeviceIntPoint
BrowserParent::GetChildProcessOffset() {
2424 // The "toplevel widget" in child processes is always at position
2425 // 0,0. Map the event coordinates to match that.
2427 LayoutDeviceIntPoint
offset(0, 0);
2428 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
2432 nsIFrame
* targetFrame
= frameLoader
->GetPrimaryFrameOfOwningContent();
2437 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2442 nsPresContext
* presContext
= targetFrame
->PresContext();
2443 nsIFrame
* rootFrame
= presContext
->PresShell()->GetRootFrame();
2444 nsView
* rootView
= rootFrame
? rootFrame
->GetView() : nullptr;
2449 // Note that we don't want to take into account transforms here:
2452 nsLayoutUtils::TransformPoint(targetFrame
, rootFrame
, pt
);
2454 // In practice, when transforms are applied to this frameLoader, we currently
2455 // get the wrong results whether we take transforms into account here or not.
2456 // But applying transforms here gives us the wrong results in all
2457 // circumstances when transforms are applied, unless they're purely
2458 // translational. It also gives us the wrong results whenever CSS transitions
2459 // are used to apply transforms, since the offeets aren't updated as the
2460 // transition is animated.
2462 // What we actually need to do is apply the transforms to the coordinates of
2463 // any events we send to the child, and reverse them for any screen
2464 // coordinates that we retrieve from the child.
2466 // TODO: Once we take into account transforms here, set viewportType
2467 // correctly. For now we use Visual as this means we don't apply
2468 // the layout-to-visual transform in TranslateViewToWidget().
2469 ViewportType viewportType
= ViewportType::Visual
;
2471 nsPoint pt
= targetFrame
->GetOffsetTo(rootFrame
);
2472 return -nsLayoutUtils::TranslateViewToWidget(presContext
, rootView
, pt
,
2473 viewportType
, widget
);
2476 LayoutDeviceIntPoint
BrowserParent::GetClientOffset() {
2477 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2478 nsCOMPtr
<nsIWidget
> docWidget
= GetDocWidget();
2480 if (widget
== docWidget
) {
2481 return widget
->GetClientOffset();
2484 return (docWidget
->GetClientOffset() +
2485 nsLayoutUtils::WidgetToWidgetOffset(widget
, docWidget
));
2488 void BrowserParent::StopIMEStateManagement() {
2492 Unused
<< SendStopIMEStateManagement();
2495 mozilla::ipc::IPCResult
BrowserParent::RecvReplyKeyEvent(
2496 const WidgetKeyboardEvent
& aEvent
) {
2497 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
2499 WidgetKeyboardEvent
localEvent(aEvent
);
2500 localEvent
.MarkAsHandledInRemoteProcess();
2502 // Here we convert the WidgetEvent that we received to an Event
2503 // to be able to dispatch it to the <browser> element as the target element.
2504 Document
* doc
= mFrameElement
->OwnerDoc();
2505 nsPresContext
* presContext
= doc
->GetPresContext();
2506 NS_ENSURE_TRUE(presContext
, IPC_OK());
2508 AutoHandlingUserInputStatePusher
userInpStatePusher(localEvent
.IsTrusted(),
2511 nsEventStatus status
= nsEventStatus_eIgnore
;
2513 // Handle access key in this process before dispatching reply event because
2514 // ESM handles it before dispatching the event to the DOM tree.
2515 if (localEvent
.mMessage
== eKeyPress
&&
2516 (localEvent
.ModifiersMatchWithAccessKey(AccessKeyType::eChrome
) ||
2517 localEvent
.ModifiersMatchWithAccessKey(AccessKeyType::eContent
))) {
2518 RefPtr
<EventStateManager
> esm
= presContext
->EventStateManager();
2519 AutoTArray
<uint32_t, 10> accessCharCodes
;
2520 localEvent
.GetAccessKeyCandidates(accessCharCodes
);
2521 if (esm
->HandleAccessKey(&localEvent
, presContext
, accessCharCodes
)) {
2522 status
= nsEventStatus_eConsumeNoDefault
;
2526 EventDispatcher::Dispatch(mFrameElement
, presContext
, &localEvent
, nullptr,
2529 if (!localEvent
.DefaultPrevented() &&
2530 !localEvent
.mFlags
.mIsSynthesizedForTests
) {
2531 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2533 widget
->PostHandleKeyEvent(&localEvent
);
2534 localEvent
.StopPropagation();
2541 mozilla::ipc::IPCResult
BrowserParent::RecvAccessKeyNotHandled(
2542 const WidgetKeyboardEvent
& aEvent
) {
2543 NS_ENSURE_TRUE(mFrameElement
, IPC_OK());
2545 // This is called only when this process had focus and HandleAccessKey
2546 // message was posted to all remote process and each remote process didn't
2547 // execute any content access keys.
2548 // XXX If there were two or more remote processes, this may be called
2549 // twice or more for a keyboard event, that must be a bug. But how to
2550 // detect if received event has already been handled?
2552 MOZ_ASSERT(aEvent
.mMessage
== eKeyPress
);
2553 WidgetKeyboardEvent
localEvent(aEvent
);
2554 localEvent
.MarkAsHandledInRemoteProcess();
2555 localEvent
.mMessage
= eAccessKeyNotFound
;
2557 // Here we convert the WidgetEvent that we received to an Event
2558 // to be able to dispatch it to the <browser> element as the target element.
2559 Document
* doc
= mFrameElement
->OwnerDoc();
2560 PresShell
* presShell
= doc
->GetPresShell();
2561 NS_ENSURE_TRUE(presShell
, IPC_OK());
2563 if (presShell
->CanDispatchEvent()) {
2564 nsPresContext
* presContext
= presShell
->GetPresContext();
2565 NS_ENSURE_TRUE(presContext
, IPC_OK());
2567 EventDispatcher::Dispatch(mFrameElement
, presContext
, &localEvent
);
2573 mozilla::ipc::IPCResult
BrowserParent::RecvRegisterProtocolHandler(
2574 const nsString
& aScheme
, nsIURI
* aHandlerURI
, const nsString
& aTitle
,
2576 nsCOMPtr
<nsIWebProtocolHandlerRegistrar
> registrar
=
2577 do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID
);
2579 registrar
->RegisterProtocolHandler(aScheme
, aHandlerURI
, aTitle
, aDocURI
,
2586 mozilla::ipc::IPCResult
BrowserParent::RecvOnStateChange(
2587 const Maybe
<WebProgressData
>& aWebProgressData
,
2588 const RequestData
& aRequestData
, const uint32_t aStateFlags
,
2589 const nsresult aStatus
,
2590 const Maybe
<WebProgressStateChangeData
>& aStateChangeData
) {
2591 if (mSuspendedProgressEvents
) {
2592 nsCOMPtr
<nsIURI
> uri
= aRequestData
.requestURI();
2593 const uint32_t startDocumentFlags
=
2594 nsIWebProgressListener::STATE_START
|
2595 nsIWebProgressListener::STATE_IS_DOCUMENT
|
2596 nsIWebProgressListener::STATE_IS_REQUEST
|
2597 nsIWebProgressListener::STATE_IS_WINDOW
|
2598 nsIWebProgressListener::STATE_IS_NETWORK
;
2599 // Once we get a load start from something that isn't the initial
2600 // about:blank, we should stop blocking future state changes.
2601 if ((aStateFlags
& startDocumentFlags
) == startDocumentFlags
&&
2602 (aWebProgressData
&& aWebProgressData
->isTopLevel()) &&
2603 (!uri
|| !NS_IsAboutBlank(uri
))) {
2604 mSuspendedProgressEvents
= false;
2610 nsCOMPtr
<nsIBrowser
> browser
;
2611 nsCOMPtr
<nsIWebProgress
> manager
;
2612 nsCOMPtr
<nsIWebProgressListener
> managerAsListener
;
2613 if (!GetWebProgressListener(getter_AddRefs(browser
), getter_AddRefs(manager
),
2614 getter_AddRefs(managerAsListener
))) {
2618 nsCOMPtr
<nsIWebProgress
> webProgress
;
2619 nsCOMPtr
<nsIRequest
> request
;
2620 ReconstructWebProgressAndRequest(manager
, aWebProgressData
, aRequestData
,
2621 getter_AddRefs(webProgress
),
2622 getter_AddRefs(request
));
2624 if (aWebProgressData
&& aWebProgressData
->isTopLevel() &&
2625 aStateChangeData
.isSome()) {
2626 Unused
<< browser
->SetIsNavigating(aStateChangeData
->isNavigating());
2627 Unused
<< browser
->SetMayEnableCharacterEncodingMenu(
2628 aStateChangeData
->mayEnableCharacterEncodingMenu());
2629 Unused
<< browser
->SetCharsetAutodetected(
2630 aStateChangeData
->charsetAutodetected());
2631 Unused
<< browser
->UpdateForStateChange(aStateChangeData
->charset(),
2632 aStateChangeData
->documentURI(),
2633 aStateChangeData
->contentType());
2634 } else if (aStateChangeData
.isSome()) {
2637 "Unexpected WebProgressStateChangeData for non-top-level WebProgress");
2640 Unused
<< managerAsListener
->OnStateChange(webProgress
, request
, aStateFlags
,
2646 mozilla::ipc::IPCResult
BrowserParent::RecvOnProgressChange(
2647 const Maybe
<WebProgressData
>& aWebProgressData
,
2648 const RequestData
& aRequestData
, const int32_t aCurSelfProgress
,
2649 const int32_t aMaxSelfProgress
, const int32_t aCurTotalProgress
,
2650 const int32_t aMaxTotalProgress
) {
2651 if (mSuspendedProgressEvents
) {
2655 nsCOMPtr
<nsIBrowser
> browser
;
2656 nsCOMPtr
<nsIWebProgress
> manager
;
2657 nsCOMPtr
<nsIWebProgressListener
> managerAsListener
;
2658 if (!GetWebProgressListener(getter_AddRefs(browser
), getter_AddRefs(manager
),
2659 getter_AddRefs(managerAsListener
))) {
2663 nsCOMPtr
<nsIWebProgress
> webProgress
;
2664 nsCOMPtr
<nsIRequest
> request
;
2665 ReconstructWebProgressAndRequest(manager
, aWebProgressData
, aRequestData
,
2666 getter_AddRefs(webProgress
),
2667 getter_AddRefs(request
));
2669 Unused
<< managerAsListener
->OnProgressChange(
2670 webProgress
, request
, aCurSelfProgress
, aMaxSelfProgress
,
2671 aCurTotalProgress
, aMaxTotalProgress
);
2676 mozilla::ipc::IPCResult
BrowserParent::RecvOnLocationChange(
2677 const Maybe
<WebProgressData
>& aWebProgressData
,
2678 const RequestData
& aRequestData
, nsIURI
* aLocation
, const uint32_t aFlags
,
2679 const bool aCanGoBack
, const bool aCanGoForward
,
2680 const Maybe
<WebProgressLocationChangeData
>& aLocationChangeData
) {
2681 if (mSuspendedProgressEvents
) {
2685 nsCOMPtr
<nsIBrowser
> browser
;
2686 nsCOMPtr
<nsIWebProgress
> manager
;
2687 nsCOMPtr
<nsIWebProgressListener
> managerAsListener
;
2688 if (!GetWebProgressListener(getter_AddRefs(browser
), getter_AddRefs(manager
),
2689 getter_AddRefs(managerAsListener
))) {
2693 nsCOMPtr
<nsIWebProgress
> webProgress
;
2694 nsCOMPtr
<nsIRequest
> request
;
2695 ReconstructWebProgressAndRequest(manager
, aWebProgressData
, aRequestData
,
2696 getter_AddRefs(webProgress
),
2697 getter_AddRefs(request
));
2699 Unused
<< browser
->UpdateWebNavigationForLocationChange(aCanGoBack
,
2702 if (aWebProgressData
&& aWebProgressData
->isTopLevel() &&
2703 aLocationChangeData
.isSome()) {
2704 nsCOMPtr
<nsIPrincipal
> contentBlockingAllowListPrincipal
;
2705 Unused
<< browser
->SetIsNavigating(aLocationChangeData
->isNavigating());
2706 Unused
<< browser
->UpdateForLocationChange(
2707 aLocation
, aLocationChangeData
->charset(),
2708 aLocationChangeData
->mayEnableCharacterEncodingMenu(),
2709 aLocationChangeData
->charsetAutodetected(),
2710 aLocationChangeData
->documentURI(), aLocationChangeData
->title(),
2711 aLocationChangeData
->contentPrincipal(),
2712 aLocationChangeData
->contentStoragePrincipal(),
2713 aLocationChangeData
->csp(), aLocationChangeData
->referrerInfo(),
2714 aLocationChangeData
->isSyntheticDocument(),
2715 aWebProgressData
->innerDOMWindowID(),
2716 aLocationChangeData
->requestContextID().isSome(),
2717 aLocationChangeData
->requestContextID().valueOr(0),
2718 aLocationChangeData
->contentType());
2721 Unused
<< managerAsListener
->OnLocationChange(webProgress
, request
, aLocation
,
2727 mozilla::ipc::IPCResult
BrowserParent::RecvOnStatusChange(
2728 const Maybe
<WebProgressData
>& aWebProgressData
,
2729 const RequestData
& aRequestData
, const nsresult aStatus
,
2730 const nsString
& aMessage
) {
2731 if (mSuspendedProgressEvents
) {
2735 nsCOMPtr
<nsIBrowser
> browser
;
2736 nsCOMPtr
<nsIWebProgress
> manager
;
2737 nsCOMPtr
<nsIWebProgressListener
> managerAsListener
;
2738 if (!GetWebProgressListener(getter_AddRefs(browser
), getter_AddRefs(manager
),
2739 getter_AddRefs(managerAsListener
))) {
2743 nsCOMPtr
<nsIWebProgress
> webProgress
;
2744 nsCOMPtr
<nsIRequest
> request
;
2745 ReconstructWebProgressAndRequest(manager
, aWebProgressData
, aRequestData
,
2746 getter_AddRefs(webProgress
),
2747 getter_AddRefs(request
));
2749 Unused
<< managerAsListener
->OnStatusChange(webProgress
, request
, aStatus
,
2755 mozilla::ipc::IPCResult
BrowserParent::RecvOnSecurityChange(
2756 const Maybe
<WebProgressData
>& aWebProgressData
,
2757 const RequestData
& aRequestData
, const uint32_t aState
,
2758 const Maybe
<WebProgressSecurityChangeData
>& aSecurityChangeData
) {
2759 nsCOMPtr
<nsIBrowser
> browser
;
2760 nsCOMPtr
<nsIWebProgress
> manager
;
2761 nsCOMPtr
<nsIWebProgressListener
> managerAsListener
;
2762 if (!GetWebProgressListener(getter_AddRefs(browser
), getter_AddRefs(manager
),
2763 getter_AddRefs(managerAsListener
))) {
2767 nsCOMPtr
<nsIWebProgress
> webProgress
;
2768 nsCOMPtr
<nsIRequest
> request
;
2769 ReconstructWebProgressAndRequest(manager
, aWebProgressData
, aRequestData
,
2770 getter_AddRefs(webProgress
),
2771 getter_AddRefs(request
));
2773 if (aWebProgressData
&& aWebProgressData
->isTopLevel() &&
2774 aSecurityChangeData
.isSome()) {
2775 Unused
<< browser
->UpdateSecurityUIForSecurityChange(
2776 aSecurityChangeData
->securityInfo(), aState
,
2777 aSecurityChangeData
->isSecureContext());
2780 Unused
<< managerAsListener
->OnSecurityChange(webProgress
, request
, aState
);
2785 mozilla::ipc::IPCResult
BrowserParent::RecvNavigationFinished() {
2786 nsCOMPtr
<nsIBrowser
> browser
=
2787 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
2790 browser
->SetIsNavigating(false);
2796 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyContentBlockingEvent(
2797 const uint32_t& aEvent
, const RequestData
& aRequestData
,
2798 const bool aBlocked
, const nsACString
& aTrackingOrigin
,
2799 nsTArray
<nsCString
>&& aTrackingFullHashes
,
2800 const Maybe
<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason
>&
2802 MOZ_ASSERT(aRequestData
.elapsedLoadTimeMS().isNothing());
2804 RefPtr
<BrowsingContext
> bc
= GetBrowsingContext();
2806 if (!bc
|| bc
->IsDiscarded()) {
2810 // Get the top-level browsing context.
2812 RefPtr
<dom::WindowGlobalParent
> wgp
=
2813 bc
->Canonical()->GetCurrentWindowGlobal();
2815 // The WindowGlobalParent would be null while running the test
2816 // browser_339445.js. This is unexpected and we will address this in a
2817 // following bug. For now, we first workaround this issue.
2822 nsCOMPtr
<nsIRequest
> request
= MakeAndAddRef
<RemoteWebProgressRequest
>(
2823 aRequestData
.requestURI(), aRequestData
.originalRequestURI(),
2824 aRequestData
.matchedList(), aRequestData
.elapsedLoadTimeMS());
2826 wgp
->NotifyContentBlockingEvent(aEvent
, request
, aBlocked
, aTrackingOrigin
,
2827 aTrackingFullHashes
, aReason
);
2832 mozilla::ipc::IPCResult
2833 BrowserParent::RecvReportBlockedEmbedderNodeByClassifier() {
2834 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
2840 Unused
<< bridge
->SendAddBlockedNodeByClassifier();
2844 bool BrowserParent::GetWebProgressListener(
2845 nsIBrowser
** aOutBrowser
, nsIWebProgress
** aOutManager
,
2846 nsIWebProgressListener
** aOutListener
) {
2847 MOZ_ASSERT(aOutBrowser
);
2848 MOZ_ASSERT(aOutManager
);
2849 MOZ_ASSERT(aOutListener
);
2851 nsCOMPtr
<nsIBrowser
> browser
;
2852 RefPtr
<Element
> currentElement
= mFrameElement
;
2854 // In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
2855 // but we want the <xul:browser> that it is embedded in.
2856 while (currentElement
) {
2857 browser
= currentElement
->AsBrowser();
2862 BrowsingContext
* browsingContext
=
2863 currentElement
->OwnerDoc()->GetBrowsingContext();
2865 browsingContext
? browsingContext
->GetEmbedderElement() : nullptr;
2872 nsCOMPtr
<nsIWebProgress
> manager
;
2873 nsresult rv
= browser
->GetRemoteWebProgressManager(getter_AddRefs(manager
));
2874 if (NS_FAILED(rv
)) {
2878 nsCOMPtr
<nsIWebProgressListener
> listener
= do_QueryInterface(manager
);
2880 // We are no longer remote so we cannot forward this event.
2884 browser
.forget(aOutBrowser
);
2885 manager
.forget(aOutManager
);
2886 listener
.forget(aOutListener
);
2891 void BrowserParent::ReconstructWebProgressAndRequest(
2892 nsIWebProgress
* aManager
, const Maybe
<WebProgressData
>& aWebProgressData
,
2893 const RequestData
& aRequestData
, nsIWebProgress
** aOutWebProgress
,
2894 nsIRequest
** aOutRequest
) {
2895 MOZ_DIAGNOSTIC_ASSERT(aOutWebProgress
,
2896 "aOutWebProgress should never be null");
2897 MOZ_DIAGNOSTIC_ASSERT(aOutRequest
, "aOutRequest should never be null");
2899 nsCOMPtr
<nsIWebProgress
> webProgress
;
2900 if (aWebProgressData
) {
2901 webProgress
= new RemoteWebProgress(
2902 aManager
, aWebProgressData
->outerDOMWindowID(),
2903 aWebProgressData
->innerDOMWindowID(), aWebProgressData
->loadType(),
2904 aWebProgressData
->isLoadingDocument(), aWebProgressData
->isTopLevel());
2906 webProgress
= new RemoteWebProgress(aManager
, 0, 0, 0, false, false);
2908 webProgress
.forget(aOutWebProgress
);
2910 if (aRequestData
.requestURI()) {
2911 nsCOMPtr
<nsIRequest
> request
= MakeAndAddRef
<RemoteWebProgressRequest
>(
2912 aRequestData
.requestURI(), aRequestData
.originalRequestURI(),
2913 aRequestData
.matchedList(), aRequestData
.elapsedLoadTimeMS());
2914 request
.forget(aOutRequest
);
2916 *aOutRequest
= nullptr;
2920 mozilla::ipc::IPCResult
BrowserParent::RecvSessionStoreUpdate(
2921 const Maybe
<nsCString
>& aDocShellCaps
, const Maybe
<bool>& aPrivatedMode
,
2922 nsTArray
<nsCString
>&& aPositions
, nsTArray
<int32_t>&& aPositionDescendants
,
2923 const nsTArray
<InputFormData
>& aInputs
,
2924 const nsTArray
<CollectedInputDataValue
>& aIdVals
,
2925 const nsTArray
<CollectedInputDataValue
>& aXPathVals
,
2926 nsTArray
<nsCString
>&& aOrigins
, nsTArray
<nsString
>&& aKeys
,
2927 nsTArray
<nsString
>&& aValues
, const bool aIsFullStorage
,
2928 const bool aNeedCollectSHistory
, const uint32_t& aFlushId
,
2929 const bool& aIsFinal
, const uint32_t& aEpoch
) {
2930 UpdateSessionStoreData data
;
2931 if (aDocShellCaps
.isSome()) {
2932 data
.mDocShellCaps
.Construct() = aDocShellCaps
.value();
2934 if (aPrivatedMode
.isSome()) {
2935 data
.mIsPrivate
.Construct() = aPrivatedMode
.value();
2937 if (aPositions
.Length() != 0) {
2938 data
.mPositions
.Construct(std::move(aPositions
));
2939 data
.mPositionDescendants
.Construct(std::move(aPositionDescendants
));
2941 if (aIdVals
.Length() != 0) {
2942 SessionStoreUtils::ComposeInputData(aIdVals
, data
.mId
.Construct());
2944 if (aXPathVals
.Length() != 0) {
2945 SessionStoreUtils::ComposeInputData(aXPathVals
, data
.mXpath
.Construct());
2947 if (aInputs
.Length() != 0) {
2948 nsTArray
<int> descendants
, numId
, numXPath
;
2949 nsTArray
<nsString
> innerHTML
;
2950 nsTArray
<nsCString
> url
;
2951 for (const InputFormData
& input
: aInputs
) {
2952 descendants
.AppendElement(input
.descendants
);
2953 numId
.AppendElement(input
.numId
);
2954 numXPath
.AppendElement(input
.numXPath
);
2955 innerHTML
.AppendElement(input
.innerHTML
);
2956 url
.AppendElement(input
.url
);
2959 data
.mInputDescendants
.Construct(std::move(descendants
));
2960 data
.mNumId
.Construct(std::move(numId
));
2961 data
.mNumXPath
.Construct(std::move(numXPath
));
2962 data
.mInnerHTML
.Construct(std::move(innerHTML
));
2963 data
.mUrl
.Construct(std::move(url
));
2965 // In normal case, we only update the storage when needed.
2966 // However, we need to reset the session storage(aOrigins.Length() will be 0)
2967 // if the usage is over the "browser_sessionstore_dom_storage_limit".
2968 // In this case, aIsFullStorage is true.
2969 if (aOrigins
.Length() != 0 || aIsFullStorage
) {
2970 data
.mStorageOrigins
.Construct(std::move(aOrigins
));
2971 data
.mStorageKeys
.Construct(std::move(aKeys
));
2972 data
.mStorageValues
.Construct(std::move(aValues
));
2973 data
.mIsFullStorage
.Construct() = aIsFullStorage
;
2976 nsCOMPtr
<nsISessionStoreFunctions
> funcs
=
2977 do_ImportModule("resource://gre/modules/SessionStoreFunctions.jsm");
2978 NS_ENSURE_TRUE(funcs
, IPC_OK());
2979 nsCOMPtr
<nsIXPConnectWrappedJS
> wrapped
= do_QueryInterface(funcs
);
2981 MOZ_ALWAYS_TRUE(jsapi
.Init(wrapped
->GetJSObjectGlobal()));
2982 JS::Rooted
<JS::Value
> dataVal(jsapi
.cx());
2983 bool ok
= ToJSValue(jsapi
.cx(), data
, &dataVal
);
2984 NS_ENSURE_TRUE(ok
, IPC_OK());
2986 nsresult rv
= funcs
->UpdateSessionStore(
2987 mFrameElement
, aFlushId
, aIsFinal
, aEpoch
, dataVal
, aNeedCollectSHistory
);
2988 NS_ENSURE_SUCCESS(rv
, IPC_OK());
2993 bool BrowserParent::HandleQueryContentEvent(WidgetQueryContentEvent
& aEvent
) {
2994 nsCOMPtr
<nsIWidget
> textInputHandlingWidget
= GetTextInputHandlingWidget();
2995 if (!textInputHandlingWidget
) {
2998 if (NS_WARN_IF(!mContentCache
.HandleQueryContentEvent(
2999 aEvent
, textInputHandlingWidget
)) ||
3000 NS_WARN_IF(!aEvent
.mSucceeded
)) {
3003 switch (aEvent
.mMessage
) {
3004 case eQueryTextRect
:
3005 case eQueryCaretRect
:
3006 case eQueryEditorRect
: {
3007 nsCOMPtr
<nsIWidget
> browserWidget
= GetWidget();
3008 if (browserWidget
!= textInputHandlingWidget
) {
3009 aEvent
.mReply
.mRect
+= nsLayoutUtils::WidgetToWidgetOffset(
3010 browserWidget
, textInputHandlingWidget
);
3012 aEvent
.mReply
.mRect
= TransformChildToParent(aEvent
.mReply
.mRect
);
3021 bool BrowserParent::SendCompositionEvent(WidgetCompositionEvent
& aEvent
) {
3026 if (!mContentCache
.OnCompositionEvent(aEvent
)) {
3030 bool ret
= Manager()->IsInputPriorityEventEnabled()
3031 ? PBrowserParent::SendCompositionEvent(aEvent
)
3032 : PBrowserParent::SendNormalPriorityCompositionEvent(aEvent
);
3033 if (NS_WARN_IF(!ret
)) {
3036 MOZ_ASSERT(aEvent
.HasBeenPostedToRemoteProcess());
3040 bool BrowserParent::SendSelectionEvent(WidgetSelectionEvent
& aEvent
) {
3044 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3048 mContentCache
.OnSelectionEvent(aEvent
);
3049 bool ret
= Manager()->IsInputPriorityEventEnabled()
3050 ? PBrowserParent::SendSelectionEvent(aEvent
)
3051 : PBrowserParent::SendNormalPrioritySelectionEvent(aEvent
);
3052 if (NS_WARN_IF(!ret
)) {
3055 MOZ_ASSERT(aEvent
.HasBeenPostedToRemoteProcess());
3056 aEvent
.mSucceeded
= true;
3060 bool BrowserParent::SendPasteTransferable(const IPCDataTransfer
& aDataTransfer
,
3061 const bool& aIsPrivateData
,
3062 nsIPrincipal
* aRequestingPrincipal
,
3063 const uint32_t& aContentPolicyType
) {
3064 return PBrowserParent::SendPasteTransferable(
3065 aDataTransfer
, aIsPrivateData
, aRequestingPrincipal
, aContentPolicyType
);
3069 void BrowserParent::SetTopLevelWebFocus(BrowserParent
* aBrowserParent
) {
3070 BrowserParent
* old
= GetFocused();
3071 if (aBrowserParent
&& !aBrowserParent
->GetBrowserBridgeParent()) {
3072 // top-level Web content
3073 sTopLevelWebFocus
= aBrowserParent
;
3074 BrowserParent
* bp
= UpdateFocus();
3077 ("SetTopLevelWebFocus updated focus; old: %p, new: %p", old
, bp
));
3078 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, bp
);
3084 void BrowserParent::UnsetTopLevelWebFocus(BrowserParent
* aBrowserParent
) {
3085 BrowserParent
* old
= GetFocused();
3086 if (sTopLevelWebFocus
== aBrowserParent
) {
3087 // top-level Web content
3088 sTopLevelWebFocus
= nullptr;
3092 ("UnsetTopLevelWebFocus moved focus to chrome; old: %p", old
));
3093 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, nullptr);
3099 void BrowserParent::UpdateFocusFromBrowsingContext() {
3100 BrowserParent
* old
= GetFocused();
3101 BrowserParent
* bp
= UpdateFocus();
3104 ("UpdateFocusFromBrowsingContext updated focus; old: %p, new: %p", old
,
3106 IMEStateManager::OnFocusMovedBetweenBrowsers(old
, bp
);
3111 BrowserParent
* BrowserParent::UpdateFocus() {
3112 if (!sTopLevelWebFocus
) {
3116 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
3118 BrowsingContext
* bc
= fm
->GetFocusedBrowsingContextInChrome();
3120 BrowsingContext
* top
= bc
->Top();
3121 MOZ_ASSERT(top
, "Should always have a top BrowsingContext.");
3122 CanonicalBrowsingContext
* canonicalTop
= top
->Canonical();
3123 MOZ_ASSERT(canonicalTop
,
3124 "Casting to canonical should always be possible in the parent "
3125 "process (top case).");
3126 WindowGlobalParent
* globalTop
= canonicalTop
->GetCurrentWindowGlobal();
3128 RefPtr
<BrowserParent
> globalTopParent
= globalTop
->GetBrowserParent();
3129 if (sTopLevelWebFocus
== globalTopParent
) {
3130 CanonicalBrowsingContext
* canonical
= bc
->Canonical();
3133 "Casting to canonical should always be possible in the parent "
3135 WindowGlobalParent
* global
= canonical
->GetCurrentWindowGlobal();
3137 RefPtr
<BrowserParent
> parent
= global
->GetBrowserParent();
3142 ("Focused BrowsingContext did not have WindowGlobalParent."));
3146 ("Top-level BrowsingContext did not have WindowGlobalParent."));
3150 sFocus
= sTopLevelWebFocus
;
3155 void BrowserParent::UnsetTopLevelWebFocusAll() {
3156 if (sTopLevelWebFocus
) {
3157 UnsetTopLevelWebFocus(sTopLevelWebFocus
);
3162 void BrowserParent::UnsetLastMouseRemoteTarget(BrowserParent
* aBrowserParent
) {
3163 if (sLastMouseRemoteTarget
== aBrowserParent
) {
3164 sLastMouseRemoteTarget
= nullptr;
3168 mozilla::ipc::IPCResult
BrowserParent::RecvRequestIMEToCommitComposition(
3169 const bool& aCancel
, bool* aIsCommitted
, nsString
* aCommittedString
) {
3170 nsCOMPtr
<nsIWidget
> widget
= GetTextInputHandlingWidget();
3172 *aIsCommitted
= false;
3176 *aIsCommitted
= mContentCache
.RequestIMEToCommitComposition(
3177 widget
, aCancel
, *aCommittedString
);
3181 mozilla::ipc::IPCResult
BrowserParent::RecvStartPluginIME(
3182 const WidgetKeyboardEvent
& aKeyboardEvent
, const int32_t& aPanelX
,
3183 const int32_t& aPanelY
, nsString
* aCommitted
) {
3184 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3188 Unused
<< widget
->StartPluginIME(aKeyboardEvent
, (int32_t&)aPanelX
,
3189 (int32_t&)aPanelY
, *aCommitted
);
3193 mozilla::ipc::IPCResult
BrowserParent::RecvSetPluginFocused(
3194 const bool& aFocused
) {
3195 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3199 widget
->SetPluginFocused((bool&)aFocused
);
3203 mozilla::ipc::IPCResult
BrowserParent::RecvSetCandidateWindowForPlugin(
3204 const CandidateWindowPosition
& aPosition
) {
3205 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3210 widget
->SetCandidateWindowForPlugin(aPosition
);
3214 mozilla::ipc::IPCResult
BrowserParent::RecvEnableIMEForPlugin(
3215 const bool& aEnable
) {
3216 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3220 widget
->EnableIMEForPlugin(aEnable
);
3224 mozilla::ipc::IPCResult
BrowserParent::RecvDefaultProcOfPluginEvent(
3225 const WidgetPluginEvent
& aEvent
) {
3226 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3231 widget
->DefaultProcOfPluginEvent(aEvent
);
3235 mozilla::ipc::IPCResult
BrowserParent::RecvGetInputContext(
3236 widget::IMEState
* aState
) {
3237 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3239 *aState
= widget::IMEState(IMEState::DISABLED
,
3240 IMEState::OPEN_STATE_NOT_SUPPORTED
);
3244 *aState
= widget
->GetInputContext().mIMEState
;
3248 mozilla::ipc::IPCResult
BrowserParent::RecvSetInputContext(
3249 const InputContext
& aContext
, const InputContextAction
& aAction
) {
3250 IMEStateManager::SetInputContextForChildProcess(this, aContext
, aAction
);
3254 mozilla::ipc::IPCResult
BrowserParent::RecvSetNativeChildOfShareableWindow(
3255 const uintptr_t& aChildWindow
) {
3257 nsCOMPtr
<nsIWidget
> widget
= GetTopLevelWidget();
3259 // Note that this call will probably cause a sync native message to the
3260 // process that owns the child window.
3261 widget
->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW
, aChildWindow
);
3265 MOZ_ASSERT_UNREACHABLE(
3266 "BrowserParent::RecvSetNativeChildOfShareableWindow not implemented!");
3267 return IPC_FAIL_NO_REASON(this);
3271 mozilla::ipc::IPCResult
BrowserParent::RecvDispatchFocusToTopLevelWindow() {
3272 if (nsCOMPtr
<nsIWidget
> widget
= GetTopLevelWidget()) {
3273 widget
->SetFocus(nsIWidget::Raise::No
, CallerType::System
);
3278 bool BrowserParent::ReceiveMessage(const nsString
& aMessage
, bool aSync
,
3279 StructuredCloneData
* aData
,
3280 nsTArray
<StructuredCloneData
>* aRetVal
) {
3281 // If we're for an oop iframe, don't deliver messages to the wrong place.
3282 if (mBrowserBridgeParent
) {
3286 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader(true);
3287 if (frameLoader
&& frameLoader
->GetFrameMessageManager()) {
3288 RefPtr
<nsFrameMessageManager
> manager
=
3289 frameLoader
->GetFrameMessageManager();
3291 manager
->ReceiveMessage(mFrameElement
, frameLoader
, aMessage
, aSync
, aData
,
3292 aRetVal
, IgnoreErrors());
3297 // nsIAuthPromptProvider
3299 // This method is largely copied from nsDocShell::GetAuthPrompt
3301 BrowserParent::GetAuthPrompt(uint32_t aPromptReason
, const nsIID
& iid
,
3303 // we're either allowing auth, or it's a proxy request
3305 nsCOMPtr
<nsIPromptFactory
> wwatch
=
3306 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
3307 NS_ENSURE_SUCCESS(rv
, rv
);
3309 nsCOMPtr
<nsPIDOMWindowOuter
> window
;
3310 RefPtr
<Element
> frame
= mFrameElement
;
3311 if (frame
) window
= frame
->OwnerDoc()->GetWindow();
3313 // Get an auth prompter for our window so that the parenting
3314 // of the dialogs works as it should when using tabs.
3315 nsCOMPtr
<nsISupports
> prompt
;
3316 rv
= wwatch
->GetPrompt(window
, iid
, getter_AddRefs(prompt
));
3317 NS_ENSURE_SUCCESS(rv
, rv
);
3319 nsCOMPtr
<nsILoginManagerAuthPrompter
> prompter
= do_QueryInterface(prompt
);
3321 prompter
->SetBrowser(mFrameElement
);
3324 *aResult
= prompt
.forget().take();
3328 PColorPickerParent
* BrowserParent::AllocPColorPickerParent(
3329 const nsString
& aTitle
, const nsString
& aInitialColor
) {
3330 return new ColorPickerParent(aTitle
, aInitialColor
);
3333 bool BrowserParent::DeallocPColorPickerParent(PColorPickerParent
* actor
) {
3338 already_AddRefed
<nsFrameLoader
> BrowserParent::GetFrameLoader(
3339 bool aUseCachedFrameLoaderAfterDestroy
) const {
3340 if (mIsDestroyed
&& !aUseCachedFrameLoaderAfterDestroy
) {
3345 RefPtr
<nsFrameLoader
> fl
= mFrameLoader
;
3348 RefPtr
<Element
> frameElement(mFrameElement
);
3349 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(frameElement
);
3350 return frameLoaderOwner
? frameLoaderOwner
->GetFrameLoader() : nullptr;
3353 void BrowserParent::TryCacheDPIAndScale() {
3358 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3361 mDPI
= widget
->GetDPI();
3362 mRounding
= widget
->RoundsWidgetCoordinatesTo();
3363 mDefaultScale
= widget
->GetDefaultScale();
3367 void BrowserParent::ApzAwareEventRoutingToChild(
3368 ScrollableLayerGuid
* aOutTargetGuid
, uint64_t* aOutInputBlockId
,
3369 nsEventStatus
* aOutApzResponse
) {
3370 // Let the widget know that the event will be sent to the child process,
3371 // which will (hopefully) send a confirmation notice back to APZ.
3372 // Do this even if APZ is off since we need it for swipe gesture support on
3373 // OS X without APZ.
3374 InputAPZContext::SetRoutedToChildProcess();
3376 if (AsyncPanZoomEnabled()) {
3377 if (aOutTargetGuid
) {
3378 *aOutTargetGuid
= InputAPZContext::GetTargetLayerGuid();
3380 // There may be cases where the APZ hit-testing code came to a different
3381 // conclusion than the main-thread hit-testing code as to where the event
3382 // is destined. In such cases the layersId of the APZ result may not match
3383 // the layersId of this RemoteLayerTreeOwner. In such cases the
3384 // main-thread hit- testing code "wins" so we need to update the guid to
3386 if (mRemoteLayerTreeOwner
.IsInitialized()) {
3387 if (aOutTargetGuid
->mLayersId
!= mRemoteLayerTreeOwner
.GetLayersId()) {
3389 ScrollableLayerGuid(mRemoteLayerTreeOwner
.GetLayersId(), 0,
3390 ScrollableLayerGuid::NULL_SCROLL_ID
);
3394 if (aOutInputBlockId
) {
3395 *aOutInputBlockId
= InputAPZContext::GetInputBlockId();
3397 if (aOutApzResponse
) {
3398 *aOutApzResponse
= InputAPZContext::GetApzResponse();
3400 // We can get here without there being an InputAPZContext on the stack
3401 // if a non-native event synthesization function (such as
3402 // nsIDOMWindowUtils.sendTouchEvent()) was used in the parent process to
3403 // synthesize an event that's targeting a content process. Such events do
3404 // not go through APZ. Without an InputAPZContext on the stack we pick up
3405 // the default value "eSentinel" which cannot be sent over IPC, so replace
3406 // it with "eIgnore" instead, which what APZ uses when it ignores an
3407 // event. If a caller needs the ability to synthesize a event with a
3408 // different APZ response, a native event synthesization function (such as
3409 // sendNativeTouchPoint()) can be used.
3410 if (*aOutApzResponse
== nsEventStatus_eSentinel
) {
3411 *aOutApzResponse
= nsEventStatus_eIgnore
;
3415 if (aOutInputBlockId
) {
3416 *aOutInputBlockId
= 0;
3418 if (aOutApzResponse
) {
3419 *aOutApzResponse
= nsEventStatus_eIgnore
;
3424 mozilla::ipc::IPCResult
BrowserParent::RecvRespondStartSwipeEvent(
3425 const uint64_t& aInputBlockId
, const bool& aStartSwipe
) {
3426 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
3427 widget
->ReportSwipeStarted(aInputBlockId
, aStartSwipe
);
3432 bool BrowserParent::GetDocShellIsActive() { return mDocShellIsActive
; }
3434 void BrowserParent::SetDocShellIsActive(bool isActive
) {
3435 mDocShellIsActive
= isActive
;
3436 SetRenderLayers(isActive
);
3437 Unused
<< SendSetDocShellIsActive(isActive
);
3439 // update active accessible documents on windows
3440 #if defined(XP_WIN) && defined(ACCESSIBILITY)
3441 if (a11y::Compatibility::IsDolphin()) {
3442 if (a11y::DocAccessibleParent
* tabDoc
= GetTopLevelDocAccessible()) {
3443 HWND window
= tabDoc
->GetEmulatedWindowHandle();
3447 a11y::nsWinUtils::ShowNativeWindow(window
);
3449 a11y::nsWinUtils::HideNativeWindow(window
);
3457 bool BrowserParent::GetSuspendMediaWhenInactive() const {
3458 return mSuspendMediaWhenInactive
;
3461 void BrowserParent::SetSuspendMediaWhenInactive(
3462 bool aSuspendMediaWhenInactive
) {
3463 mSuspendMediaWhenInactive
= aSuspendMediaWhenInactive
;
3464 Unused
<< SendSetSuspendMediaWhenInactive(aSuspendMediaWhenInactive
);
3467 bool BrowserParent::GetHasPresented() { return mHasPresented
; }
3469 bool BrowserParent::GetHasLayers() { return mHasLayers
; }
3471 bool BrowserParent::GetRenderLayers() { return mRenderLayers
; }
3473 void BrowserParent::SetRenderLayers(bool aEnabled
) {
3474 if (mActiveInPriorityManager
!= aEnabled
) {
3475 mActiveInPriorityManager
= aEnabled
;
3476 // Let's inform the priority manager. This operation can end up with the
3477 // changing of the process priority.
3478 ProcessPriorityManager::TabActivityChanged(this, aEnabled
);
3481 if (aEnabled
== mRenderLayers
) {
3482 if (aEnabled
&& mHasLayers
&& mPreserveLayers
) {
3483 // RenderLayers might be called when we've been preserving layers,
3484 // and already had layers uploaded. In that case, the MozLayerTreeReady
3485 // event will not naturally arrive, which can confuse the front-end
3486 // layer. So we fire the event here.
3487 RefPtr
<BrowserParent
> self
= this;
3488 LayersObserverEpoch epoch
= mLayerTreeEpoch
;
3489 NS_DispatchToMainThread(NS_NewRunnableFunction(
3490 "dom::BrowserParent::RenderLayers", [self
, epoch
]() {
3491 MOZ_ASSERT(NS_IsMainThread());
3492 self
->LayerTreeUpdate(epoch
, true);
3499 // Preserve layers means that attempts to stop rendering layers
3501 if (!aEnabled
&& mPreserveLayers
) {
3505 mRenderLayers
= aEnabled
;
3507 SetRenderLayersInternal(aEnabled
);
3510 void BrowserParent::SetRenderLayersInternal(bool aEnabled
) {
3511 // Increment the epoch so that layer tree updates from previous
3512 // RenderLayers requests are ignored.
3513 mLayerTreeEpoch
= mLayerTreeEpoch
.Next();
3515 Unused
<< SendRenderLayers(aEnabled
, mLayerTreeEpoch
);
3517 // Ask the child to repaint using the PHangMonitor channel/thread (which may
3518 // be less congested).
3520 Manager()->PaintTabWhileInterruptingJS(this, mLayerTreeEpoch
);
3524 void BrowserParent::PreserveLayers(bool aPreserveLayers
) {
3525 mPreserveLayers
= aPreserveLayers
;
3528 void BrowserParent::NotifyResolutionChanged() {
3529 if (!mIsDestroyed
) {
3530 // TryCacheDPIAndScale()'s cache is keyed off of
3531 // mDPI being greater than 0, so this invalidates it.
3533 TryCacheDPIAndScale();
3534 // If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
3535 // fails to cache the values, then mDefaultScale.scale might be invalid.
3536 // We don't want to send that value to content. Just send -1 for it too in
3538 Unused
<< SendUIResolutionChanged(mDPI
, mRounding
,
3539 mDPI
< 0 ? -1.0 : mDefaultScale
.scale
);
3543 void BrowserParent::Deprioritize() {
3544 if (mActiveInPriorityManager
) {
3545 ProcessPriorityManager::TabActivityChanged(this, false);
3546 mActiveInPriorityManager
= false;
3550 bool BrowserParent::StartApzAutoscroll(float aAnchorX
, float aAnchorY
,
3552 uint32_t aPresShellId
) {
3553 if (!AsyncPanZoomEnabled()) {
3557 bool success
= false;
3558 if (mRemoteLayerTreeOwner
.IsInitialized()) {
3559 layers::LayersId layersId
= mRemoteLayerTreeOwner
.GetLayersId();
3560 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
3561 ScrollableLayerGuid
guid(layersId
, aPresShellId
, aScrollId
);
3563 // The anchor coordinates that are passed in are relative to the origin
3564 // of the screen, but we are sending them to APZ which only knows about
3565 // coordinates relative to the widget, so convert them accordingly.
3566 CSSPoint anchorCss
{aAnchorX
, aAnchorY
};
3567 LayoutDeviceIntPoint anchor
=
3568 RoundedToInt(anchorCss
* widget
->GetDefaultScale());
3569 anchor
-= widget
->WidgetToScreenOffset();
3571 success
= widget
->StartAsyncAutoscroll(
3572 ViewAs
<ScreenPixel
>(
3573 anchor
, PixelCastJustification::LayoutDeviceIsScreenForBounds
),
3580 void BrowserParent::StopApzAutoscroll(nsViewID aScrollId
,
3581 uint32_t aPresShellId
) {
3582 if (!AsyncPanZoomEnabled()) {
3586 if (mRemoteLayerTreeOwner
.IsInitialized()) {
3587 layers::LayersId layersId
= mRemoteLayerTreeOwner
.GetLayersId();
3588 if (nsCOMPtr
<nsIWidget
> widget
= GetWidget()) {
3589 ScrollableLayerGuid
guid(layersId
, aPresShellId
, aScrollId
);
3591 widget
->StopAsyncAutoscroll(guid
);
3596 void BrowserParent::SuppressDisplayport(bool aEnabled
) {
3597 if (IsDestroyed()) {
3603 mActiveSupressDisplayportCount
++;
3605 mActiveSupressDisplayportCount
--;
3607 MOZ_ASSERT(mActiveSupressDisplayportCount
>= 0);
3610 Unused
<< SendSuppressDisplayport(aEnabled
);
3613 void BrowserParent::NavigateByKey(bool aForward
, bool aForDocumentNavigation
) {
3614 Unused
<< SendNavigateByKey(aForward
, aForDocumentNavigation
);
3617 void BrowserParent::LayerTreeUpdate(const LayersObserverEpoch
& aEpoch
,
3619 // Ignore updates if we're an out-of-process iframe. For oop iframes, our
3620 // |mFrameElement| is that of the top-level document, and so AsyncTabSwitcher
3621 // will treat MozLayerTreeReady / MozLayerTreeCleared events as if they came
3622 // from the top-level tab, which is wrong.
3624 // XXX: Should we still be updating |mHasLayers|?
3625 if (GetBrowserBridgeParent()) {
3629 // Ignore updates from old epochs. They might tell us that layers are
3630 // available when we've already sent a message to clear them. We can't trust
3631 // the update in that case since layers could disappear anytime after that.
3632 if (aEpoch
!= mLayerTreeEpoch
|| mIsDestroyed
) {
3636 RefPtr
<EventTarget
> target
= mFrameElement
;
3638 NS_WARNING("Could not locate target for layer tree message.");
3642 mHasLayers
= aActive
;
3644 RefPtr
<Event
> event
= NS_NewDOMEvent(mFrameElement
, nullptr, nullptr);
3646 mHasPresented
= true;
3647 event
->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false);
3649 event
->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false);
3651 event
->SetTrusted(true);
3652 event
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
3653 mFrameElement
->DispatchEvent(*event
);
3656 mozilla::ipc::IPCResult
BrowserParent::RecvPaintWhileInterruptingJSNoOp(
3657 const LayersObserverEpoch
& aEpoch
) {
3658 // We sent a PaintWhileInterruptingJS message when layers were already
3659 // visible. In this case, we should act as if an update occurred even though
3660 // we already have the layers.
3661 LayerTreeUpdate(aEpoch
, true);
3665 mozilla::ipc::IPCResult
BrowserParent::RecvRemotePaintIsReady() {
3666 RefPtr
<EventTarget
> target
= mFrameElement
;
3668 NS_WARNING("Could not locate target for MozAfterRemotePaint message.");
3672 RefPtr
<Event
> event
= NS_NewDOMEvent(mFrameElement
, nullptr, nullptr);
3673 event
->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false);
3674 event
->SetTrusted(true);
3675 event
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
3676 mFrameElement
->DispatchEvent(*event
);
3680 mozilla::ipc::IPCResult
BrowserParent::RecvNotifyCompositorTransaction() {
3681 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
3687 nsIFrame
* docFrame
= frameLoader
->GetPrimaryFrameOfOwningContent();
3690 // Bad, but nothing we can do about it (XXX/cjones: or is there?
3691 // maybe bug 589337?). When the new frame is created, we'll
3692 // probably still be the current render frame and will get to draw
3693 // our content then. Or, we're shutting down and this update goes
3698 docFrame
->InvalidateLayer(DisplayItemType::TYPE_REMOTE
);
3702 mozilla::ipc::IPCResult
BrowserParent::RecvRemoteIsReadyToHandleInputEvents() {
3703 // When enabling input event prioritization, input events may preempt other
3704 // normal priority IPC messages. To prevent the input events preempt
3705 // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
3706 // notify the parent that BrowserChild is created and ready to handle input
3708 SetReadyToHandleInputEvents();
3712 mozilla::plugins::PPluginWidgetParent
*
3713 BrowserParent::AllocPPluginWidgetParent() {
3715 return new mozilla::plugins::PluginWidgetParent();
3717 MOZ_ASSERT_UNREACHABLE("AllocPPluginWidgetParent only supports Windows");
3722 bool BrowserParent::DeallocPPluginWidgetParent(
3723 mozilla::plugins::PPluginWidgetParent
* aActor
) {
3728 PPaymentRequestParent
* BrowserParent::AllocPPaymentRequestParent() {
3729 RefPtr
<PaymentRequestParent
> actor
= new PaymentRequestParent();
3730 return actor
.forget().take();
3733 bool BrowserParent::DeallocPPaymentRequestParent(
3734 PPaymentRequestParent
* aActor
) {
3735 RefPtr
<PaymentRequestParent
> actor
=
3736 dont_AddRef(static_cast<PaymentRequestParent
*>(aActor
));
3740 nsresult
BrowserParent::HandleEvent(Event
* aEvent
) {
3745 nsAutoString eventType
;
3746 aEvent
->GetType(eventType
);
3747 if (eventType
.EqualsLiteral("MozUpdateWindowPos") ||
3748 eventType
.EqualsLiteral("fullscreenchange")) {
3749 // Events that signify the window moving are used to update the position
3750 // and notify the BrowserChild.
3751 return UpdatePosition();
3756 class FakeChannel final
: public nsIChannel
,
3757 public nsIAuthPromptCallback
,
3758 public nsIInterfaceRequestor
,
3759 public nsILoadContext
{
3761 FakeChannel(const nsCString
& aUri
, uint64_t aCallbackId
, Element
* aElement
)
3762 : mCallbackId(aCallbackId
), mElement(aElement
) {
3763 NS_NewURI(getter_AddRefs(mUri
), aUri
);
3769 override { return NS_ERROR_NOT_IMPLEMENTED; }
3770 NS_IMETHOD
GetName(nsACString
&) NO_IMPL
;
3771 NS_IMETHOD
IsPending(bool*) NO_IMPL
;
3772 NS_IMETHOD
GetStatus(nsresult
*) NO_IMPL
;
3773 NS_IMETHOD
Cancel(nsresult
) NO_IMPL
;
3774 NS_IMETHOD
GetCanceled(bool* aCanceled
) NO_IMPL
;
3775 NS_IMETHOD
Suspend() NO_IMPL
;
3776 NS_IMETHOD
Resume() NO_IMPL
;
3777 NS_IMETHOD
GetLoadGroup(nsILoadGroup
**) NO_IMPL
;
3778 NS_IMETHOD
SetLoadGroup(nsILoadGroup
*) NO_IMPL
;
3779 NS_IMETHOD
SetLoadFlags(nsLoadFlags
) NO_IMPL
;
3780 NS_IMETHOD
GetLoadFlags(nsLoadFlags
*) NO_IMPL
;
3781 NS_IMETHOD
GetTRRMode(nsIRequest::TRRMode
* aTRRMode
) NO_IMPL
;
3782 NS_IMETHOD
SetTRRMode(nsIRequest::TRRMode aMode
) NO_IMPL
;
3783 NS_IMETHOD
GetIsDocument(bool*) NO_IMPL
;
3784 NS_IMETHOD
GetOriginalURI(nsIURI
**) NO_IMPL
;
3785 NS_IMETHOD
SetOriginalURI(nsIURI
*) NO_IMPL
;
3786 NS_IMETHOD
GetURI(nsIURI
** aUri
) override
{
3787 nsCOMPtr
<nsIURI
> copy
= mUri
;
3791 NS_IMETHOD
GetOwner(nsISupports
**) NO_IMPL
;
3792 NS_IMETHOD
SetOwner(nsISupports
*) NO_IMPL
;
3793 NS_IMETHOD
GetLoadInfo(nsILoadInfo
** aLoadInfo
) override
{
3794 nsCOMPtr
<nsILoadInfo
> copy
= mLoadInfo
;
3795 copy
.forget(aLoadInfo
);
3798 NS_IMETHOD
SetLoadInfo(nsILoadInfo
* aLoadInfo
) override
{
3799 mLoadInfo
= aLoadInfo
;
3802 NS_IMETHOD
GetNotificationCallbacks(
3803 nsIInterfaceRequestor
** aRequestor
) override
{
3804 NS_ADDREF(*aRequestor
= this);
3807 NS_IMETHOD
SetNotificationCallbacks(nsIInterfaceRequestor
*) NO_IMPL
;
3808 NS_IMETHOD
GetSecurityInfo(nsISupports
**) NO_IMPL
;
3809 NS_IMETHOD
GetContentType(nsACString
&) NO_IMPL
;
3810 NS_IMETHOD
SetContentType(const nsACString
&) NO_IMPL
;
3811 NS_IMETHOD
GetContentCharset(nsACString
&) NO_IMPL
;
3812 NS_IMETHOD
SetContentCharset(const nsACString
&) NO_IMPL
;
3813 NS_IMETHOD
GetContentLength(int64_t*) NO_IMPL
;
3814 NS_IMETHOD
SetContentLength(int64_t) NO_IMPL
;
3815 NS_IMETHOD
Open(nsIInputStream
**) NO_IMPL
;
3816 NS_IMETHOD
AsyncOpen(nsIStreamListener
*) NO_IMPL
;
3817 NS_IMETHOD
GetContentDisposition(uint32_t*) NO_IMPL
;
3818 NS_IMETHOD
SetContentDisposition(uint32_t) NO_IMPL
;
3819 NS_IMETHOD
GetContentDispositionFilename(nsAString
&) NO_IMPL
;
3820 NS_IMETHOD
SetContentDispositionFilename(const nsAString
&) NO_IMPL
;
3821 NS_IMETHOD
GetContentDispositionHeader(nsACString
&) NO_IMPL
;
3822 NS_IMETHOD
OnAuthAvailable(nsISupports
* aContext
,
3823 nsIAuthInformation
* aAuthInfo
) override
;
3824 NS_IMETHOD
OnAuthCancelled(nsISupports
* aContext
, bool userCancel
) override
;
3825 NS_IMETHOD
GetInterface(const nsIID
& uuid
, void** result
) override
{
3826 return QueryInterface(uuid
, result
);
3828 NS_IMETHOD
GetAssociatedWindow(mozIDOMWindowProxy
**) NO_IMPL
;
3829 NS_IMETHOD
GetTopWindow(mozIDOMWindowProxy
**) NO_IMPL
;
3830 NS_IMETHOD
GetTopFrameElement(Element
** aElement
) override
{
3831 RefPtr
<Element
> elem
= mElement
;
3832 elem
.forget(aElement
);
3835 NS_IMETHOD
GetIsContent(bool*) NO_IMPL
;
3836 NS_IMETHOD
GetUsePrivateBrowsing(bool*) NO_IMPL
;
3837 NS_IMETHOD
SetUsePrivateBrowsing(bool) NO_IMPL
;
3838 NS_IMETHOD
SetPrivateBrowsing(bool) NO_IMPL
;
3839 NS_IMETHOD
GetScriptableOriginAttributes(JSContext
*,
3840 JS::MutableHandleValue
) NO_IMPL
;
3842 GetOriginAttributes(mozilla::OriginAttributes
& aAttrs
) override
{}
3843 NS_IMETHOD
GetUseRemoteTabs(bool*) NO_IMPL
;
3844 NS_IMETHOD
SetRemoteTabs(bool) NO_IMPL
;
3845 NS_IMETHOD
GetUseRemoteSubframes(bool*) NO_IMPL
;
3846 NS_IMETHOD
SetRemoteSubframes(bool) NO_IMPL
;
3847 NS_IMETHOD
GetUseTrackingProtection(bool*) NO_IMPL
;
3848 NS_IMETHOD
SetUseTrackingProtection(bool) NO_IMPL
;
3852 ~FakeChannel() = default;
3854 nsCOMPtr
<nsIURI
> mUri
;
3855 uint64_t mCallbackId
;
3856 RefPtr
<Element
> mElement
;
3857 nsCOMPtr
<nsILoadInfo
> mLoadInfo
;
3860 NS_IMPL_ISUPPORTS(FakeChannel
, nsIChannel
, nsIAuthPromptCallback
, nsIRequest
,
3861 nsIInterfaceRequestor
, nsILoadContext
);
3863 mozilla::ipc::IPCResult
BrowserParent::RecvAsyncAuthPrompt(
3864 const nsCString
& aUri
, const nsString
& aRealm
,
3865 const uint64_t& aCallbackId
) {
3866 nsCOMPtr
<nsIAuthPrompt2
> authPrompt
;
3867 GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL
,
3868 NS_GET_IID(nsIAuthPrompt2
), getter_AddRefs(authPrompt
));
3869 RefPtr
<FakeChannel
> channel
=
3870 new FakeChannel(aUri
, aCallbackId
, mFrameElement
);
3871 uint32_t promptFlags
= nsIAuthInformation::AUTH_HOST
;
3873 RefPtr
<nsAuthInformationHolder
> holder
=
3874 new nsAuthInformationHolder(promptFlags
, aRealm
, EmptyCString());
3876 uint32_t level
= nsIAuthPrompt2::LEVEL_NONE
;
3877 nsCOMPtr
<nsICancelable
> dummy
;
3878 nsresult rv
= authPrompt
->AsyncPromptAuth(channel
, channel
, nullptr, level
,
3879 holder
, getter_AddRefs(dummy
));
3881 if (NS_FAILED(rv
)) {
3882 return IPC_FAIL_NO_REASON(this);
3887 mozilla::ipc::IPCResult
BrowserParent::RecvInvokeDragSession(
3888 nsTArray
<IPCDataTransfer
>&& aTransfers
, const uint32_t& aAction
,
3889 Maybe
<Shmem
>&& aVisualDnDData
, const uint32_t& aStride
,
3890 const gfx::SurfaceFormat
& aFormat
, const LayoutDeviceIntRect
& aDragRect
,
3891 nsIPrincipal
* aPrincipal
, nsIContentSecurityPolicy
* aCsp
) {
3892 PresShell
* presShell
= mFrameElement
->OwnerDoc()->GetPresShell();
3894 Unused
<< Manager()->SendEndDragSession(true, true, LayoutDeviceIntPoint(),
3896 // Continue sending input events with input priority when stopping the dnd
3898 Manager()->SetInputPriorityEventEnabled(true);
3902 RefPtr
<RemoteDragStartData
> dragStartData
= new RemoteDragStartData(
3903 this, std::move(aTransfers
), aDragRect
, aPrincipal
, aCsp
);
3905 if (!aVisualDnDData
.isNothing() && aVisualDnDData
.ref().IsReadable() &&
3906 aVisualDnDData
.ref().Size
<char>() >= aDragRect
.height
* aStride
) {
3907 dragStartData
->SetVisualization(gfx::CreateDataSourceSurfaceFromData(
3908 gfx::IntSize(aDragRect
.width
, aDragRect
.height
), aFormat
,
3909 aVisualDnDData
.ref().get
<uint8_t>(), aStride
));
3912 nsCOMPtr
<nsIDragService
> dragService
=
3913 do_GetService("@mozilla.org/widget/dragservice;1");
3915 dragService
->MaybeAddChildProcess(Manager());
3918 presShell
->GetPresContext()
3919 ->EventStateManager()
3920 ->BeginTrackingRemoteDragGesture(mFrameElement
, dragStartData
);
3922 if (aVisualDnDData
.isSome()) {
3923 Unused
<< DeallocShmem(aVisualDnDData
.ref());
3929 bool BrowserParent::AsyncPanZoomEnabled() const {
3930 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3931 return widget
&& widget
->AsyncPanZoomEnabled();
3934 void BrowserParent::StartPersistence(
3935 CanonicalBrowsingContext
* aContext
,
3936 nsIWebBrowserPersistDocumentReceiver
* aRecv
, ErrorResult
& aRv
) {
3937 auto* actor
= new WebBrowserPersistDocumentParent();
3938 actor
->SetOnReady(aRecv
);
3939 bool ok
= Manager()->SendPWebBrowserPersistDocumentConstructor(actor
, this,
3942 aRv
.Throw(NS_ERROR_FAILURE
);
3944 // (The actor will be destroyed on constructor failure.)
3947 mozilla::ipc::IPCResult
BrowserParent::RecvLookUpDictionary(
3948 const nsString
& aText
, nsTArray
<FontRange
>&& aFontRangeArray
,
3949 const bool& aIsVertical
, const LayoutDeviceIntPoint
& aPoint
) {
3950 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3955 widget
->LookUpDictionary(aText
, aFontRangeArray
, aIsVertical
,
3956 TransformChildToParent(aPoint
));
3960 mozilla::ipc::IPCResult
BrowserParent::RecvShowCanvasPermissionPrompt(
3961 const nsCString
& aOrigin
, const bool& aHideDoorHanger
) {
3962 nsCOMPtr
<nsIBrowser
> browser
=
3963 mFrameElement
? mFrameElement
->AsBrowser() : nullptr;
3965 // If the tab is being closed, the browser may not be available.
3966 // In this case we can ignore the request.
3969 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
3971 return IPC_FAIL_NO_REASON(this);
3973 nsresult rv
= os
->NotifyObservers(
3975 aHideDoorHanger
? "canvas-permissions-prompt-hide-doorhanger"
3976 : "canvas-permissions-prompt",
3977 NS_ConvertUTF8toUTF16(aOrigin
).get());
3978 if (NS_FAILED(rv
)) {
3979 return IPC_FAIL_NO_REASON(this);
3984 mozilla::ipc::IPCResult
BrowserParent::RecvVisitURI(nsIURI
* aURI
,
3985 nsIURI
* aLastVisitedURI
,
3986 const uint32_t& aFlags
) {
3988 return IPC_FAIL_NO_REASON(this);
3990 RefPtr
<nsIWidget
> widget
= GetWidget();
3991 if (NS_WARN_IF(!widget
)) {
3994 nsCOMPtr
<IHistory
> history
= services::GetHistoryService();
3996 Unused
<< history
->VisitURI(widget
, aURI
, aLastVisitedURI
, aFlags
);
4001 mozilla::ipc::IPCResult
BrowserParent::RecvQueryVisitedState(
4002 const nsTArray
<RefPtr
<nsIURI
>>&& aURIs
) {
4003 #ifdef MOZ_ANDROID_HISTORY
4004 nsCOMPtr
<IHistory
> history
= services::GetHistoryService();
4005 if (NS_WARN_IF(!history
)) {
4008 RefPtr
<nsIWidget
> widget
= GetWidget();
4009 if (NS_WARN_IF(!widget
)) {
4013 for (size_t i
= 0; i
< aURIs
.Length(); ++i
) {
4015 return IPC_FAIL(this, "Received null URI");
4019 GeckoViewHistory
* gvHistory
= static_cast<GeckoViewHistory
*>(history
.get());
4020 gvHistory
->QueryVisitedState(widget
, std::move(aURIs
));
4024 return IPC_FAIL(this, "QueryVisitedState is Android-only");
4028 void BrowserParent::LiveResizeStarted() { SuppressDisplayport(true); }
4030 void BrowserParent::LiveResizeStopped() { SuppressDisplayport(false); }
4032 void BrowserParent::SetBrowserBridgeParent(BrowserBridgeParent
* aBrowser
) {
4033 // We should either be clearing out our reference to a browser bridge, or not
4034 // have either a browser bridge, browser host, or owner content yet.
4035 MOZ_ASSERT(!aBrowser
||
4036 (!mBrowserBridgeParent
&& !mBrowserHost
&& !mFrameElement
));
4037 mBrowserBridgeParent
= aBrowser
;
4040 void BrowserParent::SetBrowserHost(BrowserHost
* aBrowser
) {
4041 // We should either be clearing out our reference to a browser host, or not
4042 // have either a browser bridge, browser host, or owner content yet.
4043 MOZ_ASSERT(!aBrowser
||
4044 (!mBrowserBridgeParent
&& !mBrowserHost
&& !mFrameElement
));
4045 mBrowserHost
= aBrowser
;
4048 mozilla::ipc::IPCResult
BrowserParent::RecvSetSystemFont(
4049 const nsCString
& aFontName
) {
4050 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4052 widget
->SetSystemFont(aFontName
);
4057 mozilla::ipc::IPCResult
BrowserParent::RecvGetSystemFont(nsCString
* aFontName
) {
4058 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4060 widget
->GetSystemFont(*aFontName
);
4065 mozilla::ipc::IPCResult
BrowserParent::RecvMaybeFireEmbedderLoadEvents(
4066 EmbedderElementEventType aFireEventAtEmbeddingElement
) {
4067 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
4069 NS_WARNING("Received `load` event on unbridged BrowserParent!");
4073 Unused
<< bridge
->SendMaybeFireEmbedderLoadEvents(
4074 aFireEventAtEmbeddingElement
);
4078 mozilla::ipc::IPCResult
BrowserParent::RecvScrollRectIntoView(
4079 const nsRect
& aRect
, const ScrollAxis
& aVertical
,
4080 const ScrollAxis
& aHorizontal
, const ScrollFlags
& aScrollFlags
,
4081 const int32_t& aAppUnitsPerDevPixel
) {
4082 BrowserBridgeParent
* bridge
= GetBrowserBridgeParent();
4083 if (!bridge
|| !bridge
->CanSend()) {
4087 Unused
<< bridge
->SendScrollRectIntoView(aRect
, aVertical
, aHorizontal
,
4088 aScrollFlags
, aAppUnitsPerDevPixel
);
4093 FakeChannel::OnAuthAvailable(nsISupports
* aContext
,
4094 nsIAuthInformation
* aAuthInfo
) {
4095 nsAuthInformationHolder
* holder
=
4096 static_cast<nsAuthInformationHolder
*>(aAuthInfo
);
4098 if (!net::gNeckoChild
->SendOnAuthAvailable(
4099 mCallbackId
, holder
->User(), holder
->Password(), holder
->Domain())) {
4100 return NS_ERROR_FAILURE
;
4106 FakeChannel::OnAuthCancelled(nsISupports
* aContext
, bool userCancel
) {
4107 if (!net::gNeckoChild
->SendOnAuthCancelled(mCallbackId
, userCancel
)) {
4108 return NS_ERROR_FAILURE
;
4113 mozilla::ipc::IPCResult
BrowserParent::RecvIsWindowSupportingProtectedMedia(
4114 const uint64_t& aOuterWindowID
,
4115 IsWindowSupportingProtectedMediaResolver
&& aResolve
) {
4118 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID
);
4119 aResolve(!isFxrWindow
);
4121 MOZ_CRASH("Should only be called on Windows");
4127 mozilla::ipc::IPCResult
BrowserParent::RecvIsWindowSupportingWebVR(
4128 const uint64_t& aOuterWindowID
,
4129 IsWindowSupportingWebVRResolver
&& aResolve
) {
4132 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID
);
4133 aResolve(!isFxrWindow
);
4142 } // namespace mozilla