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/. */
8 # include "mozilla/a11y/DocAccessibleParent.h"
9 # include "nsAccessibilityService.h"
12 #include "mozilla/Monitor.h"
13 #include "mozilla/MouseEvents.h"
14 #include "mozilla/dom/BrowserBridgeParent.h"
15 #include "mozilla/dom/BrowserParent.h"
16 #include "mozilla/dom/ContentParent.h"
17 #include "mozilla/dom/ContentProcessManager.h"
18 #include "mozilla/dom/CanonicalBrowsingContext.h"
19 #include "mozilla/dom/BrowsingContextGroup.h"
20 #include "mozilla/dom/WindowGlobalParent.h"
21 #include "mozilla/ipc/Endpoint.h"
22 #include "mozilla/layers/InputAPZContext.h"
24 using namespace mozilla::ipc
;
25 using namespace mozilla::layout
;
26 using namespace mozilla::hal
;
28 namespace mozilla::dom
{
30 BrowserBridgeParent::BrowserBridgeParent() = default;
32 BrowserBridgeParent::~BrowserBridgeParent() { Destroy(); }
34 nsresult
BrowserBridgeParent::InitWithProcess(
35 BrowserParent
* aParentBrowser
, ContentParent
* aContentParent
,
36 const WindowGlobalInit
& aWindowInit
, uint32_t aChromeFlags
, TabId aTabId
) {
37 MOZ_ASSERT(!CanSend(),
38 "This should be called before the object is connected to IPC");
39 MOZ_DIAGNOSTIC_ASSERT(!aContentParent
->IsLaunching());
40 MOZ_DIAGNOSTIC_ASSERT(!aContentParent
->IsDead());
42 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
43 CanonicalBrowsingContext::Get(aWindowInit
.context().mBrowsingContextId
);
44 if (!browsingContext
|| browsingContext
->IsDiscarded()) {
45 return NS_ERROR_UNEXPECTED
;
48 MOZ_DIAGNOSTIC_ASSERT(
49 !browsingContext
->GetBrowserParent(),
50 "BrowsingContext must have had previous BrowserParent cleared");
52 MOZ_DIAGNOSTIC_ASSERT(
53 aParentBrowser
->Manager() != aContentParent
,
54 "Cannot create OOP iframe in the same process as its parent document");
56 // Unfortunately, due to the current racy destruction of BrowsingContext
57 // instances when Fission is enabled, while `browsingContext` may not be
58 // discarded, an ancestor might be.
60 // A discarded ancestor will cause us issues when creating our `BrowserParent`
61 // in the new content process, so abort the attempt if we have one.
63 // FIXME: We should never have a non-discarded BrowsingContext with discarded
64 // ancestors. (bug 1634759)
65 if (NS_WARN_IF(!browsingContext
->AncestorsAreCurrent())) {
66 return NS_ERROR_UNEXPECTED
;
69 // Ensure that our content process is subscribed to our newly created
70 // BrowsingContextGroup.
71 browsingContext
->Group()->EnsureHostProcess(aContentParent
);
72 browsingContext
->SetOwnerProcessId(aContentParent
->ChildID());
74 // Construct the BrowserParent object for our subframe.
75 auto browserParent
= MakeRefPtr
<BrowserParent
>(
76 aContentParent
, aTabId
, *aParentBrowser
, browsingContext
, aChromeFlags
);
77 browserParent
->SetBrowserBridgeParent(this);
79 // Open a remote endpoint for our PBrowser actor.
80 ManagedEndpoint
<PBrowserChild
> childEp
=
81 aContentParent
->OpenPBrowserEndpoint(browserParent
);
82 if (NS_WARN_IF(!childEp
.IsValid())) {
83 MOZ_ASSERT(false, "Browser Open Endpoint Failed");
84 return NS_ERROR_FAILURE
;
87 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
89 return NS_ERROR_UNEXPECTED
;
91 cpm
->RegisterRemoteFrame(browserParent
);
93 RefPtr
<WindowGlobalParent
> windowParent
=
94 WindowGlobalParent::CreateDisconnected(aWindowInit
);
96 return NS_ERROR_UNEXPECTED
;
99 ManagedEndpoint
<PWindowGlobalChild
> windowChildEp
=
100 browserParent
->OpenPWindowGlobalEndpoint(windowParent
);
101 if (NS_WARN_IF(!windowChildEp
.IsValid())) {
102 MOZ_ASSERT(false, "WindowGlobal Open Endpoint Failed");
103 return NS_ERROR_FAILURE
;
106 MOZ_DIAGNOSTIC_ASSERT(!browsingContext
->IsDiscarded(),
107 "bc cannot have become discarded");
109 // Tell the content process to set up its PBrowserChild.
110 bool ok
= aContentParent
->SendConstructBrowser(
111 std::move(childEp
), std::move(windowChildEp
), aTabId
,
112 browserParent
->AsIPCTabContext(), aWindowInit
, aChromeFlags
,
113 aContentParent
->ChildID(), aContentParent
->IsForBrowser(),
114 /* aIsTopLevel */ false);
115 if (NS_WARN_IF(!ok
)) {
116 MOZ_ASSERT(false, "Browser Constructor Failed");
117 return NS_ERROR_FAILURE
;
120 // Set our BrowserParent object to the newly created browser.
121 mBrowserParent
= std::move(browserParent
);
122 mBrowserParent
->SetOwnerElement(aParentBrowser
->GetOwnerElement());
123 mBrowserParent
->InitRendering();
125 GetBrowsingContext()->SetCurrentBrowserParent(mBrowserParent
);
127 windowParent
->Init();
131 CanonicalBrowsingContext
* BrowserBridgeParent::GetBrowsingContext() {
132 return mBrowserParent
->GetBrowsingContext();
135 BrowserParent
* BrowserBridgeParent::Manager() {
136 MOZ_ASSERT(CanSend());
137 return static_cast<BrowserParent
*>(PBrowserBridgeParent::Manager());
140 void BrowserBridgeParent::Destroy() {
141 if (mBrowserParent
) {
143 if (mEmbedderAccessibleDoc
&& !mEmbedderAccessibleDoc
->IsShutdown()) {
144 mEmbedderAccessibleDoc
->RemovePendingOOPChildDoc(this);
147 mBrowserParent
->Destroy();
148 mBrowserParent
->SetBrowserBridgeParent(nullptr);
149 mBrowserParent
= nullptr;
152 Unused
<< Send__delete__(this);
156 IPCResult
BrowserBridgeParent::RecvShow(const OwnerShowInfo
& aOwnerInfo
) {
157 mBrowserParent
->AttachWindowRenderer();
158 Unused
<< mBrowserParent
->SendShow(mBrowserParent
->GetShowInfo(), aOwnerInfo
);
162 IPCResult
BrowserBridgeParent::RecvScrollbarPreferenceChanged(
163 ScrollbarPreference aPref
) {
164 Unused
<< mBrowserParent
->SendScrollbarPreferenceChanged(aPref
);
168 IPCResult
BrowserBridgeParent::RecvLoadURL(nsDocShellLoadState
* aLoadState
) {
169 Unused
<< mBrowserParent
->SendLoadURL(WrapNotNull(aLoadState
),
170 mBrowserParent
->GetShowInfo());
174 IPCResult
BrowserBridgeParent::RecvResumeLoad(uint64_t aPendingSwitchID
) {
175 mBrowserParent
->ResumeLoad(aPendingSwitchID
);
179 IPCResult
BrowserBridgeParent::RecvUpdateDimensions(
180 const nsIntRect
& aRect
, const ScreenIntSize
& aSize
) {
181 mBrowserParent
->UpdateDimensions(aRect
, aSize
);
185 IPCResult
BrowserBridgeParent::RecvUpdateEffects(const EffectsInfo
& aEffects
) {
186 Unused
<< mBrowserParent
->SendUpdateEffects(aEffects
);
190 IPCResult
BrowserBridgeParent::RecvUpdateRemotePrintSettings(
191 const embedding::PrintData
& aPrintData
) {
192 Unused
<< mBrowserParent
->SendUpdateRemotePrintSettings(aPrintData
);
196 IPCResult
BrowserBridgeParent::RecvRenderLayers(const bool& aEnabled
) {
197 Unused
<< mBrowserParent
->SendRenderLayers(aEnabled
);
201 IPCResult
BrowserBridgeParent::RecvNavigateByKey(
202 const bool& aForward
, const bool& aForDocumentNavigation
) {
203 Unused
<< mBrowserParent
->SendNavigateByKey(aForward
, aForDocumentNavigation
);
207 IPCResult
BrowserBridgeParent::RecvBeginDestroy() {
212 IPCResult
BrowserBridgeParent::RecvDispatchSynthesizedMouseEvent(
213 const WidgetMouseEvent
& aEvent
) {
214 if (aEvent
.mMessage
!= eMouseMove
||
215 aEvent
.mReason
!= WidgetMouseEvent::eSynthesized
) {
216 return IPC_FAIL(this, "Unexpected event type");
219 nsCOMPtr
<nsIWidget
> widget
= Manager()->GetWidget();
224 WidgetMouseEvent event
= aEvent
;
225 event
.mWidget
= widget
;
226 // Convert mRefPoint from the dispatching child process coordinate space
227 // to the parent coordinate space. The SendRealMouseEvent call will convert
228 // it into the dispatchee child process coordinate space
229 event
.mRefPoint
= Manager()->TransformChildToParent(event
.mRefPoint
);
230 // We need to set up an InputAPZContext on the stack because
231 // BrowserParent::SendRealMouseEvent requires one. But the only thing in
232 // that context that is actually used in this scenario is the layers id,
233 // and we already have that on the mouse event.
234 layers::InputAPZContext
context(
235 layers::ScrollableLayerGuid(event
.mLayersId
, 0,
236 layers::ScrollableLayerGuid::NULL_SCROLL_ID
),
237 0, nsEventStatus_eIgnore
);
238 mBrowserParent
->SendRealMouseEvent(event
);
242 IPCResult
BrowserBridgeParent::RecvWillChangeProcess() {
243 Unused
<< mBrowserParent
->SendWillChangeProcess();
247 IPCResult
BrowserBridgeParent::RecvActivate(uint64_t aActionId
) {
248 mBrowserParent
->Activate(aActionId
);
252 IPCResult
BrowserBridgeParent::RecvDeactivate(const bool& aWindowLowering
,
253 uint64_t aActionId
) {
254 mBrowserParent
->Deactivate(aWindowLowering
, aActionId
);
258 mozilla::ipc::IPCResult
BrowserBridgeParent::RecvUpdateRemoteStyle(
259 const StyleImageRendering
& aImageRendering
) {
260 Unused
<< mBrowserParent
->SendUpdateRemoteStyle(aImageRendering
);
265 a11y::DocAccessibleParent
* BrowserBridgeParent::GetDocAccessibleParent() {
266 auto* embeddedBrowser
= GetBrowserParent();
267 if (!embeddedBrowser
) {
270 a11y::DocAccessibleParent
* docAcc
=
271 embeddedBrowser
->GetTopLevelDocAccessible();
272 return docAcc
&& !docAcc
->IsShutdown() ? docAcc
: nullptr;
275 IPCResult
BrowserBridgeParent::RecvSetEmbedderAccessible(
276 PDocAccessibleParent
* aDoc
, uint64_t aID
) {
277 # if defined(ANDROID)
278 MonitorAutoLock
mal(nsAccessibilityService::GetAndroidMonitor());
280 MOZ_ASSERT(aDoc
|| mEmbedderAccessibleDoc
,
281 "Embedder doc shouldn't be cleared if it wasn't set");
282 MOZ_ASSERT(!mEmbedderAccessibleDoc
|| !aDoc
|| mEmbedderAccessibleDoc
== aDoc
,
283 "Embedder doc shouldn't change from one doc to another");
284 if (!aDoc
&& mEmbedderAccessibleDoc
&&
285 !mEmbedderAccessibleDoc
->IsShutdown()) {
286 // We're clearing the embedder doc, so remove the pending child doc addition
288 mEmbedderAccessibleDoc
->RemovePendingOOPChildDoc(this);
290 mEmbedderAccessibleDoc
= static_cast<a11y::DocAccessibleParent
*>(aDoc
);
291 mEmbedderAccessibleID
= aID
;
297 if (GetDocAccessibleParent()) {
298 // The embedded DocAccessibleParent has already been created. This can
299 // happen if, for example, an iframe is hidden and then shown or
300 // an iframe is reflowed by layout.
301 mEmbedderAccessibleDoc
->AddChildDoc(this);
306 a11y::DocAccessibleParent
* BrowserBridgeParent::GetEmbedderAccessibleDoc() {
307 return mEmbedderAccessibleDoc
&& !mEmbedderAccessibleDoc
->IsShutdown()
308 ? mEmbedderAccessibleDoc
.get()
313 void BrowserBridgeParent::ActorDestroy(ActorDestroyReason aWhy
) { Destroy(); }
315 } // namespace mozilla::dom