Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / ipc / BrowserBridgeParent.cpp
blob4a687d557db57216ce3fc8609cef8f0beeb66262
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 #ifdef ACCESSIBILITY
8 # include "mozilla/a11y/DocAccessibleParent.h"
9 # include "nsAccessibilityService.h"
10 #endif
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();
88 if (!cpm) {
89 return NS_ERROR_UNEXPECTED;
91 cpm->RegisterRemoteFrame(browserParent);
93 RefPtr<WindowGlobalParent> windowParent =
94 WindowGlobalParent::CreateDisconnected(aWindowInit);
95 if (!windowParent) {
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();
128 return NS_OK;
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) {
142 #ifdef ACCESSIBILITY
143 if (mEmbedderAccessibleDoc && !mEmbedderAccessibleDoc->IsShutdown()) {
144 mEmbedderAccessibleDoc->RemovePendingOOPChildDoc(this);
146 #endif
147 mBrowserParent->Destroy();
148 mBrowserParent->SetBrowserBridgeParent(nullptr);
149 mBrowserParent = nullptr;
151 if (CanSend()) {
152 Unused << Send__delete__(this);
156 IPCResult BrowserBridgeParent::RecvShow(const OwnerShowInfo& aOwnerInfo) {
157 mBrowserParent->AttachWindowRenderer();
158 Unused << mBrowserParent->SendShow(mBrowserParent->GetShowInfo(), aOwnerInfo);
159 return IPC_OK();
162 IPCResult BrowserBridgeParent::RecvScrollbarPreferenceChanged(
163 ScrollbarPreference aPref) {
164 Unused << mBrowserParent->SendScrollbarPreferenceChanged(aPref);
165 return IPC_OK();
168 IPCResult BrowserBridgeParent::RecvLoadURL(nsDocShellLoadState* aLoadState) {
169 Unused << mBrowserParent->SendLoadURL(WrapNotNull(aLoadState),
170 mBrowserParent->GetShowInfo());
171 return IPC_OK();
174 IPCResult BrowserBridgeParent::RecvResumeLoad(uint64_t aPendingSwitchID) {
175 mBrowserParent->ResumeLoad(aPendingSwitchID);
176 return IPC_OK();
179 IPCResult BrowserBridgeParent::RecvUpdateDimensions(
180 const nsIntRect& aRect, const ScreenIntSize& aSize) {
181 mBrowserParent->UpdateDimensions(aRect, aSize);
182 return IPC_OK();
185 IPCResult BrowserBridgeParent::RecvUpdateEffects(const EffectsInfo& aEffects) {
186 Unused << mBrowserParent->SendUpdateEffects(aEffects);
187 return IPC_OK();
190 IPCResult BrowserBridgeParent::RecvUpdateRemotePrintSettings(
191 const embedding::PrintData& aPrintData) {
192 Unused << mBrowserParent->SendUpdateRemotePrintSettings(aPrintData);
193 return IPC_OK();
196 IPCResult BrowserBridgeParent::RecvRenderLayers(const bool& aEnabled) {
197 Unused << mBrowserParent->SendRenderLayers(aEnabled);
198 return IPC_OK();
201 IPCResult BrowserBridgeParent::RecvNavigateByKey(
202 const bool& aForward, const bool& aForDocumentNavigation) {
203 Unused << mBrowserParent->SendNavigateByKey(aForward, aForDocumentNavigation);
204 return IPC_OK();
207 IPCResult BrowserBridgeParent::RecvBeginDestroy() {
208 Destroy();
209 return IPC_OK();
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();
220 if (!widget) {
221 return IPC_OK();
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);
239 return IPC_OK();
242 IPCResult BrowserBridgeParent::RecvWillChangeProcess() {
243 Unused << mBrowserParent->SendWillChangeProcess();
244 return IPC_OK();
247 IPCResult BrowserBridgeParent::RecvActivate(uint64_t aActionId) {
248 mBrowserParent->Activate(aActionId);
249 return IPC_OK();
252 IPCResult BrowserBridgeParent::RecvDeactivate(const bool& aWindowLowering,
253 uint64_t aActionId) {
254 mBrowserParent->Deactivate(aWindowLowering, aActionId);
255 return IPC_OK();
258 mozilla::ipc::IPCResult BrowserBridgeParent::RecvUpdateRemoteStyle(
259 const StyleImageRendering& aImageRendering) {
260 Unused << mBrowserParent->SendUpdateRemoteStyle(aImageRendering);
261 return IPC_OK();
264 #ifdef ACCESSIBILITY
265 a11y::DocAccessibleParent* BrowserBridgeParent::GetDocAccessibleParent() {
266 auto* embeddedBrowser = GetBrowserParent();
267 if (!embeddedBrowser) {
268 return nullptr;
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());
279 # endif
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
287 // (if any).
288 mEmbedderAccessibleDoc->RemovePendingOOPChildDoc(this);
290 mEmbedderAccessibleDoc = static_cast<a11y::DocAccessibleParent*>(aDoc);
291 mEmbedderAccessibleID = aID;
292 if (!aDoc) {
293 MOZ_ASSERT(!aID);
294 return IPC_OK();
296 MOZ_ASSERT(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);
303 return IPC_OK();
306 a11y::DocAccessibleParent* BrowserBridgeParent::GetEmbedderAccessibleDoc() {
307 return mEmbedderAccessibleDoc && !mEmbedderAccessibleDoc->IsShutdown()
308 ? mEmbedderAccessibleDoc.get()
309 : nullptr;
311 #endif
313 void BrowserBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { Destroy(); }
315 } // namespace mozilla::dom