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