зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1561395 - Move drawSnapshot API to WindowGlobalParent and allow specifying the whole viewport as a rect. r=mattwoodrow,nika
Differential Revision: https://phabricator.services.mozilla.com/D35842 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
55b9f173eb
Коммит
27bd25767f
|
@ -89,8 +89,6 @@
|
|||
#include "mozilla/dom/SessionStoreListener.h"
|
||||
#include "mozilla/gfx/CrossProcessPaint.h"
|
||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||
#include "mozilla/ServoCSSParser.h"
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "nsGenericHTMLFrameElement.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
|
@ -3219,54 +3217,6 @@ void nsFrameLoader::Print(uint64_t aOuterWindowID,
|
|||
#endif
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> nsFrameLoader::DrawSnapshot(
|
||||
double aX, double aY, double aW, double aH, double aScale,
|
||||
const nsAString& aBackgroundColor, mozilla::ErrorResult& aRv) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
if (!XRE_IsParentProcess()) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsIGlobalObject> global = GetOwnerContent()->GetOwnerGlobal();
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Document> document = GetOwnerContent()->GetOwnerDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
PresShell* presShell = document->GetPresShell();
|
||||
if (NS_WARN_IF(!presShell)) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nscolor color;
|
||||
css::Loader* loader = document->CSSLoader();
|
||||
ServoStyleSet* set = presShell->StyleSet();
|
||||
if (NS_WARN_IF(!ServoCSSParser::ComputeColor(
|
||||
set, NS_RGB(0, 0, 0), aBackgroundColor, &color, nullptr, loader))) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfx::IntRect rect = gfx::IntRect::RoundOut(gfx::Rect(aX, aY, aW, aH));
|
||||
|
||||
if (IsRemoteFrame()) {
|
||||
gfx::CrossProcessPaint::StartRemote(GetBrowserParent()->GetTabId(), rect,
|
||||
aScale, color, promise);
|
||||
} else {
|
||||
gfx::CrossProcessPaint::StartLocal(GetDocShell(), rect, aScale, color,
|
||||
promise);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIRemoteTab> nsFrameLoader::GetRemoteTab() {
|
||||
if (!mRemoteBrowser) {
|
||||
return nullptr;
|
||||
|
|
|
@ -201,10 +201,6 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
nsIWebProgressListener* aProgressListener,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> DrawSnapshot(
|
||||
double aX, double aY, double aW, double aH, double aScale,
|
||||
const nsAString& aBackgroundColor, mozilla::ErrorResult& aRv);
|
||||
|
||||
void StartPersistence(uint64_t aOuterWindowID,
|
||||
nsIWebBrowserPersistDocumentReceiver* aRecv,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
|
|
@ -56,6 +56,25 @@ interface WindowGlobalParent {
|
|||
BrowsingContext? bc, DOMString remoteType,
|
||||
unsigned long long pendingSwitchId);
|
||||
|
||||
/**
|
||||
* Renders a region of the frame into an image bitmap.
|
||||
*
|
||||
* @param rect Specify the area of the window to render, in CSS pixels. This
|
||||
* is relative to the current scroll position. If null, the entire viewport
|
||||
* is rendered.
|
||||
* @param scale The scale to render the window at. Use devicePixelRatio
|
||||
* to have comparable rendering to the OS.
|
||||
* @param backgroundColor The background color to use.
|
||||
*
|
||||
* This API can only be used in the parent process, as content processes
|
||||
* cannot access the rendering of out of process iframes. This API works
|
||||
* with remote and local frames.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<ImageBitmap> drawSnapshot(DOMRect? rect,
|
||||
double scale,
|
||||
DOMString backgroundColor);
|
||||
|
||||
/**
|
||||
* Fetches the securityInfo object for this window. This function will
|
||||
* look for failed and successful channels to find the security info,
|
||||
|
|
|
@ -2487,34 +2487,6 @@ mozilla::ipc::IPCResult BrowserChild::RecvRenderLayers(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvRequestRootPaint(
|
||||
const IntRect& aRect, const float& aScale, const nscolor& aBackgroundColor,
|
||||
RequestRootPaintResolver&& aResolve) {
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
if (!docShell) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
aResolve(
|
||||
gfx::PaintFragment::Record(docShell, aRect, aScale, aBackgroundColor));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvRequestSubPaint(
|
||||
const float& aScale, const nscolor& aBackgroundColor,
|
||||
RequestSubPaintResolver&& aResolve) {
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
if (!docShell) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
gfx::IntRect rect = gfx::RoundedIn(gfx::Rect(
|
||||
0.0f, 0.0f, mUnscaledInnerSize.width, mUnscaledInnerSize.height));
|
||||
aResolve(
|
||||
gfx::PaintFragment::Record(docShell, rect, aScale, aBackgroundColor));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvNavigateByKey(
|
||||
const bool& aForward, const bool& aForDocumentNavigation) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
|
|
|
@ -685,14 +685,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||
const bool& aEnabled, const bool& aForce,
|
||||
const layers::LayersObserverEpoch& aEpoch);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRequestRootPaint(
|
||||
const IntRect& aRect, const float& aScale,
|
||||
const nscolor& aBackgroundColor, RequestRootPaintResolver&& aResolve);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRequestSubPaint(
|
||||
const float& aScale, const nscolor& aBackgroundColor,
|
||||
RequestSubPaintResolver&& aResolve);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNavigateByKey(const bool& aForward,
|
||||
const bool& aForDocumentNavigation);
|
||||
|
||||
|
|
|
@ -3328,39 +3328,6 @@ void BrowserParent::LayerTreeUpdate(const LayersObserverEpoch& aEpoch,
|
|||
mFrameElement->DispatchEvent(*event);
|
||||
}
|
||||
|
||||
void BrowserParent::RequestRootPaint(gfx::CrossProcessPaint* aPaint,
|
||||
IntRect aRect, float aScale,
|
||||
nscolor aBackgroundColor) {
|
||||
auto promise = SendRequestRootPaint(aRect, aScale, aBackgroundColor);
|
||||
|
||||
RefPtr<gfx::CrossProcessPaint> paint(aPaint);
|
||||
TabId tabId(GetTabId());
|
||||
promise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[paint, tabId](PaintFragment&& aFragment) {
|
||||
paint->ReceiveFragment(tabId, std::move(aFragment));
|
||||
},
|
||||
[paint, tabId](ResponseRejectReason&& aReason) {
|
||||
paint->LostFragment(tabId);
|
||||
});
|
||||
}
|
||||
|
||||
void BrowserParent::RequestSubPaint(gfx::CrossProcessPaint* aPaint,
|
||||
float aScale, nscolor aBackgroundColor) {
|
||||
auto promise = SendRequestSubPaint(aScale, aBackgroundColor);
|
||||
|
||||
RefPtr<gfx::CrossProcessPaint> paint(aPaint);
|
||||
TabId tabId(GetTabId());
|
||||
promise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[paint, tabId](PaintFragment&& aFragment) {
|
||||
paint->ReceiveFragment(tabId, std::move(aFragment));
|
||||
},
|
||||
[paint, tabId](ResponseRejectReason&& aReason) {
|
||||
paint->LostFragment(tabId);
|
||||
});
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserParent::RecvPaintWhileInterruptingJSNoOp(
|
||||
const LayersObserverEpoch& aEpoch) {
|
||||
// We sent a PaintWhileInterruptingJS message when layers were already
|
||||
|
|
|
@ -678,11 +678,6 @@ class BrowserParent final : public PBrowserParent,
|
|||
|
||||
void LayerTreeUpdate(const LayersObserverEpoch& aEpoch, bool aActive);
|
||||
|
||||
void RequestRootPaint(gfx::CrossProcessPaint* aPaint, IntRect aRect,
|
||||
float aScale, nscolor aBackgroundColor);
|
||||
void RequestSubPaint(gfx::CrossProcessPaint* aPaint, float aScale,
|
||||
nscolor aBackgroundColor);
|
||||
|
||||
mozilla::ipc::IPCResult RecvInvokeDragSession(
|
||||
nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction,
|
||||
Maybe<Shmem>&& aVisualDnDData, const uint32_t& aStride,
|
||||
|
|
|
@ -31,7 +31,6 @@ include PBackgroundSharedTypes;
|
|||
include "mozilla/GfxMessageUtils.h";
|
||||
include "mozilla/layers/LayersMessageUtils.h";
|
||||
|
||||
using moveonly mozilla::gfx::PaintFragment from "mozilla/gfx/CrossProcessPaint.h";
|
||||
using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
|
||||
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
|
||||
using mozilla::LayoutDeviceIntPoint from "Units.h";
|
||||
|
@ -47,7 +46,6 @@ using mozilla::layers::GeckoContentController::TapType from "mozilla/layers/Geck
|
|||
using ScrollableLayerGuid::ViewID from "mozilla/layers/ScrollableLayerGuid.h";
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
|
||||
using nscolor from "nsColor.h";
|
||||
using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
|
||||
using struct mozilla::widget::IMENotification from "mozilla/widget/IMEData.h";
|
||||
using struct mozilla::widget::IMENotificationRequests from "mozilla/widget/IMEData.h";
|
||||
|
@ -56,7 +54,6 @@ using struct mozilla::widget::InputContext from "mozilla/widget/IMEData.h";
|
|||
using struct mozilla::widget::InputContextAction from "mozilla/widget/IMEData.h";
|
||||
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
|
||||
using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h";
|
||||
using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
|
||||
using class mozilla::ContentCache from "ipc/nsGUIEventIPC.h";
|
||||
using class mozilla::WidgetKeyboardEvent from "ipc/nsGUIEventIPC.h";
|
||||
using class mozilla::WidgetMouseEvent from "ipc/nsGUIEventIPC.h";
|
||||
|
@ -886,9 +883,6 @@ child:
|
|||
* PaintWhileInterruptingJS).
|
||||
*/
|
||||
async RenderLayers(bool aEnabled, bool aForceRepaint, LayersObserverEpoch aEpoch);
|
||||
|
||||
async RequestRootPaint(IntRect aRect, float aScale, nscolor aBackgroundColor) returns (PaintFragment retval);
|
||||
async RequestSubPaint(float aScale, nscolor aBackgroundColor) returns (PaintFragment retval);
|
||||
child:
|
||||
/**
|
||||
* Notify the child that it shouldn't paint the offscreen displayport.
|
||||
|
|
|
@ -11,6 +11,9 @@ include protocol PBrowserBridge;
|
|||
include DOMTypes;
|
||||
|
||||
using JSWindowActorMessageKind from "mozilla/dom/JSWindowActor.h";
|
||||
using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
|
||||
using moveonly mozilla::gfx::PaintFragment from "mozilla/gfx/CrossProcessPaint.h";
|
||||
using nscolor from "nsColor.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -40,6 +43,8 @@ child:
|
|||
uint64_t aSwitchId)
|
||||
returns (nsresult rv, nullable PBrowserBridge bridge);
|
||||
|
||||
async DrawSnapshot(IntRect? aRect, float aScale, nscolor aBackgroundColor) returns (PaintFragment retval);
|
||||
|
||||
/**
|
||||
* Returns the serialized security info associated with this window.
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "mozilla/dom/WindowGlobalActorsBinding.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/ipc/InProcessChild.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
|
@ -258,6 +259,20 @@ IPCResult WindowGlobalChild::RecvChangeFrameRemoteness(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WindowGlobalChild::RecvDrawSnapshot(
|
||||
const Maybe<IntRect>& aRect, const float& aScale,
|
||||
const nscolor& aBackgroundColor, DrawSnapshotResolver&& aResolve) {
|
||||
nsCOMPtr<nsIDocShell> docShell = BrowsingContext()->GetDocShell();
|
||||
if (!docShell) {
|
||||
aResolve(gfx::PaintFragment{});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
aResolve(
|
||||
gfx::PaintFragment::Record(docShell, aRect, aScale, aBackgroundColor));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WindowGlobalChild::RecvGetSecurityInfo(
|
||||
GetSecurityInfoResolver&& aResolve) {
|
||||
Maybe<nsCString> result;
|
||||
|
|
|
@ -103,6 +103,11 @@ class WindowGlobalChild final : public WindowGlobalActor,
|
|||
dom::BrowsingContext* aBc, const nsString& aRemoteType,
|
||||
uint64_t aPendingSwitchId, ChangeFrameRemotenessResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvDrawSnapshot(const Maybe<IntRect>& aRect,
|
||||
const float& aScale,
|
||||
const nscolor& aBackgroundColor,
|
||||
DrawSnapshotResolver&& aResolve);
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetSecurityInfo(
|
||||
GetSecurityInfoResolver&& aResolve);
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "mozilla/dom/ChromeUtils.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#include "mozilla/ServoCSSParser.h"
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "mozJSComponentLoader.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
|
@ -284,7 +286,7 @@ already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
nsIGlobalObject* global = GetParentObject();
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -340,6 +342,49 @@ already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> WindowGlobalParent::DrawSnapshot(
|
||||
const DOMRect* aRect, double aScale, const nsAString& aBackgroundColor,
|
||||
mozilla::ErrorResult& aRv) {
|
||||
nsIGlobalObject* global = GetParentObject();
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nscolor color;
|
||||
if (NS_WARN_IF(!ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0),
|
||||
aBackgroundColor, &color,
|
||||
nullptr, nullptr))) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gfx::CrossProcessPaint::Start(this, aRect, (float)aScale, color,
|
||||
promise)) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void WindowGlobalParent::DrawSnapshotInternal(gfx::CrossProcessPaint* aPaint,
|
||||
const Maybe<IntRect>& aRect,
|
||||
float aScale,
|
||||
nscolor aBackgroundColor) {
|
||||
auto promise = SendDrawSnapshot(aRect, aScale, aBackgroundColor);
|
||||
|
||||
RefPtr<gfx::CrossProcessPaint> paint(aPaint);
|
||||
RefPtr<WindowGlobalParent> wgp(this);
|
||||
promise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[paint, wgp](PaintFragment&& aFragment) {
|
||||
paint->ReceiveFragment(wgp, std::move(aFragment));
|
||||
},
|
||||
[paint, wgp](ResponseRejectReason&& aReason) {
|
||||
paint->LostFragment(wgp);
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> WindowGlobalParent::GetSecurityInfo(
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
||||
|
@ -348,7 +393,7 @@ already_AddRefed<Promise> WindowGlobalParent::GetSecurityInfo(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
nsIGlobalObject* global = GetParentObject();
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -410,7 +455,7 @@ JSObject* WindowGlobalParent::WrapObject(JSContext* aCx,
|
|||
return WindowGlobalParent_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* WindowGlobalParent::GetParentObject() {
|
||||
nsIGlobalObject* WindowGlobalParent::GetParentObject() {
|
||||
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_dom_WindowGlobalParent_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/DOMRect.h"
|
||||
#include "mozilla/dom/PWindowGlobalParent.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
@ -21,6 +22,11 @@ class nsIURI;
|
|||
class nsFrameLoader;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class CrossProcessPaint;
|
||||
} // namespace gfx
|
||||
|
||||
namespace dom {
|
||||
|
||||
class WindowGlobalChild;
|
||||
|
@ -32,6 +38,7 @@ class JSWindowActorMessageMeta;
|
|||
*/
|
||||
class WindowGlobalParent final : public WindowGlobalActor,
|
||||
public PWindowGlobalParent {
|
||||
friend class gfx::CrossProcessPaint;
|
||||
friend class PWindowGlobalParent;
|
||||
|
||||
public:
|
||||
|
@ -107,6 +114,10 @@ class WindowGlobalParent final : public WindowGlobalActor,
|
|||
uint64_t aPendingSwitchId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> DrawSnapshot(
|
||||
const DOMRect* aRect, double aScale, const nsAString& aBackgroundColor,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetSecurityInfo(ErrorResult& aRv);
|
||||
|
||||
// Create a WindowGlobalParent from over IPC. This method should not be called
|
||||
|
@ -117,7 +128,7 @@ class WindowGlobalParent final : public WindowGlobalActor,
|
|||
// be called after setting the Manager actor.
|
||||
void Init(const WindowGlobalInit& aInit);
|
||||
|
||||
nsISupports* GetParentObject();
|
||||
nsIGlobalObject* GetParentObject();
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
|
@ -140,6 +151,10 @@ class WindowGlobalParent final : public WindowGlobalActor,
|
|||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
void DrawSnapshotInternal(gfx::CrossProcessPaint* aPaint,
|
||||
const Maybe<IntRect>& aRect, float aScale,
|
||||
nscolor aBackgroundColor);
|
||||
|
||||
private:
|
||||
~WindowGlobalParent();
|
||||
|
||||
|
|
|
@ -120,30 +120,6 @@ interface FrameLoader {
|
|||
nsIPrintSettings aPrintSettings,
|
||||
optional nsIWebProgressListener? aProgressListener = null);
|
||||
|
||||
/**
|
||||
* Renders a region of the frame into an image bitmap.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param w
|
||||
* @param h Specify the area of the window to render, in CSS
|
||||
* pixels. This is relative to the current scroll position.
|
||||
* @param scale The scale to render the window at. Use devicePixelRatio
|
||||
* to have comparable rendering to the OS.
|
||||
* @param backgroundColor The background color to use.
|
||||
*
|
||||
* This API can only be used in the parent process, as content processes
|
||||
* cannot access the rendering of out of process iframes. This API works
|
||||
* with remote and local frames.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<ImageBitmap> drawSnapshot(double x,
|
||||
double y,
|
||||
double w,
|
||||
double h,
|
||||
double scale,
|
||||
DOMString backgroundColor);
|
||||
|
||||
/**
|
||||
* The element which owns this frame loader.
|
||||
*
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "mozilla/dom/ContentProcessManager.h"
|
||||
#include "mozilla/dom/ImageBitmap.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/PWindowGlobalParent.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/dom/WindowGlobalChild.h"
|
||||
#include "mozilla/gfx/DrawEventRecorder.h"
|
||||
#include "mozilla/gfx/InlineTranslator.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
|
@ -41,9 +44,41 @@ static const float kMinPaintScale = 0.05f;
|
|||
|
||||
/* static */
|
||||
PaintFragment PaintFragment::Record(nsIDocShell* aDocShell,
|
||||
const IntRect& aRect, float aScale,
|
||||
const Maybe<IntRect>& aRect, float aScale,
|
||||
nscolor aBackgroundColor) {
|
||||
IntSize surfaceSize = aRect.Size();
|
||||
if (!aDocShell) {
|
||||
PF_LOG("Couldn't find DocShell.\n");
|
||||
return PaintFragment{};
|
||||
}
|
||||
|
||||
RefPtr<nsPresContext> presContext = aDocShell->GetPresContext();
|
||||
if (!presContext) {
|
||||
PF_LOG("Couldn't find PresContext.\n");
|
||||
return PaintFragment{};
|
||||
}
|
||||
|
||||
IntRect rect;
|
||||
if (!aRect) {
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
nsContentUtils::WidgetForDocument(aDocShell->GetDocument());
|
||||
|
||||
// TODO: Apply some sort of clipping to visible bounds here (Bug 1562720)
|
||||
LayoutDeviceIntRect boundsDevice = widget->GetBounds();
|
||||
boundsDevice.MoveTo(0, 0);
|
||||
nsRect boundsAu = LayoutDevicePixel::ToAppUnits(
|
||||
boundsDevice, presContext->AppUnitsPerDevPixel());
|
||||
rect = gfx::RoundedOut(CSSPixel::FromAppUnits(boundsAu).ToUnknownRect());
|
||||
} else {
|
||||
rect = *aRect;
|
||||
}
|
||||
|
||||
if (rect.IsEmpty()) {
|
||||
// TODO: Should we return an empty surface here?
|
||||
PF_LOG("Empty rect to paint.\n");
|
||||
return PaintFragment{};
|
||||
}
|
||||
|
||||
IntSize surfaceSize = rect.Size();
|
||||
surfaceSize.width *= aScale;
|
||||
surfaceSize.height *= aScale;
|
||||
|
||||
|
@ -53,7 +88,7 @@ PaintFragment PaintFragment::Record(nsIDocShell* aDocShell,
|
|||
"rect=(%d, %d) x (%d, %d), "
|
||||
"scale=%f, "
|
||||
"color=(%u, %u, %u, %u)]\n",
|
||||
aDocShell, aRect.x, aRect.y, aRect.width, aRect.height, aScale,
|
||||
aDocShell, rect.x, rect.y, rect.width, rect.height, aScale,
|
||||
NS_GET_R(aBackgroundColor), NS_GET_G(aBackgroundColor),
|
||||
NS_GET_B(aBackgroundColor), NS_GET_A(aBackgroundColor));
|
||||
|
||||
|
@ -68,16 +103,6 @@ PaintFragment PaintFragment::Record(nsIDocShell* aDocShell,
|
|||
// Flush any pending notifications
|
||||
nsContentUtils::FlushLayoutForTree(aDocShell->GetWindow());
|
||||
|
||||
// Grab the presentation shell to render
|
||||
RefPtr<nsPresContext> presContext;
|
||||
if (aDocShell) {
|
||||
presContext = aDocShell->GetPresContext();
|
||||
}
|
||||
if (!presContext) {
|
||||
PF_LOG("Couldn't find PresContext.\n");
|
||||
return PaintFragment{};
|
||||
}
|
||||
|
||||
// Initialize the recorder
|
||||
SurfaceFormat format = SurfaceFormat::B8G8R8A8;
|
||||
RefPtr<DrawTarget> referenceDt = Factory::CreateDrawTarget(
|
||||
|
@ -91,10 +116,10 @@ PaintFragment PaintFragment::Record(nsIDocShell* aDocShell,
|
|||
|
||||
// Perform the actual rendering
|
||||
{
|
||||
nsRect r(nsPresContext::CSSPixelsToAppUnits(aRect.x),
|
||||
nsPresContext::CSSPixelsToAppUnits(aRect.y),
|
||||
nsPresContext::CSSPixelsToAppUnits(aRect.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(aRect.height));
|
||||
nsRect r(nsPresContext::CSSPixelsToAppUnits(rect.x),
|
||||
nsPresContext::CSSPixelsToAppUnits(rect.y),
|
||||
nsPresContext::CSSPixelsToAppUnits(rect.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(rect.height));
|
||||
|
||||
RefPtr<gfxContext> thebes = gfxContext::CreateOrNull(dt);
|
||||
thebes->SetMatrix(Matrix::Scaling(aScale, aScale));
|
||||
|
@ -128,100 +153,119 @@ PaintFragment::PaintFragment(IntSize aSize, ByteBuf&& aRecording,
|
|||
mDependencies(std::move(aDependencies)) {}
|
||||
|
||||
/* static */
|
||||
void CrossProcessPaint::StartLocal(nsIDocShell* aRoot, const IntRect& aRect,
|
||||
float aScale, nscolor aBackgroundColor,
|
||||
dom::Promise* aPromise) {
|
||||
bool CrossProcessPaint::Start(dom::WindowGlobalParent* aRoot,
|
||||
const dom::DOMRect* aRect, float aScale,
|
||||
nscolor aBackgroundColor,
|
||||
dom::Promise* aPromise) {
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
aScale = std::max(aScale, kMinPaintScale);
|
||||
|
||||
CPP_LOG(
|
||||
"Starting local paint. "
|
||||
"[docshell=%p, "
|
||||
"rect=(%d, %d) x (%d, %d), "
|
||||
"Starting paint. "
|
||||
"[wgp=%p, "
|
||||
"scale=%f, "
|
||||
"color=(%u, %u, %u, %u)]\n",
|
||||
aRoot, aRect.x, aRect.y, aRect.width, aRect.height, aScale,
|
||||
NS_GET_R(aBackgroundColor), NS_GET_G(aBackgroundColor),
|
||||
aRoot, aScale, NS_GET_R(aBackgroundColor), NS_GET_G(aBackgroundColor),
|
||||
NS_GET_B(aBackgroundColor), NS_GET_A(aBackgroundColor));
|
||||
|
||||
RefPtr<CrossProcessPaint> resolver =
|
||||
new CrossProcessPaint(aPromise, aScale, aBackgroundColor, dom::TabId(0));
|
||||
resolver->ReceiveFragment(
|
||||
dom::TabId(0),
|
||||
PaintFragment::Record(aRoot, aRect, aScale, aBackgroundColor));
|
||||
}
|
||||
|
||||
/* static */
|
||||
void CrossProcessPaint::StartRemote(dom::TabId aRoot, const IntRect& aRect,
|
||||
float aScale, nscolor aBackgroundColor,
|
||||
dom::Promise* aPromise) {
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
aScale = std::max(aScale, kMinPaintScale);
|
||||
|
||||
CPP_LOG(
|
||||
"Starting remote paint. "
|
||||
"[tab=%llu, "
|
||||
"rect=(%d, %d) x (%d, %d), "
|
||||
"scale=%f, "
|
||||
"color=(%u, %u, %u, %u)]\n",
|
||||
(uint64_t)aRoot, aRect.x, aRect.y, aRect.width, aRect.height, aScale,
|
||||
NS_GET_R(aBackgroundColor), NS_GET_G(aBackgroundColor),
|
||||
NS_GET_B(aBackgroundColor), NS_GET_A(aBackgroundColor));
|
||||
Maybe<IntRect> rect;
|
||||
if (aRect) {
|
||||
*rect = IntRect::RoundOut((float)aRect->X(), (float)aRect->Y(),
|
||||
(float)aRect->Width(), (float)aRect->Height());
|
||||
}
|
||||
|
||||
RefPtr<CrossProcessPaint> resolver =
|
||||
new CrossProcessPaint(aPromise, aScale, aBackgroundColor, aRoot);
|
||||
resolver->QueueRootPaint(aRoot, aRect, aScale, aBackgroundColor);
|
||||
|
||||
if (aRoot->IsInProcess()) {
|
||||
RefPtr<dom::WindowGlobalChild> childActor = aRoot->GetChildActor();
|
||||
if (!childActor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// `BrowsingContext()` cannot be nullptr.
|
||||
nsCOMPtr<nsIDocShell> docShell =
|
||||
childActor->BrowsingContext()->GetDocShell();
|
||||
if (!docShell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resolver->mPendingFragments += 1;
|
||||
resolver->ReceiveFragment(
|
||||
aRoot, PaintFragment::Record(docShell, rect, aScale, aBackgroundColor));
|
||||
} else {
|
||||
resolver->QueuePaint(aRoot, rect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CrossProcessPaint::CrossProcessPaint(dom::Promise* aPromise, float aScale,
|
||||
nscolor aBackgroundColor,
|
||||
dom::TabId aRootId)
|
||||
dom::WindowGlobalParent* aRoot)
|
||||
: mPromise{aPromise},
|
||||
mRootId{aRootId},
|
||||
mRoot{aRoot},
|
||||
mScale{aScale},
|
||||
mBackgroundColor{aBackgroundColor},
|
||||
mPendingFragments{1} {}
|
||||
mPendingFragments{0} {}
|
||||
|
||||
CrossProcessPaint::~CrossProcessPaint() {}
|
||||
|
||||
void CrossProcessPaint::ReceiveFragment(dom::TabId aId,
|
||||
void CrossProcessPaint::ReceiveFragment(dom::WindowGlobalParent* aWGP,
|
||||
PaintFragment&& aFragment) {
|
||||
if (IsCleared()) {
|
||||
CPP_LOG("Ignoring fragment from %llu.\n", (uint64_t)aId);
|
||||
CPP_LOG("Ignoring fragment from %p.\n", aWGP);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPendingFragments > 0);
|
||||
MOZ_ASSERT(!mReceivedFragments.GetValue(aId));
|
||||
MOZ_ASSERT(!mReceivedFragments.GetValue(aWGP));
|
||||
MOZ_ASSERT(!aFragment.IsEmpty());
|
||||
|
||||
// Double check our invariants to protect against a compromised content
|
||||
// process
|
||||
if (mPendingFragments == 0 || mReceivedFragments.GetValue(aId) ||
|
||||
if (mPendingFragments == 0 || mReceivedFragments.GetValue(aWGP) ||
|
||||
aFragment.IsEmpty()) {
|
||||
CPP_LOG("Dropping invalid fragment from %llu.\n", (uint64_t)aId);
|
||||
LostFragment(aId);
|
||||
CPP_LOG("Dropping invalid fragment from %p.\n", aWGP);
|
||||
LostFragment(aWGP);
|
||||
return;
|
||||
}
|
||||
|
||||
CPP_LOG("Receiving fragment from %llu.\n", (uint64_t)aId);
|
||||
CPP_LOG("Receiving fragment from %p.\n", aWGP);
|
||||
|
||||
// Queue paints for child tabs
|
||||
for (auto iter = aFragment.mDependencies.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto dependency = iter.Get()->GetKey();
|
||||
QueueSubPaint(dom::TabId(dependency));
|
||||
auto dependency = dom::TabId(iter.Get()->GetKey());
|
||||
|
||||
// Get the current WindowGlobalParent of the remote browser that was marked
|
||||
// as a dependency
|
||||
dom::ContentProcessManager* cpm =
|
||||
dom::ContentProcessManager::GetSingleton();
|
||||
dom::ContentParentId cpId = cpm->GetTabProcessId(dependency);
|
||||
RefPtr<dom::BrowserParent> browser =
|
||||
cpm->GetBrowserParentByProcessAndTabId(cpId, dependency);
|
||||
RefPtr<dom::WindowGlobalParent> wgp =
|
||||
browser->GetBrowsingContext()->GetCurrentWindowGlobal();
|
||||
|
||||
if (!wgp) {
|
||||
CPP_LOG("Skipping dependency %llu with no current WGP.\n",
|
||||
(uint64_t)dependency);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Apply some sort of clipping to visible bounds here (Bug 1562720)
|
||||
QueuePaint(wgp, Nothing());
|
||||
}
|
||||
|
||||
mReceivedFragments.Put(aId, std::move(aFragment));
|
||||
mReceivedFragments.Put(aWGP, std::move(aFragment));
|
||||
mPendingFragments -= 1;
|
||||
|
||||
// Resolve this paint if we have received all pending fragments
|
||||
MaybeResolve();
|
||||
}
|
||||
|
||||
void CrossProcessPaint::LostFragment(dom::TabId aId) {
|
||||
void CrossProcessPaint::LostFragment(dom::WindowGlobalParent* aWGP) {
|
||||
if (IsCleared()) {
|
||||
CPP_LOG("Ignoring lost fragment from %llu.\n", (uint64_t)aId);
|
||||
CPP_LOG("Ignoring lost fragment from %p.\n", aWGP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -229,36 +273,14 @@ void CrossProcessPaint::LostFragment(dom::TabId aId) {
|
|||
Clear();
|
||||
}
|
||||
|
||||
void CrossProcessPaint::QueueRootPaint(dom::TabId aId, const IntRect& aRect,
|
||||
float aScale, nscolor aBackgroundColor) {
|
||||
MOZ_ASSERT(!mReceivedFragments.GetValue(aId));
|
||||
MOZ_ASSERT(mPendingFragments == 1);
|
||||
void CrossProcessPaint::QueuePaint(dom::WindowGlobalParent* aWGP,
|
||||
const Maybe<IntRect>& aRect) {
|
||||
MOZ_ASSERT(!mReceivedFragments.GetValue(aWGP));
|
||||
|
||||
CPP_LOG("Queueing root paint for %llu.\n", (uint64_t)aId);
|
||||
|
||||
dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton();
|
||||
|
||||
dom::ContentParentId cpId = cpm->GetTabProcessId(aId);
|
||||
RefPtr<dom::BrowserParent> tab =
|
||||
cpm->GetBrowserParentByProcessAndTabId(cpId, aId);
|
||||
tab->RequestRootPaint(this, aRect, aScale, aBackgroundColor);
|
||||
|
||||
// This will always be the first paint, so the constructor will already have
|
||||
// incremented one pending fragment
|
||||
}
|
||||
|
||||
void CrossProcessPaint::QueueSubPaint(dom::TabId aId) {
|
||||
MOZ_ASSERT(!mReceivedFragments.GetValue((uint64_t)aId));
|
||||
|
||||
CPP_LOG("Queueing sub paint for %llu.\n", (uint64_t)aId);
|
||||
|
||||
dom::ContentProcessManager* cpm = dom::ContentProcessManager::GetSingleton();
|
||||
|
||||
dom::ContentParentId cpId = cpm->GetTabProcessId(aId);
|
||||
RefPtr<dom::BrowserParent> tab =
|
||||
cpm->GetBrowserParentByProcessAndTabId(cpId, aId);
|
||||
tab->RequestSubPaint(this, mScale, mBackgroundColor);
|
||||
CPP_LOG("Queueing paint for %p.\n", aWGP);
|
||||
|
||||
// TODO - Don't apply the background color to all paints (Bug 1562722)
|
||||
aWGP->DrawSnapshotInternal(this, aRect, mScale, mBackgroundColor);
|
||||
mPendingFragments += 1;
|
||||
}
|
||||
|
||||
|
@ -270,6 +292,16 @@ void CrossProcessPaint::Clear() {
|
|||
|
||||
bool CrossProcessPaint::IsCleared() const { return !mPromise; }
|
||||
|
||||
static dom::TabId GetTabId(dom::WindowGlobalParent* aWGP) {
|
||||
// There is no unique TabId for a given WindowGlobalParent, as multiple
|
||||
// WindowGlobalParents share the same PBrowser actor. However, we only
|
||||
// ever queue one paint per PBrowser by just using the current
|
||||
// WindowGlobalParent for a PBrowser. So we can interchange TabId and
|
||||
// WindowGlobalParent when dealing with resolving surfaces.
|
||||
RefPtr<dom::BrowserParent> browserParent = aWGP->GetBrowserParent();
|
||||
return browserParent ? browserParent->GetTabId() : dom::TabId(0);
|
||||
}
|
||||
|
||||
void CrossProcessPaint::MaybeResolve() {
|
||||
// Don't do anything if we aren't ready, experienced an error, or already
|
||||
// resolved this paint
|
||||
|
@ -283,7 +315,7 @@ void CrossProcessPaint::MaybeResolve() {
|
|||
|
||||
// Resolve the paint fragments from the bottom up
|
||||
ResolvedSurfaceMap resolved;
|
||||
if (!ResolveInternal(mRootId, &resolved)) {
|
||||
if (!ResolveInternal(mRoot, &resolved)) {
|
||||
CPP_LOG("Couldn't resolve.\n");
|
||||
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
|
@ -291,8 +323,8 @@ void CrossProcessPaint::MaybeResolve() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Grab the result from the resolved table
|
||||
RefPtr<SourceSurface> root = resolved.Get(mRootId);
|
||||
// Grab the result from the resolved table.
|
||||
RefPtr<SourceSurface> root = resolved.Get(GetTabId(mRoot));
|
||||
CPP_LOG("Resolved all fragments.\n");
|
||||
|
||||
ErrorResult rv;
|
||||
|
@ -309,19 +341,31 @@ void CrossProcessPaint::MaybeResolve() {
|
|||
Clear();
|
||||
}
|
||||
|
||||
bool CrossProcessPaint::ResolveInternal(dom::TabId aId,
|
||||
bool CrossProcessPaint::ResolveInternal(dom::WindowGlobalParent* aWGP,
|
||||
ResolvedSurfaceMap* aResolved) {
|
||||
// Convert aWGP to an ID we can use for surfaces
|
||||
dom::TabId surfaceId = GetTabId(aWGP);
|
||||
|
||||
// We should not have resolved this paint already
|
||||
MOZ_ASSERT(!aResolved->GetWeak(aId));
|
||||
MOZ_ASSERT(!aResolved->GetWeak(surfaceId));
|
||||
|
||||
CPP_LOG("Resolving fragment %llu.\n", (uint64_t)aId);
|
||||
CPP_LOG("Resolving fragment %p.\n", aWGP);
|
||||
|
||||
Maybe<PaintFragment> fragment = mReceivedFragments.GetAndRemove(aId);
|
||||
Maybe<PaintFragment> fragment = mReceivedFragments.GetAndRemove(aWGP);
|
||||
|
||||
// Rasterize all the dependencies first so that we can resolve this fragment
|
||||
for (auto iter = fragment->mDependencies.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto dependency = iter.Get()->GetKey();
|
||||
if (!ResolveInternal(dom::TabId(dependency), aResolved)) {
|
||||
auto dependency = dom::TabId(iter.Get()->GetKey());
|
||||
|
||||
dom::ContentProcessManager* cpm =
|
||||
dom::ContentProcessManager::GetSingleton();
|
||||
dom::ContentParentId cpId = cpm->GetTabProcessId(dependency);
|
||||
RefPtr<dom::BrowserParent> tab =
|
||||
cpm->GetBrowserParentByProcessAndTabId(cpId, dependency);
|
||||
RefPtr<dom::WindowGlobalParent> wgp =
|
||||
tab->GetBrowsingContext()->GetCurrentWindowGlobal();
|
||||
|
||||
if (!ResolveInternal(wgp, aResolved)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -331,8 +375,8 @@ bool CrossProcessPaint::ResolveInternal(dom::TabId aId,
|
|||
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
||||
fragment->mSize, SurfaceFormat::B8G8R8A8);
|
||||
if (!drawTarget || !drawTarget->IsValid()) {
|
||||
CPP_LOG("Couldn't create (%d x %d) surface for fragment %llu.\n",
|
||||
fragment->mSize.width, fragment->mSize.height, (uint64_t)aId);
|
||||
CPP_LOG("Couldn't create (%d x %d) surface for fragment %p.\n",
|
||||
fragment->mSize.width, fragment->mSize.height, aWGP);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -342,15 +386,14 @@ bool CrossProcessPaint::ResolveInternal(dom::TabId aId,
|
|||
translator.SetExternalSurfaces(aResolved);
|
||||
if (!translator.TranslateRecording((char*)fragment->mRecording.mData,
|
||||
fragment->mRecording.mLen)) {
|
||||
CPP_LOG("Couldn't translate recording for fragment %llu.\n",
|
||||
(uint64_t)aId);
|
||||
CPP_LOG("Couldn't translate recording for fragment %p.\n", aWGP);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
|
||||
if (!snapshot) {
|
||||
CPP_LOG("Couldn't get snapshot for fragment %llu.\n", (uint64_t)aId);
|
||||
CPP_LOG("Couldn't get snapshot for fragment %p.\n", aWGP);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -361,7 +404,7 @@ bool CrossProcessPaint::ResolveInternal(dom::TabId aId,
|
|||
aResolved->Remove(dependency);
|
||||
}
|
||||
|
||||
aResolved->Put(aId, snapshot);
|
||||
aResolved->Put(surfaceId, snapshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/DOMRect.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/ipc/ByteBuf.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
@ -23,6 +25,11 @@ struct ParamTraits;
|
|||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class WindowGlobalParent;
|
||||
} // namespace dom
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class CrossProcessPaint;
|
||||
|
@ -40,7 +47,8 @@ class PaintFragment final {
|
|||
* for an nsIDocShell.
|
||||
*
|
||||
* @param aDocShell The document shell to record.
|
||||
* @param aRect The rectangle relative to the viewport to use.
|
||||
* @param aRect The rectangle relative to the viewport to use. If no
|
||||
* rectangle is specified, then the whole viewport will be used.
|
||||
* @param aScale The coordinate scale to use. The size of the resolved
|
||||
* surface will be `aRect.Size() * aScale`, with aScale clamped to
|
||||
* at least kMinPaintScale.
|
||||
|
@ -49,8 +57,9 @@ class PaintFragment final {
|
|||
* @return A paint fragment. The paint fragment may be `empty` if rendering
|
||||
* was unable to be accomplished for some reason.
|
||||
*/
|
||||
static PaintFragment Record(nsIDocShell* aDocShell, const IntRect& aRect,
|
||||
float aScale, nscolor aBackgroundColor);
|
||||
static PaintFragment Record(nsIDocShell* aDocShell,
|
||||
const Maybe<IntRect>& aRect, float aScale,
|
||||
nscolor aBackgroundColor);
|
||||
|
||||
/// Returns whether this paint fragment contains a valid recording.
|
||||
bool IsEmpty() const;
|
||||
|
@ -80,56 +89,42 @@ class CrossProcessPaint final {
|
|||
public:
|
||||
/**
|
||||
* Begin an asynchronous paint of a cross process document tree starting at
|
||||
* a local document shell. The local document will be painted, then async
|
||||
* paints will be queued for remote subframes. Once all subframes have been
|
||||
* recorded, the final image will be resolved, and the promise will be
|
||||
* resolved with a dom::ImageBitmap.
|
||||
* a WindowGlobalParent. A maybe-async paint for the root WGP will be done,
|
||||
* then async paints will be recursively queued for remote subframes. Once
|
||||
* all subframes have been recorded, the final image will be resolved, and
|
||||
* the promise will be resolved with a dom::ImageBitmap.
|
||||
*
|
||||
* @param aDocShell The document shell to paint.
|
||||
* @param aRect The rectangle relative to the viewport to use.
|
||||
* @param aRoot The WindowGlobalParent to paint.
|
||||
* @param aRect The rectangle relative to the viewport to use, or null to
|
||||
* render the whole viewport.
|
||||
* @param aScale The coordinate scale to use. The size of the resolved
|
||||
* surface will be `aRect.Size() * aScale`, with aScale clamped to
|
||||
* at least kMinPaintScale. See the implementation for the current
|
||||
* minimum value.
|
||||
* @param aBackgroundColor The background color to use.
|
||||
* @param aPromise The promise to resolve with a dom::ImageBitmap.
|
||||
*/
|
||||
static void StartLocal(nsIDocShell* aRoot, const IntRect& aRect, float aScale,
|
||||
nscolor aBackgroundColor, dom::Promise* aPromise);
|
||||
|
||||
/**
|
||||
* Begin an asynchronous paint of a cross process document tree starting at
|
||||
* a remote tab. An async paint for the remote tab will be queued, then async
|
||||
* paints will be recursively queued for remote subframes. Once all subframes
|
||||
* have been recorded, the final image will be resolved, and the promise will
|
||||
* be resolved with a dom::ImageBitmap.
|
||||
*
|
||||
* @param aDocShell The document shell to paint.
|
||||
* @param aRect The rectangle relative to the viewport to use.
|
||||
* @param aScale The coordinate scale to use. The size of the resolved
|
||||
* surface will be `aRect.Size() * aScale`, with aScale clamped to
|
||||
* at least kMinPaintScale. See the implementation for the current
|
||||
* minimum value.
|
||||
* @param aBackgroundColor The background color to use.
|
||||
* @param aPromise The promise to resolve with a dom::ImageBitmap.
|
||||
* @returns Whether the paint was able to be initiated or not.
|
||||
*/
|
||||
static void StartRemote(dom::TabId aRoot, const IntRect& aRect, float aScale,
|
||||
nscolor aBackgroundColor, dom::Promise* aPromise);
|
||||
static bool Start(dom::WindowGlobalParent* aRoot, const dom::DOMRect* aRect,
|
||||
float aScale, nscolor aBackgroundColor,
|
||||
dom::Promise* aPromise);
|
||||
|
||||
void ReceiveFragment(dom::TabId aId, PaintFragment&& aFragment);
|
||||
void LostFragment(dom::TabId aId);
|
||||
void ReceiveFragment(dom::WindowGlobalParent* aWGP,
|
||||
PaintFragment&& aFragment);
|
||||
void LostFragment(dom::WindowGlobalParent* aWGP);
|
||||
|
||||
private:
|
||||
typedef nsRefPtrHashtable<nsUint64HashKey, SourceSurface> ResolvedSurfaceMap;
|
||||
typedef nsDataHashtable<nsUint64HashKey, PaintFragment> ReceivedFragmentMap;
|
||||
typedef nsDataHashtable<nsRefPtrHashKey<dom::WindowGlobalParent>,
|
||||
PaintFragment>
|
||||
ReceivedFragmentMap;
|
||||
|
||||
CrossProcessPaint(dom::Promise* aPromise, float aScale,
|
||||
nscolor aBackgroundColor, dom::TabId aRootId);
|
||||
nscolor aBackgroundColor, dom::WindowGlobalParent* aRoot);
|
||||
~CrossProcessPaint();
|
||||
|
||||
void QueueRootPaint(dom::TabId aId, const IntRect& aRect, float aScale,
|
||||
nscolor aBackgroundColor);
|
||||
void QueueSubPaint(dom::TabId aId);
|
||||
void QueuePaint(dom::WindowGlobalParent* aWGP, const Maybe<IntRect>& aRect);
|
||||
|
||||
/// Clear the state of this paint so that it cannot be resolved or receive
|
||||
/// any paint fragments.
|
||||
|
@ -141,10 +136,11 @@ class CrossProcessPaint final {
|
|||
/// Resolves the paint fragments if we have none pending and resolves the
|
||||
/// promise.
|
||||
void MaybeResolve();
|
||||
bool ResolveInternal(dom::TabId aId, ResolvedSurfaceMap* aResolved);
|
||||
bool ResolveInternal(dom::WindowGlobalParent* aWGP,
|
||||
ResolvedSurfaceMap* aResolved);
|
||||
|
||||
RefPtr<dom::Promise> mPromise;
|
||||
dom::TabId mRootId;
|
||||
RefPtr<dom::WindowGlobalParent> mRoot;
|
||||
float mScale;
|
||||
nscolor mBackgroundColor;
|
||||
uint32_t mPendingFragments;
|
||||
|
|
Загрузка…
Ссылка в новой задаче