Bug 1695806 - Defer sending a snapshot reqeust for remote process iframe until cloning the iframe document finished. r=mattwoodrow,nika

Differential Revision: https://phabricator.services.mozilla.com/D119950
This commit is contained in:
Hiroyuki Ikezoe 2021-07-27 00:47:44 +00:00
parent 139b694208
commit a5ecf77776
6 changed files with 105 additions and 35 deletions

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
#include "mozilla/dom/PWindowGlobalParent.h"
#include "mozilla/dom/WindowGlobalParent.h"
@ -2511,6 +2512,45 @@ void CanonicalBrowsingContext::SetTouchEventsOverride(
SetTouchEventsOverrideInternal(aOverride, aRv);
}
void CanonicalBrowsingContext::CloneDocumentTreeInto(
CanonicalBrowsingContext* aSource, const nsACString& aRemoteType,
embedding::PrintData&& aPrintData) {
RemotenessChangeOptions options;
options.mRemoteType = aRemoteType;
mClonePromise =
ChangeRemoteness(options, /* aPendingSwitchId = */ 0)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[source = MaybeDiscardedBrowsingContext{aSource},
data = std::move(aPrintData)](
BrowserParent* aBp) -> RefPtr<GenericNonExclusivePromise> {
return aBp->SendCloneDocumentTreeIntoSelf(source, data)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[](BrowserParent::CloneDocumentTreeIntoSelfPromise::
ResolveOrRejectValue&& aValue) {
if (aValue.IsResolve() && aValue.ResolveValue()) {
return GenericNonExclusivePromise::CreateAndResolve(
true, __func__);
}
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
});
},
[](nsresult aRv) -> RefPtr<GenericNonExclusivePromise> {
NS_WARNING(
nsPrintfCString("Remote clone failed: %x\n", unsigned(aRv))
.get());
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
});
mClonePromise->Then(
GetMainThreadSerialEventTarget(), __func__,
[self = RefPtr{this}]() { self->mClonePromise = nullptr; });
}
NS_IMPL_CYCLE_COLLECTION_CLASS(CanonicalBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CanonicalBrowsingContext,

View File

@ -36,6 +36,10 @@ class nsITimer;
namespace mozilla {
enum class CallState;
namespace embedding {
class PrintData;
}
namespace net {
class DocumentLoadListener;
}
@ -331,6 +335,16 @@ class CanonicalBrowsingContext final : public BrowsingContext {
void ClearPermanentKey() { mPermanentKey.setNull(); }
void MaybeSetPermanentKey(Element* aEmbedder);
void CloneDocumentTreeInto(CanonicalBrowsingContext* aSource,
const nsACString& aRemoteType,
embedding::PrintData&& aPrintData);
// Returns a Promise which resolves when cloning documents for printing
// finished if this browsing context is cloning document tree.
RefPtr<GenericNonExclusivePromise> GetClonePromise() const {
return mClonePromise;
}
protected:
// Called when the browsing context is being discarded.
void CanonicalDiscard();
@ -494,6 +508,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {
bool mIsReplaced = false;
// A Promise created when cloning documents for printing.
RefPtr<GenericNonExclusivePromise> mClonePromise;
JS::Heap<JS::Value> mPermanentKey;
};

View File

@ -3844,20 +3844,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCloneDocumentTreeInto(
return IPC_OK();
}
RemotenessChangeOptions options;
options.mRemoteType = cp->GetRemoteType();
target->ChangeRemoteness(options, /* aPendingSwitchId = */ 0)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[source = RefPtr{source},
data = std::move(aPrintData)](BrowserParent* aBp) {
Unused << aBp->SendCloneDocumentTreeIntoSelf(source, data);
},
[](nsresult aRv) {
NS_WARNING(
nsPrintfCString("Remote clone failed: %x\n", unsigned(aRv))
.get());
});
target->CloneDocumentTreeInto(source, cp->GetRemoteType(),
std::move(aPrintData));
return IPC_OK();
}

View File

@ -6,6 +6,7 @@
#include "CrossProcessPaint.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentProcessManager.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/BrowserParent.h"
@ -357,7 +358,7 @@ void CrossProcessPaint::QueueDependencies(
for (const auto& key : aDependencies) {
auto dependency = dom::TabId(key);
// Get the current WindowGlobalParent of the remote browser that was marked
// Get the current BrowserParent of the remote browser that was marked
// as a dependency
dom::ContentProcessManager* cpm =
dom::ContentProcessManager::GetSingleton();
@ -370,17 +371,11 @@ void CrossProcessPaint::QueueDependencies(
(uint64_t)dependency);
continue;
}
RefPtr<dom::WindowGlobalParent> wgp =
browser->GetBrowsingContext()->GetCurrentWindowGlobal();
if (!wgp) {
CPP_LOG("Skipping dependency %" PRIu64 " with no current WGP.\n",
(uint64_t)dependency);
continue;
}
// TODO: Apply some sort of clipping to visible bounds here (Bug 1562720)
QueuePaint(wgp, Nothing());
// Note that if the remote document is currently being cloned, it's possible
// that the BrowserParent isn't the one for the cloned document, but the
// BrowsingContext should be persisted/consistent.
QueuePaint(browser->GetBrowsingContext());
}
}
@ -390,13 +385,49 @@ void CrossProcessPaint::QueuePaint(dom::WindowGlobalParent* aWGP,
CrossProcessPaintFlags aFlags) {
MOZ_ASSERT(!mReceivedFragments.Contains(GetTabId(aWGP)));
CPP_LOG("Queueing paint for %p.\n", aWGP);
CPP_LOG("Queueing paint for WindowGlobalParent(%p).\n", aWGP);
aWGP->DrawSnapshotInternal(this, aRect, mScale, aBackgroundColor,
(uint32_t)aFlags);
mPendingFragments += 1;
}
void CrossProcessPaint::QueuePaint(dom::CanonicalBrowsingContext* aBc) {
RefPtr<GenericNonExclusivePromise> clonePromise = aBc->GetClonePromise();
if (!clonePromise) {
RefPtr<dom::WindowGlobalParent> wgp = aBc->GetCurrentWindowGlobal();
// TODO: Apply some sort of clipping to visible bounds here (Bug 1562720)
QueuePaint(wgp, Nothing(), NS_RGBA(0, 0, 0, 0),
CrossProcessPaintFlags::DrawView);
return;
}
CPP_LOG("Queueing paint for BrowsingContext(%p).\n", aBc);
// In the case it's still in the process of cloning the remote document, we
// should defer the snapshot request after the cloning has been finished.
mPendingFragments += 1;
clonePromise->Then(
GetMainThreadSerialEventTarget(), __func__,
[self = RefPtr{this}, bc = RefPtr{aBc}]() {
RefPtr<dom::WindowGlobalParent> wgp = bc->GetCurrentWindowGlobal();
MOZ_ASSERT(!self->mReceivedFragments.Contains(GetTabId(wgp)));
// TODO: Apply some sort of clipping to visible bounds here (Bug
// 1562720)
wgp->DrawSnapshotInternal(self, Nothing(), self->mScale,
NS_RGBA(0, 0, 0, 0),
(uint32_t)CrossProcessPaintFlags::DrawView);
},
[self = RefPtr{this}]() {
CPP_LOG(
"Abort painting for BrowsingContext(%p) because cloning remote "
"document failed.\n",
self.get());
self->Clear(NS_ERROR_FAILURE);
});
}
void CrossProcessPaint::Clear(nsresult aStatus) {
mPendingFragments = 0;
mReceivedFragments.Clear();

View File

@ -30,6 +30,7 @@ struct ParamTraits;
namespace mozilla {
namespace dom {
class CanonicalBrowsingContext;
class DOMRect;
class Promise;
class WindowGlobalParent;
@ -145,6 +146,8 @@ class CrossProcessPaint final {
nscolor aBackgroundColor = NS_RGBA(0, 0, 0, 0),
CrossProcessPaintFlags aFlags = CrossProcessPaintFlags::DrawView);
void QueuePaint(dom::CanonicalBrowsingContext* aBc);
/// Clear the state of this paint so that it cannot be resolved or receive
/// any paint fragments.
void Clear(nsresult aStatus);

View File

@ -1,9 +0,0 @@
[iframe-cross-origin-print.sub.html]
bug:
if fission: https://bugzilla.mozilla.org/show_bug.cgi?id=1695806
expected:
if fission and (os == "linux") and not debug and not webrender: [FAIL, PASS]
if fission and (os == "linux") and not debug and webrender: [PASS, FAIL]
if fission and (os == "linux") and debug: [FAIL, PASS]
if fission and (os == "win") and not debug: [PASS, FAIL]
if fission and (os == "win") and debug: [FAIL, PASS]