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/. */
6 
7 #ifdef ACCESSIBILITY
8 #  ifdef XP_WIN
9 #    include "mozilla/a11y/RemoteAccessible.h"
10 #    include "mozilla/a11y/ProxyWrappers.h"
11 #  endif
12 #  include "mozilla/a11y/DocAccessible.h"
13 #  include "mozilla/a11y/DocManager.h"
14 #  include "mozilla/a11y/OuterDocAccessible.h"
15 #endif
16 #include "mozilla/dom/BrowserBridgeChild.h"
17 #include "mozilla/dom/BrowserBridgeHost.h"
18 #include "mozilla/dom/BrowsingContext.h"
19 #include "mozilla/dom/MozFrameLoaderOwnerBinding.h"
20 #include "mozilla/PresShell.h"
21 #include "nsFocusManager.h"
22 #include "nsFrameLoader.h"
23 #include "nsFrameLoaderOwner.h"
24 #include "nsObjectLoadingContent.h"
25 #include "nsQueryObject.h"
26 #include "nsSubDocumentFrame.h"
27 #include "nsView.h"
28 
29 using namespace mozilla::ipc;
30 
31 mozilla::LazyLogModule gBrowserChildFocusLog("BrowserChildFocus");
32 
33 #define LOGBROWSERCHILDFOCUS(args) \
34   MOZ_LOG(gBrowserChildFocusLog, mozilla::LogLevel::Debug, args)
35 
36 namespace mozilla::dom {
37 
BrowserBridgeChild(BrowsingContext * aBrowsingContext,TabId aId,const LayersId & aLayersId)38 BrowserBridgeChild::BrowserBridgeChild(BrowsingContext* aBrowsingContext,
39                                        TabId aId, const LayersId& aLayersId)
40     : mId{aId}, mLayersId{aLayersId}, mBrowsingContext(aBrowsingContext) {}
41 
~BrowserBridgeChild()42 BrowserBridgeChild::~BrowserBridgeChild() {
43 #if defined(ACCESSIBILITY) && defined(XP_WIN)
44   if (mEmbeddedDocAccessible) {
45     mEmbeddedDocAccessible->Shutdown();
46   }
47 #endif
48 }
49 
FinishInit(nsFrameLoader * aFrameLoader)50 already_AddRefed<BrowserBridgeHost> BrowserBridgeChild::FinishInit(
51     nsFrameLoader* aFrameLoader) {
52   MOZ_DIAGNOSTIC_ASSERT(!mFrameLoader);
53   mFrameLoader = aFrameLoader;
54 
55   RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
56   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(owner->GetOwnerGlobal());
57   MOZ_DIAGNOSTIC_ASSERT(docShell);
58 
59   nsDocShell::Cast(docShell)->OOPChildLoadStarted(this);
60 
61 #if defined(ACCESSIBILITY)
62   if (a11y::DocAccessible* docAcc =
63           a11y::GetExistingDocAccessible(owner->OwnerDoc())) {
64     if (a11y::LocalAccessible* ownerAcc = docAcc->GetAccessible(owner)) {
65       if (a11y::OuterDocAccessible* outerAcc = ownerAcc->AsOuterDoc()) {
66         outerAcc->SendEmbedderAccessible(this);
67       }
68     }
69   }
70 #endif  // defined(ACCESSIBILITY)
71 
72   return MakeAndAddRef<BrowserBridgeHost>(this);
73 }
74 
GetLoadContext()75 nsILoadContext* BrowserBridgeChild::GetLoadContext() {
76   return mBrowsingContext;
77 }
78 
NavigateByKey(bool aForward,bool aForDocumentNavigation)79 void BrowserBridgeChild::NavigateByKey(bool aForward,
80                                        bool aForDocumentNavigation) {
81   Unused << SendNavigateByKey(aForward, aForDocumentNavigation);
82 }
83 
Activate(uint64_t aActionId)84 void BrowserBridgeChild::Activate(uint64_t aActionId) {
85   LOGBROWSERCHILDFOCUS(
86       ("BrowserBridgeChild::Activate actionid: %" PRIu64, aActionId));
87   Unused << SendActivate(aActionId);
88 }
89 
Deactivate(bool aWindowLowering,uint64_t aActionId)90 void BrowserBridgeChild::Deactivate(bool aWindowLowering, uint64_t aActionId) {
91   Unused << SendDeactivate(aWindowLowering, aActionId);
92 }
93 
SetIsUnderHiddenEmbedderElement(bool aIsUnderHiddenEmbedderElement)94 void BrowserBridgeChild::SetIsUnderHiddenEmbedderElement(
95     bool aIsUnderHiddenEmbedderElement) {
96   Unused << SendSetIsUnderHiddenEmbedderElement(aIsUnderHiddenEmbedderElement);
97 }
98 
99 /*static*/
GetFrom(nsFrameLoader * aFrameLoader)100 BrowserBridgeChild* BrowserBridgeChild::GetFrom(nsFrameLoader* aFrameLoader) {
101   if (!aFrameLoader) {
102     return nullptr;
103   }
104   return aFrameLoader->GetBrowserBridgeChild();
105 }
106 
107 /*static*/
GetFrom(nsIContent * aContent)108 BrowserBridgeChild* BrowserBridgeChild::GetFrom(nsIContent* aContent) {
109   RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(aContent);
110   if (!loaderOwner) {
111     return nullptr;
112   }
113   RefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
114   return GetFrom(frameLoader);
115 }
116 
RecvRequestFocus(const bool & aCanRaise,const CallerType aCallerType)117 mozilla::ipc::IPCResult BrowserBridgeChild::RecvRequestFocus(
118     const bool& aCanRaise, const CallerType aCallerType) {
119   // Adapted from BrowserParent
120   RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
121   if (!owner) {
122     return IPC_OK();
123   }
124   nsContentUtils::RequestFrameFocus(*owner, aCanRaise, aCallerType);
125   return IPC_OK();
126 }
127 
RecvMoveFocus(const bool & aForward,const bool & aForDocumentNavigation)128 mozilla::ipc::IPCResult BrowserBridgeChild::RecvMoveFocus(
129     const bool& aForward, const bool& aForDocumentNavigation) {
130   // Adapted from BrowserParent
131   RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
132   if (!fm) {
133     return IPC_OK();
134   }
135 
136   RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
137   if (!owner) {
138     return IPC_OK();
139   }
140 
141   RefPtr<Element> dummy;
142 
143   uint32_t type =
144       aForward
145           ? (aForDocumentNavigation
146                  ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARDDOC)
147                  : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARD))
148           : (aForDocumentNavigation
149                  ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_BACKWARDDOC)
150                  : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_BACKWARD));
151   fm->MoveFocus(nullptr, owner, type, nsIFocusManager::FLAG_BYKEY,
152                 getter_AddRefs(dummy));
153   return IPC_OK();
154 }
155 
156 mozilla::ipc::IPCResult
RecvSetEmbeddedDocAccessibleCOMProxy(const a11y::IDispatchHolder & aCOMProxy)157 BrowserBridgeChild::RecvSetEmbeddedDocAccessibleCOMProxy(
158     const a11y::IDispatchHolder& aCOMProxy) {
159 #if defined(ACCESSIBILITY) && defined(XP_WIN)
160   MOZ_ASSERT(!aCOMProxy.IsNull());
161   if (mEmbeddedDocAccessible) {
162     mEmbeddedDocAccessible->Shutdown();
163   }
164   RefPtr<IDispatch> comProxy(aCOMProxy.Get());
165   mEmbeddedDocAccessible =
166       new a11y::RemoteIframeDocRemoteAccessibleWrap(comProxy);
167 #endif
168   return IPC_OK();
169 }
170 
RecvMaybeFireEmbedderLoadEvents(EmbedderElementEventType aFireEventAtEmbeddingElement)171 mozilla::ipc::IPCResult BrowserBridgeChild::RecvMaybeFireEmbedderLoadEvents(
172     EmbedderElementEventType aFireEventAtEmbeddingElement) {
173   RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
174   if (!owner) {
175     return IPC_OK();
176   }
177 
178   if (aFireEventAtEmbeddingElement == EmbedderElementEventType::LoadEvent) {
179     nsEventStatus status = nsEventStatus_eIgnore;
180     WidgetEvent event(/* aIsTrusted = */ true, eLoad);
181     event.mFlags.mBubbles = false;
182     event.mFlags.mCancelable = false;
183     EventDispatcher::Dispatch(owner, nullptr, &event, nullptr, &status);
184   } else if (aFireEventAtEmbeddingElement ==
185              EmbedderElementEventType::ErrorEvent) {
186     mFrameLoader->FireErrorEvent();
187   }
188 
189   UnblockOwnerDocsLoadEvent();
190 
191   return IPC_OK();
192 }
193 
RecvScrollRectIntoView(const nsRect & aRect,const ScrollAxis & aVertical,const ScrollAxis & aHorizontal,const ScrollFlags & aScrollFlags,const int32_t & aAppUnitsPerDevPixel)194 mozilla::ipc::IPCResult BrowserBridgeChild::RecvScrollRectIntoView(
195     const nsRect& aRect, const ScrollAxis& aVertical,
196     const ScrollAxis& aHorizontal, const ScrollFlags& aScrollFlags,
197     const int32_t& aAppUnitsPerDevPixel) {
198   RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
199   if (!owner) {
200     return IPC_OK();
201   }
202 
203   nsIFrame* frame = owner->GetPrimaryFrame();
204   if (!frame) {
205     return IPC_OK();
206   }
207 
208   nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(frame);
209   if (!subdocumentFrame) {
210     return IPC_OK();
211   }
212 
213   nsPoint extraOffset = subdocumentFrame->GetExtraOffset();
214 
215   int32_t parentAPD = frame->PresContext()->AppUnitsPerDevPixel();
216   nsRect rect =
217       aRect.ScaleToOtherAppUnitsRoundOut(aAppUnitsPerDevPixel, parentAPD);
218   rect += extraOffset;
219   RefPtr<PresShell> presShell = frame->PresShell();
220   presShell->ScrollFrameRectIntoView(frame, rect, nsMargin(), aVertical,
221                                      aHorizontal, aScrollFlags);
222 
223   return IPC_OK();
224 }
225 
RecvSubFrameCrashed()226 mozilla::ipc::IPCResult BrowserBridgeChild::RecvSubFrameCrashed() {
227   if (RefPtr<nsFrameLoaderOwner> frameLoaderOwner =
228           do_QueryObject(mFrameLoader->GetOwnerContent())) {
229     frameLoaderOwner->SubframeCrashed();
230   }
231   return IPC_OK();
232 }
233 
ActorDestroy(ActorDestroyReason aWhy)234 void BrowserBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
235   if (!mBrowsingContext) {
236     // This BBC was never valid, skip teardown.
237     return;
238   }
239 
240   // Ensure we unblock our document's 'load' event (in case the OOP-iframe has
241   // been removed before it finished loading, or its subprocess crashed):
242   UnblockOwnerDocsLoadEvent();
243 }
244 
UnblockOwnerDocsLoadEvent()245 void BrowserBridgeChild::UnblockOwnerDocsLoadEvent() {
246   if (!mHadInitialLoad) {
247     mHadInitialLoad = true;
248     if (auto* docShell =
249             nsDocShell::Cast(mBrowsingContext->GetParent()->GetDocShell())) {
250       docShell->OOPChildLoadDone(this);
251     }
252   }
253 }
254 
RecvIntrinsicSizeOrRatioChanged(const Maybe<IntrinsicSize> & aIntrinsicSize,const Maybe<AspectRatio> & aIntrinsicRatio)255 mozilla::ipc::IPCResult BrowserBridgeChild::RecvIntrinsicSizeOrRatioChanged(
256     const Maybe<IntrinsicSize>& aIntrinsicSize,
257     const Maybe<AspectRatio>& aIntrinsicRatio) {
258   if (RefPtr<Element> owner = mFrameLoader->GetOwnerContent()) {
259     if (nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(owner)) {
260       static_cast<nsObjectLoadingContent*>(olc.get())
261           ->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize,
262                                                    aIntrinsicRatio);
263     }
264   }
265   return IPC_OK();
266 }
267 
268 }  // namespace mozilla::dom
269