diff options
Diffstat (limited to 'dom/ipc')
25 files changed, 400 insertions, 121 deletions
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index bdd10fdcb2..3d1f399edb 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -2342,7 +2342,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview( /* aListener = */ nullptr, docShellToCloneInto, nsGlobalWindowOuter::IsPreview::Yes, nsGlobalWindowOuter::IsForWindowDotPrint::No, - std::move(aCallback), IgnoreErrors()); + std::move(aCallback), nullptr, IgnoreErrors()); #endif return IPC_OK(); } @@ -2359,8 +2359,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvExitPrintPreview() { return IPC_OK(); } -mozilla::ipc::IPCResult BrowserChild::RecvPrint( - const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData) { +mozilla::ipc::IPCResult BrowserChild::CommonPrint( + const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData, + RefPtr<BrowsingContext>* aCachedBrowsingContext) { #ifdef NS_PRINTING if (NS_WARN_IF(aBc.IsNullOrDiscarded())) { return IPC_OK(); @@ -2389,12 +2390,12 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrint( IgnoredErrorResult rv; RefPtr printJob = static_cast<RemotePrintJobChild*>( aPrintData.remotePrintJob().AsChild()); - outerWindow->Print(printSettings, printJob, - /* aListener = */ nullptr, - /* aWindowToCloneInto = */ nullptr, - nsGlobalWindowOuter::IsPreview::No, - nsGlobalWindowOuter::IsForWindowDotPrint::No, - /* aPrintPreviewCallback = */ nullptr, rv); + outerWindow->Print( + printSettings, printJob, + /* aListener = */ nullptr, + /* aWindowToCloneInto = */ nullptr, nsGlobalWindowOuter::IsPreview::No, + nsGlobalWindowOuter::IsForWindowDotPrint::No, + /* aPrintPreviewCallback = */ nullptr, aCachedBrowsingContext, rv); if (NS_WARN_IF(rv.Failed())) { return IPC_OK(); } @@ -2403,6 +2404,49 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrint( return IPC_OK(); } +mozilla::ipc::IPCResult BrowserChild::RecvPrint( + const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData, + bool aReturnStaticClone, PrintResolver&& aResolve) { +#ifdef NS_PRINTING + RefPtr<BrowsingContext> browsingContext; + auto result = CommonPrint(aBc, aPrintData, + aReturnStaticClone ? &browsingContext : nullptr); + aResolve(browsingContext); + return result; +#else + aResolve(nullptr); + return IPC_OK(); +#endif +} + +mozilla::ipc::IPCResult BrowserChild::RecvPrintClonedPage( + const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData, + const MaybeDiscardedBrowsingContext& aClonedBc) { +#ifdef NS_PRINTING + if (aClonedBc.IsNullOrDiscarded()) { + return IPC_OK(); + } + RefPtr<BrowsingContext> clonedBc = aClonedBc.get(); + return CommonPrint(aBc, aPrintData, &clonedBc); +#else + return IPC_OK(); +#endif +} + +mozilla::ipc::IPCResult BrowserChild::RecvDestroyPrintClone( + const MaybeDiscardedBrowsingContext& aCachedPage) { +#ifdef NS_PRINTING + if (aCachedPage) { + RefPtr<nsPIDOMWindowOuter> window = aCachedPage->GetDOMWindow(); + if (NS_WARN_IF(!window)) { + return IPC_OK(); + } + window->Close(); + } +#endif + return IPC_OK(); +} + mozilla::ipc::IPCResult BrowserChild::RecvUpdateNativeWindowHandle( const uintptr_t& aNewHandle) { #if defined(XP_WIN) && defined(ACCESSIBILITY) diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h index ddbf8f0b74..90cb712476 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -507,7 +507,15 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, mozilla::ipc::IPCResult RecvExitPrintPreview(); MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvPrint( - const MaybeDiscardedBrowsingContext&, const PrintData&); + const MaybeDiscardedBrowsingContext&, const PrintData&, bool, + PrintResolver&&); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvPrintClonedPage( + const MaybeDiscardedBrowsingContext&, const PrintData&, + const MaybeDiscardedBrowsingContext&); + + mozilla::ipc::IPCResult RecvDestroyPrintClone( + const MaybeDiscardedBrowsingContext&); mozilla::ipc::IPCResult RecvUpdateNativeWindowHandle( const uintptr_t& aNewHandle); @@ -712,6 +720,11 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, void InternalSetDocShellIsActive(bool aIsActive); + MOZ_CAN_RUN_SCRIPT + mozilla::ipc::IPCResult CommonPrint( + const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData, + RefPtr<BrowsingContext>* aCachedBrowsingContext); + bool CreateRemoteLayerManager( mozilla::layers::PCompositorBridgeChild* aCompositorChild); diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 5d13d2e814..23c677c09c 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -826,8 +826,6 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) { // out-of-process iframe. RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true); if (frameLoader) { - ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr); - if (mBrowsingContext->IsTop()) { // If this is a top-level BrowsingContext, tell the frameloader it's time // to go away. Otherwise, this is a subframe crash, and we can keep the diff --git a/dom/ipc/CoalescedTouchData.cpp b/dom/ipc/CoalescedTouchData.cpp index 3c3bc71a0c..551e6ae901 100644 --- a/dom/ipc/CoalescedTouchData.cpp +++ b/dom/ipc/CoalescedTouchData.cpp @@ -25,8 +25,7 @@ void CoalescedTouchData::CreateCoalescedTouchEvent( WidgetPointerEvent* event = touch->mCoalescedWidgetEvents->mEvents.AppendElement(WidgetPointerEvent( aEvent.IsTrusted(), ePointerMove, aEvent.mWidget)); - PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch, - i == 0); + PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch); event->mFlags.mBubbles = false; event->mFlags.mCancelable = false; } @@ -63,8 +62,7 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent, sameTouch->mCoalescedWidgetEvents->mEvents.AppendElement( WidgetPointerEvent(aEvent.IsTrusted(), ePointerMove, aEvent.mWidget)); - PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch, - i == 0); + PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch); event->mFlags.mBubbles = false; event->mFlags.mCancelable = false; } diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 7507d88fe0..2ebdd303d8 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2310,8 +2310,10 @@ mozilla::ipc::IPCResult ContentChild::RecvThemeChanged( mozilla::ipc::IPCResult ContentChild::RecvLoadProcessScript( const nsString& aURL) { auto* global = ContentProcessMessageManager::Get(); - global->LoadScript(aURL); - return IPC_OK(); + if (global && global->LoadScript(aURL)) { + return IPC_OK(); + } + return IPC_FAIL(this, "ContentProcessMessageManager::LoadScript failed"); } mozilla::ipc::IPCResult ContentChild::RecvAsyncMessage( @@ -3923,7 +3925,8 @@ mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow( mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus( const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, - uint64_t aActionId) { + uint64_t aActionId, bool aShouldClearAncestorFocus, + const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) { if (aContext.IsNullOrDiscarded()) { MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, ("ChildIPC: Trying to send a message to dead or detached context")); @@ -3932,7 +3935,12 @@ mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus( if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { RefPtr<BrowsingContext> bc = aContext.get(); - fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId); + RefPtr<BrowsingContext> ancestor = + aAncestorBrowsingContextToFocus.IsNullOrDiscarded() + ? nullptr + : aAncestorBrowsingContextToFocus.get(); + fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId, + aShouldClearAncestorFocus, ancestor); } return IPC_OK(); } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index b9ab77ef5b..12b6c3cabf 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -661,7 +661,8 @@ class ContentChild final : public PContentChild, uint64_t aActionId); MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvAdjustWindowFocus( const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, - uint64_t aActionId); + uint64_t aActionId, bool aShouldClearFocus, + const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus); MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvClearFocus( const MaybeDiscarded<BrowsingContext>& aContext); mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext( diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 2dbdb662ff..412b7e8796 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -644,6 +644,10 @@ static const char* sObserverTopics[] = { DEFAULT_TIMEZONE_CHANGED_OBSERVER_TOPIC, }; +void ContentParent_NotifyUpdatedDictionaries() { + ContentParent::NotifyUpdatedDictionaries(); +} + // PreallocateProcess is called by the PreallocatedProcessManager. // ContentParent then takes this process back within GetNewOrUsedBrowserProcess. /*static*/ already_AddRefed<ContentParent> @@ -1895,10 +1899,6 @@ void ContentParent::ShutDownMessageManager() { return; } - mMessageManager->ReceiveMessage(mMessageManager, nullptr, - CHILD_PROCESS_SHUTDOWN_MESSAGE, false, - nullptr, nullptr, IgnoreErrors()); - mMessageManager->SetOsPid(-1); mMessageManager->Disconnect(); mMessageManager = nullptr; @@ -3273,7 +3273,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) { // because content scripts mean that a moz-extension can live in any // process. Same thing for system principal Blob URLs. Content Blob // URL's are sent for content principals on-demand by - // AboutToLoadHttpFtpDocumentForChild and RemoteWorkerManager. + // AboutToLoadHttpDocumentForChild and RemoteWorkerManager. if (!BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal)) { return true; } @@ -6365,7 +6365,7 @@ void ContentParent::UpdateCookieStatus(nsIChannel* aChannel) { } } -nsresult ContentParent::AboutToLoadHttpFtpDocumentForChild( +nsresult ContentParent::AboutToLoadHttpDocumentForChild( nsIChannel* aChannel, bool* aShouldWaitForPermissionCookieUpdate) { MOZ_ASSERT(aChannel); @@ -7362,7 +7362,8 @@ mozilla::ipc::IPCResult ContentParent::RecvRaiseWindow( mozilla::ipc::IPCResult ContentParent::RecvAdjustWindowFocus( const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, - uint64_t aActionId) { + uint64_t aActionId, bool aShouldClearFocus, + const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) { if (aContext.IsNullOrDiscarded()) { MOZ_LOG( BrowsingContext::GetLog(), LogLevel::Debug, @@ -7389,7 +7390,9 @@ mozilla::ipc::IPCResult ContentParent::RecvAdjustWindowFocus( ContentParent* cp = cpm->GetContentProcessById( ContentParentId(canonicalParent->OwnerProcessId())); if (cp && !processes.Get(cp)) { - Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId); + Unused << cp->SendAdjustWindowFocus(context, aIsVisible, aActionId, + aShouldClearFocus, + aAncestorBrowsingContextToFocus); processes.InsertOrUpdate(cp, true); } context = canonicalParent; @@ -8092,6 +8095,8 @@ IPCResult ContentParent::RecvRawMessage( stack.emplace(); stack->BorrowFromClonedMessageData(*aStack); } + MMPrinter::Print("ContentParent::RecvRawMessage", aMeta.actorName(), + aMeta.messageName(), aData); ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 15139a93f1..31cfa6de88 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -50,8 +50,6 @@ #include "DriverCrashGuard.h" #include "nsIReferrerInfo.h" -#define CHILD_PROCESS_SHUTDOWN_MESSAGE u"child-process-shutdown"_ns - class nsConsoleService; class nsIContentProcessInfo; class nsICycleCollectorLogSink; @@ -551,12 +549,12 @@ class ContentParent final : public PContentParent, void SetMainThreadQoSPriority(nsIThread::QoSPriority aQoSPriority); // This function is called when we are about to load a document from an - // HTTP(S) or FTP channel for a content process. It is a useful place + // HTTP(S) channel for a content process. It is a useful place // to start to kick off work as early as possible in response to such // document loads. // aShouldWaitForPermissionCookieUpdate is set to true if main thread IPCs for // updating permissions/cookies are sent. - nsresult AboutToLoadHttpFtpDocumentForChild( + nsresult AboutToLoadHttpDocumentForChild( nsIChannel* aChannel, bool* aShouldWaitForPermissionCookieUpdate = nullptr); @@ -618,7 +616,8 @@ class ContentParent final : public PContentParent, uint64_t aActionId); mozilla::ipc::IPCResult RecvAdjustWindowFocus( const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, - uint64_t aActionId); + uint64_t aActionId, bool aShouldClearFocus, + const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus); mozilla::ipc::IPCResult RecvClearFocus( const MaybeDiscarded<BrowsingContext>& aContext); mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext( diff --git a/dom/ipc/ContentParent_NotifyUpdatedDictionaries.h b/dom/ipc/ContentParent_NotifyUpdatedDictionaries.h new file mode 100644 index 0000000000..0c78fb874d --- /dev/null +++ b/dom/ipc/ContentParent_NotifyUpdatedDictionaries.h @@ -0,0 +1,17 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_ContentParent_NotifyUpdatedDictionaries_h +#define mozilla_dom_ContentParent_NotifyUpdatedDictionaries_h + +// Avoid including ContentParent.h because it ends up including WebGLTypes.h, +// where we have our mozilla::malloc(ForbidNarrowing<size_t>) overrides, which +// cause issues with the way hunspell overrides malloc for itself. +namespace mozilla::dom { +void ContentParent_NotifyUpdatedDictionaries(); +} // namespace mozilla::dom + +#endif // mozilla_dom_ContentParent_NotifyUpdatedDictionaries_h diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index faee4e861c..1be3537e68 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -114,6 +114,7 @@ struct ScreenDetails { ScreenOrientation orientation; uint16_t orientationAngle; bool isPseudoDisplay; + bool isHDR; }; struct DimensionInfo diff --git a/dom/ipc/MMPrinter.cpp b/dom/ipc/MMPrinter.cpp index be2911341a..796b4fbeb3 100644 --- a/dom/ipc/MMPrinter.cpp +++ b/dom/ipc/MMPrinter.cpp @@ -26,8 +26,8 @@ LazyLogModule MMPrinter::sMMLog("MessageManager"); // the output of the logs into logs more friendly to reading. /* static */ -void MMPrinter::PrintImpl(char const* aLocation, const nsAString& aMsg, - ClonedMessageData const& aData) { +Maybe<uint64_t> MMPrinter::PrintHeader(char const* aLocation, + const nsAString& aMsg) { NS_ConvertUTF16toUTF8 charMsg(aMsg); /* @@ -43,15 +43,29 @@ void MMPrinter::PrintImpl(char const* aLocation, const nsAString& aMsg, char* mmSkipLog = PR_GetEnv("MOZ_LOG_MESSAGEMANAGER_SKIP"); if (mmSkipLog && strstr(mmSkipLog, charMsg.get())) { - return; + return Nothing(); } - uint64_t msg_id = RandomUint64OrDie(); + uint64_t aMsgId = RandomUint64OrDie(); MOZ_LOG(MMPrinter::sMMLog, LogLevel::Debug, - ("%" PRIu64 " %s Message: %s in process type: %s", msg_id, aLocation, + ("%" PRIu64 " %s Message: %s in process type: %s", aMsgId, aLocation, charMsg.get(), XRE_GetProcessTypeString())); + return Some(aMsgId); +} + +/* static */ +void MMPrinter::PrintNoData(uint64_t aMsgId) { + if (!MOZ_LOG_TEST(sMMLog, LogLevel::Verbose)) { + return; + } + MOZ_LOG(MMPrinter::sMMLog, LogLevel::Verbose, + ("%" PRIu64 " (No Data)", aMsgId)); +} + +/* static */ +void MMPrinter::PrintData(uint64_t aMsgId, ClonedMessageData const& aData) { if (!MOZ_LOG_TEST(sMMLog, LogLevel::Verbose)) { return; } @@ -75,8 +89,7 @@ void MMPrinter::PrintImpl(char const* aLocation, const nsAString& aMsg, if (rv.Failed()) { // In testing, the only reason this would fail was if there was no data in // the message; so it seems like this is safe-ish. - MOZ_LOG(MMPrinter::sMMLog, LogLevel::Verbose, - ("%" PRIu64 " (No Data)", msg_id)); + MMPrinter::PrintNoData(aMsgId); rv.SuppressException(); return; } @@ -86,7 +99,7 @@ void MMPrinter::PrintImpl(char const* aLocation, const nsAString& aMsg, if (!srcString.init(cx, unevalObj)) return; MOZ_LOG(MMPrinter::sMMLog, LogLevel::Verbose, - ("%" PRIu64 " %s", msg_id, NS_ConvertUTF16toUTF8(srcString).get())); + ("%" PRIu64 " %s", aMsgId, NS_ConvertUTF16toUTF8(srcString).get())); } } // namespace mozilla::dom diff --git a/dom/ipc/MMPrinter.h b/dom/ipc/MMPrinter.h index 7d89f9ee8f..1d00bfc2e6 100644 --- a/dom/ipc/MMPrinter.h +++ b/dom/ipc/MMPrinter.h @@ -7,6 +7,7 @@ #ifndef MMPrinter_h #define MMPrinter_h +#include "mozilla/Maybe.h" #include "mozilla/dom/DOMTypes.h" #include "nsString.h" @@ -17,14 +18,40 @@ class MMPrinter { static void Print(char const* aLocation, const nsAString& aMsg, ClonedMessageData const& aData) { if (MOZ_UNLIKELY(MOZ_LOG_TEST(MMPrinter::sMMLog, LogLevel::Debug))) { - MMPrinter::PrintImpl(aLocation, aMsg, aData); + Maybe<uint64_t> msgId = MMPrinter::PrintHeader(aLocation, aMsg); + if (!msgId.isSome()) { + return; + } + MMPrinter::PrintData(*msgId, aData); + } + } + + static void Print(char const* aLocation, const nsACString& aActorName, + const nsAString& aMessageName, + const Maybe<ClonedMessageData>& aData) { + if (MOZ_UNLIKELY(MOZ_LOG_TEST(MMPrinter::sMMLog, LogLevel::Debug))) { + Maybe<uint64_t> msgId = MMPrinter::PrintHeader( + aLocation, + NS_ConvertUTF8toUTF16(aActorName + " - "_ns) + aMessageName); + + if (!msgId.isSome()) { + return; + } + + if (aData.isSome()) { + MMPrinter::PrintData(*msgId, *aData); + } else { + MMPrinter::PrintNoData(*msgId); + } } } private: static LazyLogModule sMMLog; - static void PrintImpl(char const* aLocation, const nsAString& aMsg, - ClonedMessageData const& aData); + static Maybe<uint64_t> PrintHeader(char const* aLocation, + const nsAString& aMsg); + static void PrintNoData(uint64_t aMsgId); + static void PrintData(uint64_t aMsgId, ClonedMessageData const& aData); }; } // namespace mozilla::dom diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index caef472ec2..372a81b139 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -87,7 +87,7 @@ using nsCursor from "nsIWidget.h"; using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h"; using struct mozilla::DimensionRequest from "mozilla/widget/WidgetMessageUtils.h"; using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h"; -using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h"; +[MoveOnly=data] using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h"; using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h"; using mozilla::EventMessage from "mozilla/EventForwards.h"; using nsEventStatus from "mozilla/EventForwards.h"; @@ -960,8 +960,33 @@ child: * * @param aBrowsingContext the browsing context to print. * @param aPrintData the serialized settings to print with + * @param aReturnStaticClone If the document in aBrowsingContext is not a static clone, whether + * to return the static document clone created. + * Note that if you call this with true but do not later call PrintClonedPage(), + * you must call DestroyPrintCache() to avoid leaks. */ - async Print(MaybeDiscardedBrowsingContext aBC, PrintData aPrintData); + async Print(MaybeDiscardedBrowsingContext aBC, PrintData aPrintData, bool aReturnStaticClone) returns(MaybeDiscardedBrowsingContext staticCloneBrowsingContext); + + /** + * Tell the child to print the passed in static clone browsing context with the given settings. + * + * @param aBrowsingContext the browsing context to print. + * @param aPrintData the serialized settings to print with + * @param aStaticCloneBrowsingContext The static clone of aBrowsingContext that + * was created by an earlier call to Print(). This is the page that will actually be + * printed. + */ + async PrintClonedPage(MaybeDiscardedBrowsingContext aBC, PrintData aPrintData, MaybeDiscardedBrowsingContext aStaticCloneBrowsingContext); + + /** + * Destroy the static document clone for printing, if present. See Print() for details. + * For callers' simplicity, it is safe to call this method even if aStaticCloneBrowsingContext + * is null or has already been discarded. + * + * @param aStaticCloneBrowsingContext The static clone that was created by + * an earlier call to Print(). + */ + async DestroyPrintClone(MaybeDiscardedBrowsingContext aStaticCloneBrowsingContext); /** * Update the child with the tab's current top-level native window handle. diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 3789c046c8..67c4c298e4 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -104,7 +104,7 @@ using mozilla::ImagePoint from "Units.h"; using mozilla::ImageIntSize from "Units.h"; using mozilla::widget::ThemeChangeKind from "mozilla/widget/WidgetMessageUtils.h"; using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h"; -using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h"; +[MoveOnly=data] using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h"; using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h"; using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h"; using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h"; @@ -1874,8 +1874,18 @@ both: async DiscardBrowsingContext(MaybeDiscardedBrowsingContext aContext, bool aDoDiscard) returns (uint64_t unused); + /** + * aContext is the one that's taking the affect. Either the one that + * receives the focus, or the one that loses the focus. + * + * aAncestorBrowsingContextToFocus can only be non-null when + * aShouldClearAncestorFocus is true. This is the browsing context + * that receives the focus when aContext loses the focus. + */ async AdjustWindowFocus(MaybeDiscardedBrowsingContext aContext, - bool aIsVisible, uint64_t aActionId); + bool aIsVisible, uint64_t aActionId, + bool aShouldClearAncestorFocus, + MaybeDiscardedBrowsingContext aAncestorBrowsingContextToFocus); async WindowClose(MaybeDiscardedBrowsingContext aContext, bool aTrustedCaller); async WindowFocus(MaybeDiscardedBrowsingContext aContext, diff --git a/dom/ipc/ProcessIsolation.cpp b/dom/ipc/ProcessIsolation.cpp index f0c6dd8863..ddfbeb3d28 100644 --- a/dom/ipc/ProcessIsolation.cpp +++ b/dom/ipc/ProcessIsolation.cpp @@ -343,6 +343,7 @@ static IsolationBehavior IsolationBehaviorForURI(nsIURI* aURI, bool aIsSubframe, browser_tabs_remote_separatePrivilegedMozillaWebContentProcess()) { nsAutoCString host; if (NS_SUCCEEDED(aURI->GetAsciiHost(host))) { + // This code is duplicated in E10SUtils.sys.mjs, please update both for (const auto& separatedDomain : sSeparatedMozillaDomains) { // If the domain exactly matches our host, or our host ends with "." + // separatedDomain, we consider it matching. @@ -407,8 +408,8 @@ static already_AddRefed<BasePrincipal> GetAboutReaderURLPrincipal( // Extract the "url" parameter from the `about:reader`'s query parameters, // and recover a content principal from it. - nsAutoString readerSpec; - if (URLParams::Extract(query, u"url"_ns, readerSpec)) { + nsAutoCString readerSpec; + if (URLParams::Extract(query, "url"_ns, readerSpec)) { nsCOMPtr<nsIURI> readerUri; if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(readerUri), readerSpec))) { return BasePrincipal::CreateContentPrincipal(readerUri, aAttrs); diff --git a/dom/ipc/StructuredCloneData.h b/dom/ipc/StructuredCloneData.h index 0566a3b07f..6beba4f745 100644 --- a/dom/ipc/StructuredCloneData.h +++ b/dom/ipc/StructuredCloneData.h @@ -93,20 +93,14 @@ class SharedJSAllocatedData final { * to send a structured clone that may include blobs or transferables such as * message ports. * - To send the data, instantiate a StructuredCloneData instance and Write() - * into it like a normal structure clone. When you are ready to send the - * ClonedMessageData-bearing IPC message, use the appropriate - * BuildClonedMessageDataFor{Parent,Child,BackgroundParent,BackgroundChild} + * into it like a normal structured clone. When you are ready to send the + * ClonedMessageData-bearing IPC message, call the BuildClonedMessageData * method to populate the ClonedMessageData and then send it before your * StructuredCloneData instance is destroyed. (Buffer borrowing is used * under-the-hood to avoid duplicating the serialized data, requiring this.) - * - To receive the data, instantiate a StructuredCloneData and use the - * appropriate {Borrow,Copy,Steal}FromClonedMessageDataFor{Parent,Child, - * BackgroundParent,BackgroundChild} method. See the memory management - * section for more info. - * - * Variations: - * - If transferables are not allowed (ex: BroadcastChannel), then use the - * StructuredCloneDataNoTransfers subclass instead of StructuredCloneData. + * - To receive the data, instantiate a StructuredCloneData and then call + * the BorrowFromClonedMessageData method. See the memory management + * section for more information. * * ## Memory Management ## * @@ -135,11 +129,11 @@ class SharedJSAllocatedData final { * * 1: Specifically, in the Write() case an owning SharedJSAllocatedData is * created efficiently (by stealing from StructuredCloneHolder). The - * BuildClonedMessageDataFor* method can be called at any time and it will + * BuildClonedMessageData method can be called at any time and it will * borrow the underlying memory. While it would be even better if * SerializedStructuredCloneBuffer could hold a SharedJSAllocatedData ref, - * there's no reason you can't wait to BuildClonedMessageDataFor* until you - * need to make the IPC Send* call. + * there's no reason you can't wait to call the BuildClonedMessageData + * method until you need to make the IPC Send* call. */ class StructuredCloneData : public StructuredCloneHolder { public: diff --git a/dom/ipc/WindowGlobalChild.cpp b/dom/ipc/WindowGlobalChild.cpp index ec2811f972..4072828911 100644 --- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -35,7 +35,7 @@ #include "nsQueryObject.h" #include "nsSerializationHelper.h" #include "nsFrameLoader.h" -#include "nsIScriptSecurityManager.h" +#include "nsScriptSecurityManager.h" #include "mozilla/dom/JSWindowActorBinding.h" #include "mozilla/dom/JSWindowActorChild.h" @@ -588,30 +588,19 @@ void WindowGlobalChild::SetDocumentURI(nsIURI* aDocumentURI) { embedderInnerWindowID, BrowsingContext()->UsePrivateBrowsing()); if (StaticPrefs::dom_security_setdocumenturi()) { - auto isLoadableViaInternet = [](nsIURI* uri) { - return (uri && (net::SchemeIsHTTP(uri) || net::SchemeIsHTTPS(uri))); - }; - if (isLoadableViaInternet(aDocumentURI)) { - nsCOMPtr<nsIURI> principalURI = mDocumentPrincipal->GetURI(); - if (mDocumentPrincipal->GetIsNullPrincipal()) { - nsCOMPtr<nsIPrincipal> precursor = - mDocumentPrincipal->GetPrecursorPrincipal(); - if (precursor) { - principalURI = precursor->GetURI(); - } - } - - if (isLoadableViaInternet(principalURI)) { - nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); - - if (!NS_SUCCEEDED(ssm->CheckSameOriginURI(principalURI, aDocumentURI, - false, false))) { - MOZ_DIAGNOSTIC_ASSERT(false, - "Setting DocumentURI with a different origin " - "than principal URI"); - } + nsCOMPtr<nsIURI> principalURI = mDocumentPrincipal->GetURI(); + if (mDocumentPrincipal->GetIsNullPrincipal()) { + nsCOMPtr<nsIPrincipal> precursor = + mDocumentPrincipal->GetPrecursorPrincipal(); + if (precursor) { + principalURI = precursor->GetURI(); } } + + MOZ_DIAGNOSTIC_ASSERT(!nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin( + principalURI, aDocumentURI), + "Setting DocumentURI with a different origin " + "than principal URI"); } mDocumentURI = aDocumentURI; diff --git a/dom/ipc/WindowGlobalParent.cpp b/dom/ipc/WindowGlobalParent.cpp index 13fbe2940c..f60790a155 100644 --- a/dom/ipc/WindowGlobalParent.cpp +++ b/dom/ipc/WindowGlobalParent.cpp @@ -39,6 +39,7 @@ #include "mozilla/Telemetry.h" #include "mozilla/Variant.h" #include "mozilla/ipc/ProtocolUtils.h" +#include "MMPrinter.h" #include "nsContentUtils.h" #include "nsDocShell.h" #include "nsDocShellLoadState.h" @@ -230,8 +231,8 @@ void WindowGlobalParent::OriginCounter::UpdateSiteOriginsFrom( } void WindowGlobalParent::OriginCounter::Accumulate() { - mozilla::glean::geckoview::per_document_site_origins.AccumulateSamples( - {mMaxOrigins}); + mozilla::glean::geckoview::per_document_site_origins.AccumulateSingleSample( + mMaxOrigins); mMaxOrigins = 0; mOriginMap.Clear(); @@ -398,26 +399,20 @@ IPCResult WindowGlobalParent::RecvUpdateDocumentURI(NotNull<nsIURI*> aURI) { return IPC_FAIL(this, "Setting DocumentURI with unknown protocol."); } - auto isLoadableViaInternet = [](nsIURI* uri) { - return (uri && (net::SchemeIsHTTP(uri) || net::SchemeIsHTTPS(uri))); - }; - - if (isLoadableViaInternet(aURI)) { - nsCOMPtr<nsIURI> principalURI = mDocumentPrincipal->GetURI(); - if (mDocumentPrincipal->GetIsNullPrincipal()) { - nsCOMPtr<nsIPrincipal> precursor = - mDocumentPrincipal->GetPrecursorPrincipal(); - if (precursor) { - principalURI = precursor->GetURI(); - } + nsCOMPtr<nsIURI> principalURI = mDocumentPrincipal->GetURI(); + if (mDocumentPrincipal->GetIsNullPrincipal()) { + nsCOMPtr<nsIPrincipal> precursor = + mDocumentPrincipal->GetPrecursorPrincipal(); + if (precursor) { + principalURI = precursor->GetURI(); } + } - if (isLoadableViaInternet(principalURI) && - !nsScriptSecurityManager::SecurityCompareURIs(principalURI, aURI)) { - return IPC_FAIL(this, - "Setting DocumentURI with a different Origin than " - "principal URI"); - } + if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI, + aURI)) { + return IPC_FAIL(this, + "Setting DocumentURI with a different Origin than " + "principal URI"); } } @@ -570,6 +565,8 @@ IPCResult WindowGlobalParent::RecvRawMessage( stack.emplace(); stack->BorrowFromClonedMessageData(*aStack); } + MMPrinter::Print("WindowGlobalParent::RecvRawMessage", aMeta.actorName(), + aMeta.messageName(), aData); ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } diff --git a/dom/ipc/jsactor/JSActor.cpp b/dom/ipc/jsactor/JSActor.cpp index 03926fee04..2c706ca515 100644 --- a/dom/ipc/jsactor/JSActor.cpp +++ b/dom/ipc/jsactor/JSActor.cpp @@ -441,14 +441,8 @@ void JSActor::QueryHandler::ResolvedCallback(JSContext* aCx, return; } - Maybe<ipc::StructuredCloneData> data{std::in_place}; - data->InitScope(JS::StructuredCloneScope::DifferentProcess); - - IgnoredErrorResult error; - data->Write(aCx, aValue, error); - if (NS_WARN_IF(error.Failed())) { - JS_ClearPendingException(aCx); - + Maybe<ipc::StructuredCloneData> data = TryClone(aCx, aValue); + if (!data) { nsAutoCString msg; msg.Append(mActor->Name()); msg.Append(':'); diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 3f10b9fbab..35b6039d89 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -52,6 +52,7 @@ EXPORTS.mozilla.dom += [ "CoalescedWheelData.h", "ContentChild.h", "ContentParent.h", + "ContentParent_NotifyUpdatedDictionaries.h", "ContentProcess.h", "ContentProcessManager.h", "CSPMessageUtils.h", diff --git a/dom/ipc/nsIHangReport.idl b/dom/ipc/nsIHangReport.idl index ff01d7f51a..d99137d942 100644 --- a/dom/ipc/nsIHangReport.idl +++ b/dom/ipc/nsIHangReport.idl @@ -47,5 +47,5 @@ interface nsIHangReport : nsISupports // Inquire whether the report is for a content process loaded by the given // frameloader, or any descendents in its BrowsingContext tree. - bool isReportForBrowserOrChildren(in FrameLoader aFrameLoader); + boolean isReportForBrowserOrChildren(in FrameLoader aFrameLoader); }; diff --git a/dom/ipc/nsILoginDetectionService.idl b/dom/ipc/nsILoginDetectionService.idl index a0b1ae90a7..123318d5db 100644 --- a/dom/ipc/nsILoginDetectionService.idl +++ b/dom/ipc/nsILoginDetectionService.idl @@ -18,5 +18,5 @@ interface nsILoginDetectionService : nsISupports * Returns true if we have loaded logins from the password manager. * This is now used by testcase only. */ - bool isLoginsLoaded(); + boolean isLoginsLoaded(); }; diff --git a/dom/ipc/tests/JSWindowActor/browser_event_listener.js b/dom/ipc/tests/JSWindowActor/browser_event_listener.js index 725c2c3753..21cb0c5ee9 100644 --- a/dom/ipc/tests/JSWindowActor/browser_event_listener.js +++ b/dom/ipc/tests/JSWindowActor/browser_event_listener.js @@ -144,7 +144,7 @@ declTest("test in-process content events are not processed twice", { "content", "Should be a content <browser>" ); - is(browser.getAttribute("remotetype"), "", "Should not be remote"); + is(browser.getAttribute("remotetype"), null, "Should not be remote"); await testEventProcessedOnce(browser); }, }); @@ -160,8 +160,12 @@ declTest("test in-process chrome events are processed correctly", { "chrome://mochitests/content/browser/dom/ipc/tests/JSWindowActor/file_dummyChromePage.html" ); let chromeBrowser = dialog._frame; - is(chromeBrowser.getAttribute("type"), "", "Should be a chrome <browser>"); - is(chromeBrowser.getAttribute("remotetype"), "", "Should not be remote"); + is( + chromeBrowser.getAttribute("type"), + null, + "Should be a chrome <browser>" + ); + is(chromeBrowser.getAttribute("remotetype"), null, "Should not be remote"); await testEventProcessedOnce(chromeBrowser, "dummyChromePage.html"); diff --git a/dom/ipc/tests/browser.toml b/dom/ipc/tests/browser.toml index cd2129e9c1..550558ca46 100644 --- a/dom/ipc/tests/browser.toml +++ b/dom/ipc/tests/browser.toml @@ -64,6 +64,8 @@ skip-if = [ ["browser_hide_tooltip.js"] +["browser_isactiveintab.js"] + ["browser_layers_unloaded_while_interruptingJS.js"] ["browser_memory_distribution_telemetry.js"] diff --git a/dom/ipc/tests/browser_isactiveintab.js b/dom/ipc/tests/browser_isactiveintab.js new file mode 100644 index 0000000000..bd189f1826 --- /dev/null +++ b/dom/ipc/tests/browser_isactiveintab.js @@ -0,0 +1,138 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function documentURL(origin, html) { + let params = new URLSearchParams(); + params.append("html", html.trim()); + return `${origin}/document-builder.sjs?${params.toString()}`; +} + +add_task(async function checkIsActiveInTab() { + // This test creates a few tricky situations with navigation and iframes and + // examines the results of various ways you might think to check if a page + // is currently visible, and confirms that isActiveInTab works, even if the + // others don't. + + // Make a top level page with two nested iframes. + const IFRAME2_URL = documentURL("https://example.com", `<h1>iframe2</h1>`); + const IFRAME1_URL = documentURL( + "https://example.com", + `<iframe src=${JSON.stringify(IFRAME2_URL)}></iframe><h1>iframe1</h1>` + ); + const TEST_URL = documentURL( + "https://example.com", + `<iframe src=${JSON.stringify(IFRAME1_URL)}></iframe><h1>top window</h1>` + ); + + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + let topBC1 = browser.browsingContext; + let topWindowGlobal1 = topBC1.currentWindowGlobal; + + is( + browser.browsingContext.children.length, + 1, + "only one child for top window" + ); + let iframe1 = browser.browsingContext.children[0]; + let iframeWindowGlobal1a = iframe1.currentWindowGlobal; + + is(iframe1.children.length, 1, "only one child for iframe"); + let iframe2 = iframe1.children[0]; + let iframeWindowGlobal2 = iframe2.currentWindowGlobal; + + ok(topWindowGlobal1.isActiveInTab, "top window global is active in tab"); + ok(iframeWindowGlobal1a.isActiveInTab, "topmost iframe is active in tab"); + ok(iframeWindowGlobal2.isActiveInTab, "innermost iframe is active in tab"); + + // Do a same-origin navigation on the topmost iframe. + let iframe1bURI = + "https://example.com/browser/dom/ipc/tests/file_dummy.html"; + let loadedIframe = BrowserTestUtils.browserLoaded( + browser, + true, + iframe1bURI + ); + await SpecialPowers.spawn( + iframe1, + [iframe1bURI], + async function (_iframe1bURI) { + content.location = _iframe1bURI; + } + ); + await loadedIframe; + + ok( + topWindowGlobal1.isActiveInTab, + "top window global is still active in tab" + ); + + let iframeWindowGlobal1b = iframe1.currentWindowGlobal; + isnot( + iframeWindowGlobal1a, + iframeWindowGlobal1b, + "navigating changed the iframe's current window" + ); + + // This tests the !CanSend() case but unfortunately not the + // `bc->GetCurrentWindowGlobal() != this` case. Apparently the latter will + // only hold temporarily, so that is likely hard to test. + ok( + !iframeWindowGlobal1a.isActiveInTab, + "topmost iframe is not active in tab" + ); + + ok(iframeWindowGlobal1b.isActiveInTab, "new iframe is active in tab"); + + is( + iframe2.currentWindowGlobal, + iframeWindowGlobal2, + "innermost iframe current window global has not changed" + ); + + ok( + iframeWindowGlobal2.isCurrentGlobal, + "innermost iframe is still the current global for its BC" + ); + + // With a same-origin navigation, this hits the !bc->AncestorsAreCurrent() + // case. (With a cross-origin navigation, this hits the !CanSend() case.) + ok( + !iframeWindowGlobal2.isActiveInTab, + "innermost iframe is not active in tab" + ); + + // Load a new page into the tab to test the behavior when a page is in + // the BFCache. + let newTopURI = "https://example.com/browser/dom/ipc/tests/file_dummy.html"; + let loadedTop2 = BrowserTestUtils.browserLoaded(browser, false, newTopURI); + await BrowserTestUtils.startLoadingURIString(browser, newTopURI); + await loadedTop2; + + isnot(browser.browsingContext, topBC1, "Navigated to a new BC"); + + is( + topBC1.currentWindowGlobal, + topWindowGlobal1, + "old top window is still the current window global for the old BC" + ); + ok(topWindowGlobal1.isInBFCache, "old top window's BC is in the BFCache"); + ok(!topWindowGlobal1.isCurrentGlobal, "old top frame isn't current"); + ok(!topWindowGlobal1.isActiveInTab, "old top frame not active in tab"); + + is( + iframe1.currentWindowGlobal, + iframeWindowGlobal1b, + "old iframe is still the current window global for the BC" + ); + ok(!iframeWindowGlobal1b.isCurrentGlobal, "newer top iframe isn't current"); + ok( + iframeWindowGlobal1b.isInBFCache, + "old top window's BC is in the BFCache" + ); + ok(iframe1.ancestorsAreCurrent, "ancestors of iframe are current"); + ok( + !iframeWindowGlobal1b.isActiveInTab, + "newer top iframe is active in not active in tab after top level navigation" + ); + }); +}); |