/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef ACCESSIBILITY # ifdef XP_WIN # include "mozilla/a11y/ProxyAccessible.h" # include "mozilla/a11y/ProxyWrappers.h" # endif # include "mozilla/a11y/DocAccessible.h" # include "mozilla/a11y/DocManager.h" # include "mozilla/a11y/OuterDocAccessible.h" #endif #include "mozilla/dom/BrowserBridgeChild.h" #include "mozilla/dom/BrowserBridgeHost.h" #include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/MozFrameLoaderOwnerBinding.h" #include "mozilla/PresShell.h" #include "nsFocusManager.h" #include "nsFrameLoader.h" #include "nsFrameLoaderOwner.h" #include "nsObjectLoadingContent.h" #include "nsQueryObject.h" #include "nsSubDocumentFrame.h" #include "nsView.h" using namespace mozilla::ipc; namespace mozilla::dom { BrowserBridgeChild::BrowserBridgeChild(BrowsingContext* aBrowsingContext, TabId aId, const LayersId& aLayersId) : mId{aId}, mLayersId{aLayersId}, mBrowsingContext(aBrowsingContext) {} BrowserBridgeChild::~BrowserBridgeChild() { #if defined(ACCESSIBILITY) && defined(XP_WIN) if (mEmbeddedDocAccessible) { mEmbeddedDocAccessible->Shutdown(); } #endif } already_AddRefed BrowserBridgeChild::FinishInit( nsFrameLoader* aFrameLoader) { MOZ_DIAGNOSTIC_ASSERT(!mFrameLoader); mFrameLoader = aFrameLoader; RefPtr owner = mFrameLoader->GetOwnerContent(); nsCOMPtr docShell = do_GetInterface(owner->GetOwnerGlobal()); MOZ_DIAGNOSTIC_ASSERT(docShell); nsDocShell::Cast(docShell)->OOPChildLoadStarted(this); #if defined(ACCESSIBILITY) if (a11y::DocAccessible* docAcc = a11y::GetExistingDocAccessible(owner->OwnerDoc())) { if (a11y::Accessible* ownerAcc = docAcc->GetAccessible(owner)) { if (a11y::OuterDocAccessible* outerAcc = ownerAcc->AsOuterDoc()) { outerAcc->SendEmbedderAccessible(this); } } } #endif // defined(ACCESSIBILITY) return MakeAndAddRef(this); } nsILoadContext* BrowserBridgeChild::GetLoadContext() { return mBrowsingContext; } void BrowserBridgeChild::NavigateByKey(bool aForward, bool aForDocumentNavigation) { Unused << SendNavigateByKey(aForward, aForDocumentNavigation); } void BrowserBridgeChild::Activate(uint64_t aActionId) { Unused << SendActivate(aActionId); } void BrowserBridgeChild::Deactivate(bool aWindowLowering, uint64_t aActionId) { Unused << SendDeactivate(aWindowLowering, aActionId); } void BrowserBridgeChild::SetIsUnderHiddenEmbedderElement( bool aIsUnderHiddenEmbedderElement) { Unused << SendSetIsUnderHiddenEmbedderElement(aIsUnderHiddenEmbedderElement); } /*static*/ BrowserBridgeChild* BrowserBridgeChild::GetFrom(nsFrameLoader* aFrameLoader) { if (!aFrameLoader) { return nullptr; } return aFrameLoader->GetBrowserBridgeChild(); } /*static*/ BrowserBridgeChild* BrowserBridgeChild::GetFrom(nsIContent* aContent) { RefPtr loaderOwner = do_QueryObject(aContent); if (!loaderOwner) { return nullptr; } RefPtr frameLoader = loaderOwner->GetFrameLoader(); return GetFrom(frameLoader); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvRequestFocus( const bool& aCanRaise, const CallerType aCallerType) { // Adapted from BrowserParent RefPtr owner = mFrameLoader->GetOwnerContent(); if (!owner) { return IPC_OK(); } nsContentUtils::RequestFrameFocus(*owner, aCanRaise, aCallerType); return IPC_OK(); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvMoveFocus( const bool& aForward, const bool& aForDocumentNavigation) { // Adapted from BrowserParent RefPtr fm = nsFocusManager::GetFocusManager(); if (!fm) { return IPC_OK(); } RefPtr owner = mFrameLoader->GetOwnerContent(); if (!owner) { return IPC_OK(); } RefPtr dummy; uint32_t type = aForward ? (aForDocumentNavigation ? static_cast(nsIFocusManager::MOVEFOCUS_FORWARDDOC) : static_cast(nsIFocusManager::MOVEFOCUS_FORWARD)) : (aForDocumentNavigation ? static_cast(nsIFocusManager::MOVEFOCUS_BACKWARDDOC) : static_cast(nsIFocusManager::MOVEFOCUS_BACKWARD)); fm->MoveFocus(nullptr, owner, type, nsIFocusManager::FLAG_BYKEY, getter_AddRefs(dummy)); return IPC_OK(); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvSetEmbeddedDocAccessibleCOMProxy( const a11y::IDispatchHolder& aCOMProxy) { #if defined(ACCESSIBILITY) && defined(XP_WIN) MOZ_ASSERT(!aCOMProxy.IsNull()); if (mEmbeddedDocAccessible) { mEmbeddedDocAccessible->Shutdown(); } RefPtr comProxy(aCOMProxy.Get()); mEmbeddedDocAccessible = new a11y::RemoteIframeDocProxyAccessibleWrap(comProxy); #endif return IPC_OK(); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvMaybeFireEmbedderLoadEvents( EmbedderElementEventType aFireEventAtEmbeddingElement) { RefPtr owner = mFrameLoader->GetOwnerContent(); if (!owner) { return IPC_OK(); } if (aFireEventAtEmbeddingElement == EmbedderElementEventType::LoadEvent) { nsEventStatus status = nsEventStatus_eIgnore; WidgetEvent event(/* aIsTrusted = */ true, eLoad); event.mFlags.mBubbles = false; event.mFlags.mCancelable = false; EventDispatcher::Dispatch(owner, nullptr, &event, nullptr, &status); } else if (aFireEventAtEmbeddingElement == EmbedderElementEventType::ErrorEvent) { mFrameLoader->FireErrorEvent(); } UnblockOwnerDocsLoadEvent(); return IPC_OK(); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvScrollRectIntoView( const nsRect& aRect, const ScrollAxis& aVertical, const ScrollAxis& aHorizontal, const ScrollFlags& aScrollFlags, const int32_t& aAppUnitsPerDevPixel) { RefPtr owner = mFrameLoader->GetOwnerContent(); if (!owner) { return IPC_OK(); } nsIFrame* frame = owner->GetPrimaryFrame(); if (!frame) { return IPC_OK(); } nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(frame); if (!subdocumentFrame) { return IPC_OK(); } nsPoint extraOffset = subdocumentFrame->GetExtraOffset(); int32_t parentAPD = frame->PresContext()->AppUnitsPerDevPixel(); nsRect rect = aRect.ScaleToOtherAppUnitsRoundOut(aAppUnitsPerDevPixel, parentAPD); rect += extraOffset; RefPtr presShell = frame->PresShell(); presShell->ScrollFrameRectIntoView(frame, rect, aVertical, aHorizontal, aScrollFlags); return IPC_OK(); } mozilla::ipc::IPCResult BrowserBridgeChild::RecvSubFrameCrashed() { if (RefPtr frameLoaderOwner = do_QueryObject(mFrameLoader->GetOwnerContent())) { frameLoaderOwner->SubframeCrashed(); } return IPC_OK(); } void BrowserBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { if (!mBrowsingContext) { // This BBC was never valid, skip teardown. return; } // Ensure we unblock our document's 'load' event (in case the OOP-iframe has // been removed before it finished loading, or its subprocess crashed): UnblockOwnerDocsLoadEvent(); } void BrowserBridgeChild::UnblockOwnerDocsLoadEvent() { if (!mHadInitialLoad) { mHadInitialLoad = true; if (auto* docShell = nsDocShell::Cast(mBrowsingContext->GetParent()->GetDocShell())) { docShell->OOPChildLoadDone(this); } } } mozilla::ipc::IPCResult BrowserBridgeChild::RecvIntrinsicSizeOrRatioChanged( const Maybe& aIntrinsicSize, const Maybe& aIntrinsicRatio) { if (RefPtr owner = mFrameLoader->GetOwnerContent()) { if (nsCOMPtr olc = do_QueryInterface(owner)) { static_cast(olc.get()) ->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize, aIntrinsicRatio); } } return IPC_OK(); } } // namespace mozilla::dom