Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Noemi Erli 2018-10-09 00:56:03 +03:00
Родитель f9668b6e7e 31184dddce
Коммит c2709dc7e9
49 изменённых файлов: 1288 добавлений и 114 удалений

Просмотреть файл

@ -195,7 +195,7 @@ class UrlbarInput {
// Private methods below.
_updateTextOverflow() {
if (!this._inOverflow) {
if (!this._overflowing) {
this.removeAttribute("textoverflow");
return;
}
@ -203,7 +203,7 @@ class UrlbarInput {
this.window.promiseDocumentFlushed(() => {
// Check overflow again to ensure it didn't change in the meantime.
let input = this.inputField;
if (input && this._inOverflow) {
if (input && this._overflowing) {
let side = input.scrollLeft &&
input.scrollLeft == input.scrollLeftMax ? "start" : "end";
this.setAttribute("textoverflow", side);
@ -212,7 +212,7 @@ class UrlbarInput {
}
_updateUrlTooltip() {
if (this.focused || !this._inOverflow) {
if (this.focused || !this._overflowing) {
this.inputField.removeAttribute("title");
} else {
this.inputField.setAttribute("title", this.value);
@ -392,7 +392,7 @@ class UrlbarInput {
if (targetIsPlaceholder) {
return;
}
this._inOverflow = true;
this._overflowing = true;
this._updateTextOverflow();
}
@ -404,7 +404,7 @@ class UrlbarInput {
if (targetIsPlaceholder) {
return;
}
this._inOverflow = false;
this._overflowing = false;
this._updateTextOverflow();

Просмотреть файл

@ -35,10 +35,17 @@ function sortWithClones(requests, sorter, a, b) {
return sorter(a, b);
}
const getFilterFn = createSelector(
/**
* Take clones into account when filtering. If a request is
* a clone, it's not filtered out.
*/
const getFilterWithCloneFn = createSelector(
state => state.filters,
filters => r => {
const matchesType = Object.keys(filters.requestFilterTypes).some(filter => {
if (r.id.endsWith("-clone")) {
return true;
}
return filters.requestFilterTypes[filter] && Filters[filter] && Filters[filter](r);
});
return matchesType && isFreetextMatch(r, filters.requestFilterText);
@ -78,7 +85,7 @@ const getSortedRequests = createSelector(
const getDisplayedRequests = createSelector(
state => state.requests,
getFilterFn,
getFilterWithCloneFn,
getSortFn,
({ requests }, filterFn, sortFn) => {
const arr = [...requests.values()].filter(filterFn).sort(sortFn);

Просмотреть файл

@ -120,6 +120,7 @@ subsuite = clipboard
skip-if = (os == 'mac') # Bug 1479782
[browser_net_header-docs.js]
[browser_net_edit_resend_caret.js]
[browser_net_edit_resend_with_filtering.js]
[browser_net_filter-01.js]
[browser_net_filter-02.js]
[browser_net_filter-03.js]

Просмотреть файл

@ -0,0 +1,55 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests if resending a XHR request while filtering XHR displays
* the correct requests
*/
add_task(async function() {
const { tab, monitor } = await initNetMonitor(POST_RAW_URL);
const { document, store, windowRequire, parent } = monitor.panelWin;
const parentDocument = parent.document;
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
store.dispatch(Actions.batchEnable(false));
// Execute XHR request and filter by XHR
await performRequests(monitor, tab, 1);
document.querySelector(".requests-list-filter-xhr-button").click();
// Confirm XHR request and click it
const xhrRequestItem = document.querySelectorAll(".request-list-item")[0];
EventUtils.sendMouseEvent({ type: "mousedown" }, xhrRequestItem);
const {
getSelectedRequest
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
const firstRequest = getSelectedRequest(store.getState());
// Open context menu and execute "Edit & Resend".
EventUtils.sendMouseEvent({ type: "contextmenu" }, xhrRequestItem);
parentDocument.querySelector("#request-list-context-resend").click();
// Click Resend
await waitUntil(() => document.querySelector("#custom-request-send-button"));
document.querySelector("#custom-request-send-button").click();
// Filtering by "other" so the resent request is visible after completion
document.querySelector(".requests-list-filter-other-button").click();
// Select the cloned request
document.querySelectorAll(".request-list-item")[0].click();
const resendRequest = getSelectedRequest(store.getState());
ok(resendRequest.id !== firstRequest.id,
"The second XHR request was made and is unique");
ok(resendRequest.id.replace(/-clone$/, "") == firstRequest.id,
"The second XHR request is a clone of the first");
return teardown(monitor);
});

Просмотреть файл

@ -80,8 +80,11 @@
#include "mozilla/dom/ChromeMessageSender.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FrameLoaderBinding.h"
#include "mozilla/gfx/CrossProcessPaint.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/ServoCSSParser.h"
#include "mozilla/ServoStyleSet.h"
#include "nsGenericHTMLFrameElement.h"
#include "GeckoProfiler.h"
@ -129,8 +132,8 @@ typedef FrameMetrics::ViewID ViewID;
// itself. Note that "#foo" on the end of URL doesn't affect
// whether it's considered identical, but "?foo" or ";foo" are
// considered and compared.
// Bug 228829: Limit this to 1, like IE does.
#define MAX_SAME_URL_CONTENT_FRAMES 1
// Limit this to 2, like chromium does.
#define MAX_SAME_URL_CONTENT_FRAMES 2
// Bug 8065: Limit content frame depth to some reasonable level. This
// does not count chrome frames when determining depth, nor does it
@ -3103,6 +3106,64 @@ 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)
{
RefPtr<nsIGlobalObject> global = GetOwnerContent()->GetOwnerGlobal();
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RefPtr<nsIDocument> document = GetOwnerContent()->GetOwnerDocument();
if (NS_WARN_IF(!document)) {
aRv = NS_ERROR_FAILURE;
return nullptr;
}
nsIPresShell* presShell = document->GetShell();
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(mRemoteBrowser->GetTabId(),
rect,
aScale,
color,
promise);
} else {
gfx::CrossProcessPaint::StartLocal(mDocShell,
rect,
aScale,
color,
promise);
}
return promise.forget();
}
already_AddRefed<nsITabParent>
nsFrameLoader::GetTabParent()
{

Просмотреть файл

@ -171,6 +171,15 @@ public:
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);

Просмотреть файл

@ -808,6 +808,17 @@ ImageBitmap::ToCloneData() const
return result;
}
/* static */ already_AddRefed<ImageBitmap>
ImageBitmap::CreateFromSourceSurface(nsIGlobalObject* aGlobal,
gfx::SourceSurface* aSource,
ErrorResult& aRv)
{
RefPtr<layers::Image> data = CreateImageFromSurface(aSource);
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
ret->mAllocatedImageData = true;
return ret.forget();
}
/* static */ already_AddRefed<ImageBitmap>
ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
ImageBitmapCloneData* aData)

Просмотреть файл

@ -118,6 +118,11 @@ public:
UniquePtr<ImageBitmapCloneData>
ToCloneData() const;
static already_AddRefed<ImageBitmap>
CreateFromSourceSurface(nsIGlobalObject* aGlobal,
gfx::SourceSurface* aSource,
ErrorResult& aRv);
static already_AddRefed<ImageBitmap>
CreateFromCloneData(nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData);

Просмотреть файл

@ -607,3 +607,4 @@ support-files =
[test_getElementsByName_after_mutation.html]
[test_bug1279218.html]
[test_set_input_files.html]
[test_nestediframe.html]

Просмотреть файл

@ -0,0 +1,55 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for same URLs nested iframes</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
function reportState(msg) {
if (location.href.includes("#")) {
parent.postMessage(msg, "*");
return;
}
if (msg == "OK 1") {
ok(true, "First frame loaded");
} else if (msg == "KO 2") {
ok(true, "Second frame load failed");
SimpleTest.finish();
} else {
ok(false, "Unknown message: " + msg);
}
}
addEventListener("message", event => {
reportState(event.data);
});
var recursion;
if (!location.href.includes("#")) {
recursion = 1;
} else {
recursion = parseInt(localStorage.recursion) + 1;
}
localStorage.recursion = "" + recursion;
var ifr = document.createElement('iframe');
ifr.src = location.href.split("#")[0] + "#" + recursion;
document.body.appendChild(ifr);
ifr.onload = function() {
reportState("OK " + recursion);
}
ifr.onerror = function() {
reportState("KO " + recursion);
}
</script>
</body>
</html>

Просмотреть файл

@ -181,6 +181,7 @@ ContentProcessManager::RegisterRemoteFrame(const TabId& aTabId,
}
iter->second.mRemoteFrames[aTabId] = info;
mTabProcessMap[aTabId] = aChildCpId;
return true;
}
@ -200,6 +201,11 @@ ContentProcessManager::UnregisterRemoteFrame(const ContentParentId& aChildCpId,
if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
iter->second.mRemoteFrames.erase(aChildTabId);
}
auto tabProcessIter = mTabProcessMap.find(aChildTabId);
if (tabProcessIter != mTabProcessMap.end()) {
mTabProcessMap.erase(tabProcessIter);
}
}
bool
@ -273,6 +279,17 @@ ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCp
return true;
}
ContentParentId
ContentProcessManager::GetTabProcessId(const TabId& aTabId)
{
auto tabProcessIter = mTabProcessMap.find(aTabId);
MOZ_ASSERT(tabProcessIter != mTabProcessMap.end());
if (tabProcessIter == mTabProcessMap.end()) {
return ContentParentId(0);
}
return tabProcessIter->second;
}
already_AddRefed<TabParent>
ContentProcessManager::GetTabParentByProcessAndTabId(const ContentParentId& aChildCpId,
const TabId& aChildTabId)

Просмотреть файл

@ -115,6 +115,12 @@ public:
/*out*/ContentParentId* aOpenerCpId,
/*out*/ TabId* aOpenerTabId);
/**
* Get the ContentParentId of the parent of the given tab id.
*/
ContentParentId
GetTabProcessId(const TabId& aTabId);
/**
* Get all TabParents' Ids managed by the givent content process.
* Return empty array when TabParent couldn't be found via aChildCpId
@ -157,6 +163,7 @@ public:
private:
static StaticAutoPtr<ContentProcessManager> sSingleton;
std::map<ContentParentId, ContentProcessInfo> mContentParentMap;
std::map<TabId, ContentParentId> mTabProcessMap;
ContentProcessManager() {MOZ_COUNT_CTOR(ContentProcessManager);};
};

Просмотреть файл

@ -32,6 +32,7 @@ include "mozilla/GfxMessageUtils.h";
include "mozilla/layers/LayersMessageUtils.h";
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
using moveonly mozilla::gfx::PaintFragment from "mozilla/gfx/CrossProcessPaint.h";
using mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";
@ -766,6 +767,9 @@ child:
*/
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.
* This is useful to speed up interactive operations over async

Просмотреть файл

@ -26,6 +26,7 @@
#include "mozilla/dom/MessageManagerBinding.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/dom/PaymentRequestChild.h"
#include "mozilla/gfx/CrossProcessPaint.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/layers/APZChild.h"
@ -2667,6 +2668,31 @@ TabChild::RecvRenderLayers(const bool& aEnabled, const bool& aForceRepaint, cons
return IPC_OK();
}
mozilla::ipc::IPCResult
TabChild::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
TabChild::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
TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
{

Просмотреть файл

@ -724,6 +724,10 @@ protected:
virtual mozilla::ipc::IPCResult RecvRenderLayers(const bool& aEnabled, const bool& aForce, const layers::LayersObserverEpoch& aEpoch) override;
virtual mozilla::ipc::IPCResult RecvRequestRootPaint(const IntRect& aRect, const float& aScale, const nscolor& aBackgroundColor, RequestRootPaintResolver&& aResolve) override;
virtual mozilla::ipc::IPCResult RecvRequestSubPaint(const float& aScale, const nscolor& aBackgroundColor, RequestSubPaintResolver&& aResolve) override;
virtual mozilla::ipc::IPCResult RecvNavigateByKey(const bool& aForward,
const bool& aForDocumentNavigation) override;

Просмотреть файл

@ -3098,6 +3098,38 @@ TabParent::LayerTreeUpdate(const LayersObserverEpoch& aEpoch, bool aActive)
mFrameElement->DispatchEvent(*event);
}
void
TabParent::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
TabParent::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
TabParent::RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch)
{

Просмотреть файл

@ -17,6 +17,7 @@
#include "mozilla/dom/TabContext.h"
#include "mozilla/EventForwards.h"
#include "mozilla/dom/File.h"
#include "mozilla/gfx/CrossProcessPaint.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Move.h"
@ -562,6 +563,9 @@ public:
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);
virtual mozilla::ipc::IPCResult
RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
const uint32_t& aAction,

Просмотреть файл

@ -108,6 +108,30 @@ 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);
/**
* If false, then the subdocument is not clipped to its CSS viewport, and the
* subdocument's viewport scrollbar(s) are not rendered.

Просмотреть файл

@ -1037,6 +1037,12 @@ public:
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
const DrawOptions &aOptions = DrawOptions()) = 0;
virtual void DrawDependentSurface(uint64_t aId,
const Rect &aDest,
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
const DrawOptions &aOptions = DrawOptions())
{ MOZ_CRASH("GFX: DrawDependentSurface"); }
/**
* Draw the output of a FilterNode to the DrawTarget.
*

Просмотреть файл

@ -66,6 +66,18 @@ DrawEventRecorderMemory::RecordEvent(const RecordedEvent &aEvent)
aEvent.RecordToStream(mOutputStream);
}
void
DrawEventRecorderMemory::AddDependentSurface(uint64_t aDependencyId)
{
mDependentSurfaces.PutEntry(aDependencyId);
}
nsTHashtable<nsUint64HashKey>&&
DrawEventRecorderMemory::TakeDependentSurfaces()
{
return std::move(mDependentSurfaces);
}
DrawEventRecorderFile::DrawEventRecorderFile(const char_type* aFilename)
: mOutputStream(aFilename, ofstream::binary)
{
@ -114,7 +126,7 @@ DrawEventRecorderMemory::DrawEventRecorderMemory()
DrawEventRecorderMemory::DrawEventRecorderMemory(const SerializeResourcesFn &aFn) :
mSerializeCallback(aFn)
{
mExternalFonts = true;
mExternalFonts = !!mSerializeCallback;
WriteHeader(mOutputStream);
}

Просмотреть файл

@ -16,6 +16,9 @@
#include <unordered_map>
#include <functional>
#include "nsHashKeys.h"
#include "nsTHashtable.h"
namespace mozilla {
namespace gfx {
@ -110,6 +113,11 @@ public:
virtual void StoreSourceSurfaceRecording(SourceSurface *aSurface,
const char *aReason);
virtual void AddDependentSurface(uint64_t aDependencyId)
{
MOZ_CRASH("GFX: AddDependentSurface");
}
protected:
void StoreExternalSurfaceRecording(SourceSurface* aSurface,
uint64_t aKey);
@ -177,6 +185,10 @@ public:
void RecordEvent(const RecordedEvent &aEvent) override;
void AddDependentSurface(uint64_t aDependencyId) override;
nsTHashtable<nsUint64HashKey>&& TakeDependentSurfaces();
/**
* @return the current size of the recording (in chars).
*/
@ -205,6 +217,7 @@ protected:
private:
SerializeResourcesFn mSerializeCallback;
nsTHashtable<nsUint64HashKey> mDependentSurfaces;
void Flush() override;
};

Просмотреть файл

@ -417,6 +417,16 @@ DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
}
void
DrawTargetRecording::DrawDependentSurface(uint64_t aId,
const Rect &aDest,
const DrawSurfaceOptions &aSurfOptions,
const DrawOptions &aOptions)
{
mRecorder->AddDependentSurface(aId);
mRecorder->RecordEvent(RecordedDrawDependentSurface(this, aId, aDest, aSurfOptions, aOptions));
}
void
DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface,
const Point &aDest,

Просмотреть файл

@ -57,6 +57,11 @@ public:
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void DrawDependentSurface(uint64_t aId,
const Rect &aDest,
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void DrawFilter(FilterNode *aNode,
const Rect &aSourceRect,
const Point &aDestPoint,

Просмотреть файл

@ -34,6 +34,11 @@ public:
bool TranslateRecording(char *, size_t len);
void SetExternalSurfaces(nsRefPtrHashtable<nsUint64HashKey, SourceSurface>* aExternalSurfaces)
{
mExternalSurfaces = aExternalSurfaces;
}
DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
{
DrawTarget* result = mDrawTargets.GetWeak(aRefPtr);
@ -90,6 +95,11 @@ public:
return result;
}
already_AddRefed<SourceSurface> LookupExternalSurface(uint64_t aKey) override
{
return mExternalSurfaces->Get(aKey);
}
void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final
{
mDrawTargets.Put(aRefPtr, aDT);
@ -187,6 +197,7 @@ private:
nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
nsRefPtrHashtable<nsUint64HashKey, SourceSurface>* mExternalSurfaces;
};
} // namespace gfx

Просмотреть файл

@ -65,6 +65,8 @@ RecordedEvent::GetEventName(EventType aType)
return "Stroke";
case DRAWSURFACE:
return "DrawSurface";
case DRAWDEPENDENTSURFACE:
return "DrawDependentSurface";
case DRAWSURFACEWITHSHADOW:
return "DrawSurfaceWithShadow";
case DRAWFILTER:

Просмотреть файл

@ -234,6 +234,7 @@ public:
MASK,
STROKE,
DRAWSURFACE,
DRAWDEPENDENTSURFACE,
DRAWSURFACEWITHSHADOW,
PATHCREATION,
PATHDESTRUCTION,

Просмотреть файл

@ -644,6 +644,35 @@ private:
DrawOptions mOptions;
};
class RecordedDrawDependentSurface : public RecordedDrawingEvent<RecordedDrawDependentSurface> {
public:
RecordedDrawDependentSurface(DrawTarget *aDT, uint64_t aId, const Rect &aDest,
const DrawSurfaceOptions &aDSOptions,
const DrawOptions &aOptions)
: RecordedDrawingEvent(DRAWDEPENDENTSURFACE, aDT), mId(aId), mDest(aDest)
, mDSOptions(aDSOptions), mOptions(aOptions)
{
}
virtual bool PlayEvent(Translator *aTranslator) const override;
template<class S> void Record(S &aStream) const;
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const override;
virtual std::string GetName() const override { return "DrawDependentSurface"; }
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedDrawDependentSurface(S &aStream);
uint64_t mId;
Rect mDest;
DrawSurfaceOptions mDSOptions;
DrawOptions mOptions;
};
class RecordedDrawSurfaceWithShadow : public RecordedDrawingEvent<RecordedDrawSurfaceWithShadow> {
public:
RecordedDrawSurfaceWithShadow(DrawTarget *aDT, ReferencePtr aRefSource, const Point &aDest,
@ -2431,6 +2460,43 @@ RecordedDrawSurface::OutputSimpleEventInfo(std::stringstream &aStringStream) con
aStringStream << "[" << mDT << "] DrawSurface (" << mRefSource << ")";
}
inline bool
RecordedDrawDependentSurface::PlayEvent(Translator *aTranslator) const
{
RefPtr<SourceSurface> surface(aTranslator->LookupExternalSurface(mId));
aTranslator->LookupDrawTarget(mDT)->
DrawSurface(surface, mDest, Rect(Point(), Size(surface->GetSize())),
mDSOptions, mOptions);
return true;
}
template<class S>
void
RecordedDrawDependentSurface::Record(S &aStream) const
{
RecordedDrawingEvent::Record(aStream);
WriteElement(aStream, mId);
WriteElement(aStream, mDest);
WriteElement(aStream, mDSOptions);
WriteElement(aStream, mOptions);
}
template<class S>
RecordedDrawDependentSurface::RecordedDrawDependentSurface(S &aStream)
: RecordedDrawingEvent(DRAWDEPENDENTSURFACE, aStream)
{
ReadElement(aStream, mId);
ReadElement(aStream, mDest);
ReadElement(aStream, mDSOptions);
ReadElement(aStream, mOptions);
}
inline void
RecordedDrawDependentSurface::OutputSimpleEventInfo(std::stringstream &aStringStream) const
{
aStringStream << "[" << mDT << "] DrawDependentSurface (" << mId << ")";
}
inline bool
RecordedDrawFilter::PlayEvent(Translator *aTranslator) const
{
@ -3443,6 +3509,7 @@ RecordedFilterNodeSetInput::OutputSimpleEventInfo(std::stringstream &aStringStre
f(MASK, RecordedMask); \
f(STROKE, RecordedStroke); \
f(DRAWSURFACE, RecordedDrawSurface); \
f(DRAWDEPENDENTSURFACE, RecordedDrawDependentSurface); \
f(DRAWSURFACEWITHSHADOW, RecordedDrawSurfaceWithShadow); \
f(DRAWFILTER, RecordedDrawFilter); \
f(PATHCREATION, RecordedPathCreation); \

Просмотреть файл

@ -0,0 +1,427 @@
/* -*- 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/. */
#include "CrossProcessPaint.h"
#include "mozilla/dom/ContentProcessManager.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/gfx/InlineTranslator.h"
#include "mozilla/PresShell.h"
#include "gfxPlatform.h"
#include "nsContentUtils.h"
#include "nsGlobalWindowInner.h"
#include "nsIDocShell.h"
#include "nsPresContext.h"
#define ENABLE_PAINT_LOG 0
// #define ENABLE_PAINT_LOG 1
#if ENABLE_PAINT_LOG
# define PF_LOG(...) printf_stderr("PaintFragment: " __VA_ARGS__)
# define CPP_LOG(...) printf_stderr("CrossProcessPaint: " __VA_ARGS__)
#else
# define PF_LOG(...)
# define CPP_LOG(...)
#endif
namespace mozilla {
namespace gfx {
using namespace mozilla::ipc;
/// The minimum scale we allow tabs to be rasterized at.
static const float kMinPaintScale = 0.05;
/* static */ PaintFragment
PaintFragment::Record(nsIDocShell* aDocShell,
const IntRect& aRect,
float aScale,
nscolor aBackgroundColor)
{
IntSize surfaceSize = aRect.Size();
surfaceSize.width *= aScale;
surfaceSize.height *= aScale;
CPP_LOG("Recording "
"[docshell=%p, "
"rect=(%d, %d) x (%d, %d), "
"scale=%f, "
"color=(%u, %u, %u, %u)]\n",
aDocShell,
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));
// Check for invalid sizes
if (surfaceSize.width <= 0 || surfaceSize.height <= 0 ||
!Factory::CheckSurfaceSize(surfaceSize)) {
PF_LOG("Invalid surface size of (%d x %d).\n",
surfaceSize.width,
surfaceSize.height);
return PaintFragment{};
}
// Flush any pending notifications
nsContentUtils::FlushLayoutForTree(aDocShell->GetWindow());
// Grab the presentation shell to render
RefPtr<nsPresContext> presContext;
if (aDocShell) {
aDocShell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext) {
PF_LOG("Couldn't find PresContext.\n");
return PaintFragment{};
}
// Initialize the recorder
SurfaceFormat format = SurfaceFormat::B8G8R8A8;
RefPtr<DrawTarget> referenceDt =
Factory::CreateDrawTarget(gfxPlatform::GetPlatform()->GetSoftwareBackend(),
IntSize(1, 1),
format);
// TODO: This may OOM crash if the content is complex enough
RefPtr<DrawEventRecorderMemory> recorder =
MakeAndAddRef<DrawEventRecorderMemory>(nullptr);
RefPtr<DrawTarget> dt =
Factory::CreateRecordingDrawTarget(recorder, referenceDt, surfaceSize);
// Perform the actual rendering
{
nsRect r(nsPresContext::CSSPixelsToAppUnits(aRect.x),
nsPresContext::CSSPixelsToAppUnits(aRect.y),
nsPresContext::CSSPixelsToAppUnits(aRect.width),
nsPresContext::CSSPixelsToAppUnits(aRect.height));
RefPtr<gfxContext> thebes = gfxContext::CreateOrNull(dt);
thebes->SetMatrix(Matrix::Scaling(aScale, aScale));
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
Unused << shell->RenderDocument(r, 0, aBackgroundColor, thebes);
}
ByteBuf recording = ByteBuf((uint8_t*)recorder->mOutputStream.mData,
recorder->mOutputStream.mLength,
recorder->mOutputStream.mCapacity);
recorder->mOutputStream.mData = nullptr;
recorder->mOutputStream.mLength = 0;
recorder->mOutputStream.mCapacity = 0;
return PaintFragment{
surfaceSize,
std::move(recording),
std::move(recorder->TakeDependentSurfaces()),
};
}
bool
PaintFragment::IsEmpty() const
{
return !mRecording.mData || mRecording.mLen == 0 || mSize == IntSize(0, 0);
}
PaintFragment::PaintFragment(IntSize aSize,
ByteBuf&& aRecording,
nsTHashtable<nsUint64HashKey>&& aDependencies)
: mSize(aSize)
, mRecording(std::move(aRecording))
, mDependencies(std::move(aDependencies))
{
}
/* static */ void
CrossProcessPaint::StartLocal(nsIDocShell* aRoot,
const IntRect& 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), "
"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),
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));
RefPtr<CrossProcessPaint> resolver = new CrossProcessPaint(aPromise,
aScale,
aBackgroundColor,
aRoot);
resolver->QueueRootPaint(aRoot, aRect, aScale, aBackgroundColor);
}
CrossProcessPaint::CrossProcessPaint(dom::Promise* aPromise,
float aScale,
nscolor aBackgroundColor,
dom::TabId aRootId)
: mPromise{aPromise}
, mRootId{aRootId}
, mScale{aScale}
, mBackgroundColor{aBackgroundColor}
, mPendingFragments{1}
{
}
CrossProcessPaint::~CrossProcessPaint()
{
}
void
CrossProcessPaint::ReceiveFragment(dom::TabId aId, PaintFragment&& aFragment)
{
if (IsCleared()) {
CPP_LOG("Ignoring fragment from %llu.\n", (uint64_t)aId);
return;
}
MOZ_ASSERT(mPendingFragments > 0);
MOZ_ASSERT(!mReceivedFragments.GetValue(aId));
MOZ_ASSERT(!aFragment.IsEmpty());
// Double check our invariants to protect against a compromised content
// process
if (mPendingFragments == 0 ||
mReceivedFragments.GetValue(aId) ||
aFragment.IsEmpty()) {
CPP_LOG("Dropping invalid fragment from %llu.\n", (uint64_t)aId);
LostFragment(aId);
return;
}
CPP_LOG("Receiving fragment from %llu.\n", (uint64_t)aId);
// Queue paints for child tabs
for (auto iter = aFragment.mDependencies.Iter(); !iter.Done(); iter.Next()) {
auto dependency = iter.Get()->GetKey();
QueueSubPaint(dom::TabId(dependency));
}
mReceivedFragments.Put(aId, std::move(aFragment));
mPendingFragments -= 1;
// Resolve this paint if we have received all pending fragments
MaybeResolve();
}
void
CrossProcessPaint::LostFragment(dom::TabId aId)
{
if (IsCleared()) {
CPP_LOG("Ignoring lost fragment from %llu.\n", (uint64_t)aId);
return;
}
mPromise->MaybeReject(NS_ERROR_FAILURE);
Clear();
}
void
CrossProcessPaint::QueueRootPaint(dom::TabId aId,
const IntRect& aRect,
float aScale,
nscolor aBackgroundColor)
{
MOZ_ASSERT(!mReceivedFragments.GetValue(aId));
MOZ_ASSERT(mPendingFragments == 1);
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::TabParent> tab = cpm->GetTabParentByProcessAndTabId(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::TabParent> tab = cpm->GetTabParentByProcessAndTabId(cpId, aId);
tab->RequestSubPaint(this, mScale, mBackgroundColor);
mPendingFragments += 1;
}
void
CrossProcessPaint::Clear()
{
mPromise = nullptr;
mPendingFragments = 0;
mReceivedFragments.Clear();
}
bool
CrossProcessPaint::IsCleared() const
{
return !mPromise;
}
void
CrossProcessPaint::MaybeResolve()
{
// Don't do anything if we aren't ready, experienced an error, or already
// resolved this paint
if (IsCleared() || mPendingFragments > 0) {
CPP_LOG("Not ready to resolve yet, have %u fragments left.\n",
mPendingFragments);
return;
}
CPP_LOG("Starting to resolve fragments.\n");
// Resolve the paint fragments from the bottom up
ResolvedSurfaceMap resolved;
if (!ResolveInternal(mRootId, &resolved)) {
CPP_LOG("Couldn't resolve.\n");
mPromise->MaybeReject(NS_ERROR_FAILURE);
Clear();
return;
}
// Grab the result from the resolved table
RefPtr<SourceSurface> root = resolved.Get(mRootId);
CPP_LOG("Resolved all fragments.\n");
ErrorResult rv;
RefPtr<dom::ImageBitmap> bitmap =
dom::ImageBitmap::CreateFromSourceSurface(mPromise->GetParentObject(),
root,
rv);
if (!rv.Failed()) {
CPP_LOG("Success, fulfilling promise.\n");
mPromise->MaybeResolve(bitmap);
} else {
CPP_LOG("Couldn't create ImageBitmap for SourceSurface.\n");
mPromise->MaybeReject(rv);
}
Clear();
}
bool
CrossProcessPaint::ResolveInternal(dom::TabId aId,
ResolvedSurfaceMap* aResolved)
{
// We should not have resolved this paint already
MOZ_ASSERT(!aResolved->GetWeak(aId));
CPP_LOG("Resolving fragment %llu.\n", (uint64_t)aId);
Maybe<PaintFragment> fragment = mReceivedFragments.GetAndRemove(aId);
// 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)) {
return false;
}
}
// Create the destination draw target
RefPtr<DrawTarget> drawTarget =
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);
return false;
}
// Translate the recording using our child tabs
{
InlineTranslator translator(drawTarget, nullptr);
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);
return false;
}
}
RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
if (!snapshot) {
CPP_LOG("Couldn't get snapshot for fragment %llu.\n",
(uint64_t)aId);
return false;
}
// We are done with the resolved images of our dependencies, let's remove
// them
for (auto iter = fragment->mDependencies.Iter(); !iter.Done(); iter.Next()) {
auto dependency = iter.Get()->GetKey();
aResolved->Remove(dependency);
}
aResolved->Put(aId, snapshot);
return true;
}
} // namespace gfx
} // namespace mozilla

170
gfx/ipc/CrossProcessPaint.h Normal file
Просмотреть файл

@ -0,0 +1,170 @@
/* -*- 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 _include_mozilla_gfx_ipc_CrossProcessPaint_h_
#define _include_mozilla_gfx_ipc_CrossProcessPaint_h_
#include "nsISupportsImpl.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/ipc/ByteBuf.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsRefPtrHashtable.h"
#include "nsTHashtable.h"
namespace IPC {
template<typename T> struct ParamTraits;
} // namespace IPC
namespace mozilla {
namespace gfx {
class CrossProcessPaint;
/**
* A fragment of a paint of a cross process document tree.
*/
class PaintFragment
{
public:
/// Initializes an empty PaintFragment
PaintFragment() = default;
/**
* Creates a paint fragment by recording the draw commands and dependent tabs
* for an nsIDocShell.
*
* @param aDocShell The document shell to record.
* @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.
* @param aBackgroundColor The background color to use.
*
* @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);
/// Returns whether this paint fragment contains a valid recording.
bool IsEmpty() const;
PaintFragment(PaintFragment&&) = default;
PaintFragment& operator=(PaintFragment&&) = default;
protected:
friend struct IPC::ParamTraits<PaintFragment>;
friend CrossProcessPaint;
typedef mozilla::ipc::ByteBuf ByteBuf;
PaintFragment(IntSize, ByteBuf&&, nsTHashtable<nsUint64HashKey>&&);
IntSize mSize;
ByteBuf mRecording;
nsTHashtable<nsUint64HashKey> mDependencies;
};
/**
* An object for painting a cross process document tree.
*/
class CrossProcessPaint
{
NS_INLINE_DECL_REFCOUNTING(CrossProcessPaint);
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.
*
* @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.
*/
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.
*/
static void StartRemote(dom::TabId aRoot,
const IntRect& aRect,
float aScale,
nscolor aBackgroundColor,
dom::Promise* aPromise);
void ReceiveFragment(dom::TabId aId, PaintFragment&& aFragment);
void LostFragment(dom::TabId aId);
private:
typedef nsRefPtrHashtable<nsUint64HashKey, SourceSurface> ResolvedSurfaceMap;
typedef nsDataHashtable<nsUint64HashKey, PaintFragment> ReceivedFragmentMap;
CrossProcessPaint(dom::Promise* aPromise,
float aScale,
nscolor aBackgroundColor,
dom::TabId aRootId);
~CrossProcessPaint();
void QueueRootPaint(dom::TabId aId,
const IntRect& aRect,
float aScale,
nscolor aBackgroundColor);
void QueueSubPaint(dom::TabId aId);
/// Clear the state of this paint so that it cannot be resolved or receive
/// any paint fragments.
void Clear();
/// Returns if this paint has been cleared.
bool IsCleared() const;
/// Resolves the paint fragments if we have none pending and resolves the
/// promise.
void MaybeResolve();
bool ResolveInternal(dom::TabId aId,
ResolvedSurfaceMap* aResolved);
RefPtr<dom::Promise> mPromise;
dom::TabId mRootId;
float mScale;
nscolor mBackgroundColor;
uint32_t mPendingFragments;
ReceivedFragmentMap mReceivedFragments;
};
} // namespace gfx
} // namespace mozilla
#endif // _include_mozilla_gfx_ipc_CrossProcessPaint_h_

Просмотреть файл

@ -20,6 +20,7 @@
#include "gfxTelemetry.h"
#include "gfxTypes.h"
#include "ipc/IPCMessageUtils.h"
#include "mozilla/gfx/CrossProcessPaint.h"
#include "mozilla/gfx/Matrix.h"
#include "nsRect.h"
#include "nsRegion.h"
@ -1279,6 +1280,23 @@ struct ParamTraits<mozilla::Array<T, Length>>
}
};
template<>
struct ParamTraits<mozilla::gfx::PaintFragment>
{
typedef mozilla::gfx::PaintFragment paramType;
static void Write(Message* aMsg, paramType& aParam) {
WriteParam(aMsg, aParam.mSize);
WriteParam(aMsg, aParam.mRecording);
WriteParam(aMsg, aParam.mDependencies);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
return ReadParam(aMsg, aIter, &aResult->mSize) &&
ReadParam(aMsg, aIter, &aResult->mRecording) &&
ReadParam(aMsg, aIter, &aResult->mDependencies);
}
};
} /* namespace IPC */
#endif /* __GFXMESSAGEUTILS_H__ */

Просмотреть файл

@ -13,6 +13,7 @@ EXPORTS.mozilla += [
]
EXPORTS.mozilla.gfx += [
'CrossProcessPaint.h',
'GPUChild.h',
'GPUParent.h',
'GPUProcessHost.h',
@ -49,6 +50,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
UNIFIED_SOURCES += [
'CompositorSession.cpp',
'CompositorWidgetVsyncObserver.cpp',
'CrossProcessPaint.cpp',
'D3DMessageUtils.cpp',
'GPUChild.cpp',
'GPUProcessHost.cpp',

Просмотреть файл

@ -58,6 +58,14 @@ public:
aFrom.mCapacity = 0;
}
ByteBuf& operator=(ByteBuf&& aFrom)
{
std::swap(mData, aFrom.mData);
std::swap(mLen, aFrom.mLen);
std::swap(mCapacity, aFrom.mCapacity);
return *this;
}
~ByteBuf()
{
free(mData);

Просмотреть файл

@ -30,11 +30,13 @@
#include <type_traits>
#include "nsExceptionHandler.h"
#include "nsHashKeys.h"
#include "nsID.h"
#include "nsIWidget.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
#include "js/StructuredClone.h"
#include "nsCSSPropertyID.h"
@ -537,6 +539,39 @@ struct ParamTraits<nsAutoString> : ParamTraits<nsString>
#endif // MOZILLA_INTERNAL_API
template <>
struct ParamTraits<nsTHashtable<nsUint64HashKey>>
{
typedef nsTHashtable<nsUint64HashKey> paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
uint32_t count = aParam.Count();
WriteParam(aMsg, count);
for (auto iter = aParam.ConstIter(); !iter.Done(); iter.Next()) {
WriteParam(aMsg, iter.Get()->GetKey());
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
uint32_t count;
if (!ReadParam(aMsg, aIter, &count)) {
return false;
}
paramType table(count);
for (uint32_t i = 0; i < count; ++i) {
uint64_t key;
if (!ReadParam(aMsg, aIter, &key)) {
return false;
}
table.PutEntry(key);
}
*aResult = std::move(table);
return true;
}
};
// Pickle::ReadBytes and ::WriteBytes take the length in ints, so we must
// ensure there is no overflow. This returns |false| if it would overflow.
// Otherwise, it returns |true| and places the byte length in |aByteLength|.

Просмотреть файл

@ -177,7 +177,8 @@ class Include(Node):
class UsingStmt(Node):
def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None, refcounted=False):
def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None,
refcounted=False, moveonly=False):
Node.__init__(self, loc)
assert not isinstance(cxxTypeSpec, str)
assert cxxHeader is None or isinstance(cxxHeader, str)
@ -186,6 +187,7 @@ class UsingStmt(Node):
self.header = cxxHeader
self.kind = kind
self.refcounted = refcounted
self.moveonly = moveonly
def canBeForwardDeclared(self):
return self.isClass() or self.isStruct()
@ -199,6 +201,9 @@ class UsingStmt(Node):
def isRefcounted(self):
return self.refcounted
def isMoveonly(self):
return self.moveonly
# "singletons"

Просмотреть файл

@ -598,6 +598,9 @@ def _cxxConstRefType(ipdltype, side):
t.const = inner.const or not inner.ref
t.ref = 1
return t
if ipdltype.isCxx() and ipdltype.isMoveonly():
t.ref = 1
return t
if ipdltype.isCxx() and ipdltype.isRefcounted():
# Use T* instead of const RefPtr<T>&
t = t.T
@ -609,10 +612,11 @@ def _cxxConstRefType(ipdltype, side):
def _cxxTypeNeedsMove(ipdltype):
return ipdltype.isIPDL() and (ipdltype.isArray() or
ipdltype.isShmem() or
ipdltype.isByteBuf() or
ipdltype.isEndpoint())
return ((ipdltype.isIPDL() and (ipdltype.isArray() or
ipdltype.isShmem() or
ipdltype.isByteBuf() or
ipdltype.isEndpoint())) or
(ipdltype.isCxx() and ipdltype.isMoveonly()))
def _cxxTypeCanMove(ipdltype):

Просмотреть файл

@ -132,6 +132,7 @@ reserved = set((
'prio',
'protocol',
'refcounted',
'moveonly',
'returns',
'struct',
'sync',
@ -288,13 +289,20 @@ def p_MaybeRefcounted(p):
p[0] = 2 == len(p)
def p_MaybeMoveOnly(p):
"""MaybeMoveOnly : MOVEONLY
|"""
p[0] = 2 == len(p)
def p_UsingStmt(p):
"""UsingStmt : USING MaybeRefcounted UsingKind CxxType FROM STRING"""
"""UsingStmt : USING MaybeRefcounted MaybeMoveOnly UsingKind CxxType FROM STRING"""
p[0] = UsingStmt(locFromTok(p, 1),
refcounted=p[2],
kind=p[3],
cxxTypeSpec=p[4],
cxxHeader=p[6])
moveonly=p[3],
kind=p[4],
cxxTypeSpec=p[5],
cxxHeader=p[7])
# --------------------
# Namespaced stuff

Просмотреть файл

@ -142,11 +142,12 @@ VOID = VoidType()
class ImportedCxxType(Type):
def __init__(self, qname, refcounted):
def __init__(self, qname, refcounted, moveonly):
assert isinstance(qname, QualifiedId)
self.loc = qname.loc
self.qname = qname
self.refcounted = refcounted
self.moveonly = moveonly
def isCxx(self):
return True
@ -157,6 +158,9 @@ class ImportedCxxType(Type):
def isRefcounted(self):
return self.refcounted
def isMoveonly(self):
return self.moveonly
def name(self):
return self.qname.baseid
@ -848,12 +852,15 @@ class GatherDecls(TcheckVisitor):
elif fullname == 'mozilla::ipc::FileDescriptor':
ipdltype = FDType(using.type.spec)
else:
ipdltype = ImportedCxxType(using.type.spec, using.isRefcounted())
ipdltype = ImportedCxxType(using.type.spec, using.isRefcounted(), using.isMoveonly())
existingType = self.symtab.lookup(ipdltype.fullname())
if existingType and existingType.fullname == ipdltype.fullname():
if ipdltype.isRefcounted() != existingType.type.isRefcounted():
self.error(using.loc, "inconsistent refcounted status of type `%s`",
str(using.type))
if ipdltype.isMoveonly() != existingType.type.isMoveonly():
self.error(using.loc, "inconsistent moveonly status of type `%s`",
str(using.type))
using.decl = existingType
return
using.decl = self.declare(

Просмотреть файл

@ -11,8 +11,8 @@ function start(){
o196=document.getElementById('ifr32247').contentDocument.createElementNS('http:2000svg','altGlyph');
o230=o185.cloneNode(true);
tmp.id='ifr42257';
tmp.addEventListener("load", start_dataiframe11);
o230.ownerDocument.documentElement.appendChild(tmp);
start_dataiframe11();
//window.setTimeout('start_dataiframe11()',100);
}function start_dataiframe11(){
o232=o230.ownerDocument.getElementById('ifr42257').contentDocument.documentElement;

Просмотреть файл

@ -367,7 +367,16 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
if (rfp) {
rfp->BuildDisplayList(aBuilder, this, aLists);
// We're the subdoc for <browser remote="true"> and it has
// painted content. Display its shadow layer tree.
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsPoint offset = aBuilder->ToReferenceFrame(this);
nsRect bounds = this->EnsureInnerView()->GetBounds() + offset;
clipState.ClipContentDescendants(bounds);
aLists.Content()->AppendToTop(
MakeDisplayItem<nsDisplayRemote>(aBuilder, this));
return;
}

Просмотреть файл

@ -165,13 +165,8 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
{
MOZ_ASSERT(aFrame,
"makes no sense to have a shadow tree without a frame");
MOZ_ASSERT(!mContainer ||
IsTempLayerManager(aManager) ||
mContainer->Manager() == aManager,
"retaining manager changed out from under us ... HELP!");
if (IsTempLayerManager(aManager) ||
(mContainer && mContainer->Manager() != aManager)) {
if (IsTempLayerManager(aManager)) {
// This can happen if aManager is a "temporary" manager, or if the
// widget's layer manager changed out from under us. We need to
// FIXME handle the former case somehow, probably with an API to
@ -279,23 +274,6 @@ RenderFrameParent::TriggerRepaint()
docFrame->InvalidateLayer(DisplayItemType::TYPE_REMOTE);
}
void
RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsSubDocumentFrame* aFrame,
const nsDisplayListSet& aLists)
{
// We're the subdoc for <browser remote="true"> and it has
// painted content. Display its shadow layer tree.
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsPoint offset = aBuilder->ToReferenceFrame(aFrame);
nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset;
clipState.ClipContentDescendants(bounds);
aLists.Content()->AppendToTop(
MakeDisplayItem<nsDisplayRemote>(aBuilder, aFrame));
}
void
RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
@ -346,6 +324,7 @@ RenderFrameParent::EnsureLayersConnected(CompositorOptions* aCompositorOptions)
nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
nsSubDocumentFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
, mTabId{0}
, mEventRegionsOverride(EventRegionsOverride::NoOverride)
{
bool frameIsPointerEventsNone =
@ -357,6 +336,25 @@ nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresShell())) {
mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent;
}
nsFrameLoader* frameLoader = GetRenderFrameParent()->FrameLoader();
if (frameLoader) {
TabParent* browser = TabParent::GetFrom(frameLoader);
if (browser) {
mTabId = browser->GetTabId();
}
}
}
mozilla::LayerState
nsDisplayRemote::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
if (mozilla::layout::IsTempLayerManager(aManager)) {
return mozilla::LAYER_NONE;
}
return mozilla::LAYER_ACTIVE_FORCE;
}
bool
@ -383,6 +381,21 @@ nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
void
nsDisplayRemote::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx)
{
DrawTarget* target = aCtx->GetDrawTarget();
if (!target->IsRecording() || mTabId == 0) {
NS_WARNING("Remote iframe not rendered");
return;
}
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
Rect destRect =
mozilla::NSRectToSnappedRect(GetContentRect(), appUnitsPerDevPixel, *target);
target->DrawDependentSurface(mTabId, destRect);
}
bool
nsDisplayRemote::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/Attributes.h"
#include <map>
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/layers/APZUtils.h"
#include "mozilla/layers/CompositorOptions.h"
#include "mozilla/layers/LayersTypes.h"
@ -64,9 +65,6 @@ public:
bool IsInitted();
void Destroy();
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsSubDocumentFrame* aFrame,
const nsDisplayListSet& aLists);
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
@ -90,6 +88,11 @@ public:
LayerManager* AttachLayerManager();
nsFrameLoader* FrameLoader() const
{
return mFrameLoader;
}
protected:
void ActorDestroy(ActorDestroyReason why) override;
@ -113,7 +116,6 @@ private:
CompositorOptions mCompositorOptions;
RefPtr<nsFrameLoader> mFrameLoader;
RefPtr<ContainerLayer> mContainer;
RefPtr<LayerManager> mLayerManager;
// True after Destroy() has been called, which is triggered
@ -156,15 +158,14 @@ public:
LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE_FORCE;
}
const ContainerLayerParameters& aParameters) override;
already_AddRefed<Layer>
BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
@ -179,6 +180,7 @@ private:
mozilla::layers::LayersId GetRemoteLayersId() const;
RenderFrameParent* GetRenderFrameParent() const;
mozilla::dom::TabId mTabId;
mozilla::LayoutDeviceIntPoint mOffset;
mozilla::layers::EventRegionsOverride mEventRegionsOverride;
};

Просмотреть файл

@ -1,7 +1,3 @@
[encrypted-media-default-feature-policy.https.sub.html]
expected: TIMEOUT
[Default "encrypted-media" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "encrypted-media" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL

Просмотреть файл

@ -1,35 +1,16 @@
[MediaStream-default-feature-policy.https.sub.html]
expected: TIMEOUT
[Default "microphone" feature policy ["self"\] allows the top-level document.]
expected: FAIL
[Default "microphone" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "microphone" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL
[Feature policy "microphone" can be enabled in cross-origin iframes using "allow" attribute.]
expected: FAIL
[Default "camera" feature policy ["self"\] allows the top-level document.]
expected: FAIL
[Default "camera" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "camera" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL
[Feature policy "camera" can be enabled in cross-origin iframes using "allow" attribute.]
expected: FAIL
[Default "camera; microphone" feature policy ["self"\] allows the top-level document.]
expected: FAIL
[Default "camera; microphone" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "camera; microphone" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL
@ -38,28 +19,18 @@
[MediaStream-default-feature-policy.https.html]
expected: TIMEOUT
[Default "microphone" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "microphone" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL
[Feature policy "microphone" can be enabled in cross-origin iframes using "allow" attribute.]
expected: FAIL
[Default "camera" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "camera" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL
[Feature policy "camera" can be enabled in cross-origin iframes using "allow" attribute.]
expected: FAIL
[Default "camera; microphone" feature policy ["self"\] allows same-origin iframes.]
expected: TIMEOUT
[Default "camera; microphone" feature policy ["self"\] disallows cross-origin iframes.]
expected: FAIL

Просмотреть файл

@ -1,8 +1,4 @@
[xmlhttprequest-sync-default-feature-policy.sub.html]
expected: TIMEOUT
[Default "sync-xhr" feature policy ["*"\] allows same-origin iframes.]
expected: TIMEOUT
[Feature policy "sync-xhr" can be disabled in cross-origin iframes using "allow" attribute.]
expected: FAIL

Просмотреть файл

@ -69,3 +69,4 @@ skip-if = verify
[test_threathit_report.html]
skip-if = verify
[test_fastblock_bug1477046.html]
skip-if = (os == 'win' && os_version == "6.1") || (os == 'mac') # Bug 1495110

Просмотреть файл

@ -1904,6 +1904,24 @@
</body>
</method>
<method name="drawSnapshot">
<parameter name="x"/>
<parameter name="y"/>
<parameter name="w"/>
<parameter name="h"/>
<parameter name="scale"/>
<parameter name="backgroundColor"/>
<body>
<![CDATA[
if (!this.frameLoader) {
throw Components.Exception("No frame loader.",
Cr.NS_ERROR_FAILURE);
}
return this.frameLoader.drawSnapshot(x, y, w, h, scale, backgroundColor);
]]>
</body>
</method>
<method name="dropLinks">
<parameter name="aLinksCount"/>
<parameter name="aLinks"/>

Просмотреть файл

@ -108,6 +108,23 @@ nsTArray_base<Alloc, Copy>::UsesAutoArrayBuffer() const
bool IsTwiceTheRequiredBytesRepresentableAsUint32(size_t aCapacity,
size_t aElemSize);
template<class Alloc, class Copy>
template<typename ActualAlloc>
typename ActualAlloc::ResultTypeProxy
nsTArray_base<Alloc, Copy>::ExtendCapacity(size_type aLength,
size_type aCount,
size_type aElemSize)
{
mozilla::CheckedInt<size_type> newLength = aLength;
newLength += aCount;
if (!newLength.isValid()) {
return ActualAlloc::FailureResult();
}
return this->EnsureCapacity<ActualAlloc>(newLength.value(), aElemSize);
}
template<class Alloc, class Copy>
template<typename ActualAlloc>
typename ActualAlloc::ResultTypeProxy
@ -330,7 +347,7 @@ nsTArray_base<Alloc, Copy>::SwapFromEnd(index_type aStart,
template<class Alloc, class Copy>
template<typename ActualAlloc>
bool
typename ActualAlloc::ResultTypeProxy
nsTArray_base<Alloc, Copy>::InsertSlotsAt(index_type aIndex, size_type aCount,
size_type aElemSize,
size_t aElemAlign)
@ -339,20 +356,15 @@ nsTArray_base<Alloc, Copy>::InsertSlotsAt(index_type aIndex, size_type aCount,
InvalidArrayIndex_CRASH(aIndex, Length());
}
size_type newLen = Length() + aCount;
EnsureCapacity<ActualAlloc>(newLen, aElemSize);
// Check for out of memory conditions
if (Capacity() < newLen) {
return false;
if (!ActualAlloc::Successful(this->ExtendCapacity<ActualAlloc>(Length(), aCount, aElemSize))) {
return ActualAlloc::FailureResult();
}
// Move the existing elements as needed. Note that this will
// change our mLength, so no need to call IncrementLength.
ShiftData<ActualAlloc>(aIndex, 0, aCount, aElemSize, aElemAlign);
return true;
return ActualAlloc::SuccessResult();
}
// nsTArray_base::IsAutoArrayRestorer is an RAII class which takes

Просмотреть файл

@ -396,6 +396,17 @@ protected:
typename ActualAlloc::ResultTypeProxy EnsureCapacity(size_type aCapacity,
size_type aElemSize);
// Extend the storage to accommodate aCount extra elements.
// @param aLength The current size of the array.
// @param aCount The number of elements to add.
// @param aElemSize The size of an array element.
// @return False if insufficient memory is available or the new length
// would overflow; true otherwise.
template<typename ActualAlloc>
typename ActualAlloc::ResultTypeProxy ExtendCapacity(size_type aLength,
size_type aCount,
size_type aElemSize);
// Tries to resize the storage to the minimum required amount. If this fails,
// the array is left as-is.
// @param aElemSize The size of an array element.
@ -448,8 +459,9 @@ protected:
// @param aElementSize the size of an array element.
// @param aElemAlign the alignment in bytes of an array element.
template<typename ActualAlloc>
bool InsertSlotsAt(index_type aIndex, size_type aCount,
size_type aElementSize, size_t aElemAlign);
typename ActualAlloc::ResultTypeProxy
InsertSlotsAt(index_type aIndex, size_type aCount,
size_type aElementSize, size_t aElemAlign);
template<typename ActualAlloc, class Allocator>
typename ActualAlloc::ResultTypeProxy
@ -1761,8 +1773,8 @@ public:
protected:
template<typename ActualAlloc = Alloc>
elem_type* AppendElements(size_type aCount) {
if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
Length() + aCount, sizeof(elem_type)))) {
if (!ActualAlloc::Successful(this->template ExtendCapacity<ActualAlloc>(
Length(), aCount, sizeof(elem_type)))) {
return nullptr;
}
elem_type* elems = Elements() + Length();
@ -2230,9 +2242,8 @@ protected:
template<typename ActualAlloc = Alloc>
elem_type* InsertElementsAt(index_type aIndex, size_type aCount)
{
if (!base_type::template InsertSlotsAt<ActualAlloc>(aIndex, aCount,
sizeof(elem_type),
MOZ_ALIGNOF(elem_type))) {
if (!ActualAlloc::Successful(this->template InsertSlotsAt<ActualAlloc>(
aIndex, aCount, sizeof(elem_type), MOZ_ALIGNOF(elem_type)))) {
return nullptr;
}
@ -2455,9 +2466,8 @@ auto
nsTArray_Impl<E, Alloc>::InsertElementsAt(index_type aIndex, size_type aCount,
const Item& aItem) -> elem_type*
{
if (!base_type::template InsertSlotsAt<ActualAlloc>(aIndex, aCount,
sizeof(elem_type),
MOZ_ALIGNOF(elem_type))) {
if (!ActualAlloc::Successful(this->template InsertSlotsAt<ActualAlloc>(
aIndex, aCount, sizeof(elem_type), MOZ_ALIGNOF(elem_type)))) {
return nullptr;
}
@ -2480,6 +2490,7 @@ nsTArray_Impl<E, Alloc>::InsertElementAt(index_type aIndex) -> elem_type*
InvalidArrayIndex_CRASH(aIndex, Length());
}
// Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK.
if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
Length() + 1, sizeof(elem_type)))) {
return nullptr;
@ -2500,6 +2511,7 @@ nsTArray_Impl<E, Alloc>::InsertElementAt(index_type aIndex, Item&& aItem) -> ele
InvalidArrayIndex_CRASH(aIndex, Length());
}
// Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK.
if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
Length() + 1, sizeof(elem_type)))) {
return nullptr;
@ -2516,8 +2528,8 @@ template<class Item, typename ActualAlloc>
auto
nsTArray_Impl<E, Alloc>::AppendElements(const Item* aArray, size_type aArrayLen) -> elem_type*
{
if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
Length() + aArrayLen, sizeof(elem_type)))) {
if (!ActualAlloc::Successful(this->template ExtendCapacity<ActualAlloc>(
Length(), aArrayLen, sizeof(elem_type)))) {
return nullptr;
}
index_type len = Length();
@ -2539,8 +2551,8 @@ nsTArray_Impl<E, Alloc>::AppendElements(nsTArray_Impl<Item, Allocator>&& aArray)
index_type len = Length();
index_type otherLen = aArray.Length();
if (!Alloc::Successful(this->template EnsureCapacity<Alloc>(
len + otherLen, sizeof(elem_type)))) {
if (!Alloc::Successful(this->template ExtendCapacity<Alloc>(
len, otherLen, sizeof(elem_type)))) {
return nullptr;
}
copy_type::MoveNonOverlappingRegion(Elements() + len, aArray.Elements(), otherLen,
@ -2556,6 +2568,7 @@ template<class Item, typename ActualAlloc>
auto
nsTArray_Impl<E, Alloc>::AppendElement(Item&& aItem) -> elem_type*
{
// Length() + 1 is guaranteed to not overflow, so EnsureCapacity is OK.
if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
Length() + 1, sizeof(elem_type)))) {
return nullptr;

Просмотреть файл

@ -98,6 +98,7 @@ public:
~nsTHashtable();
nsTHashtable(nsTHashtable<EntryType>&& aOther);
nsTHashtable<EntryType>& operator=(nsTHashtable<EntryType>&& aOther);
/**
* Return the generation number for the table. This increments whenever
@ -405,6 +406,14 @@ nsTHashtable<EntryType>::nsTHashtable(nsTHashtable<EntryType>&& aOther)
{
}
template<class EntryType>
nsTHashtable<EntryType>&
nsTHashtable<EntryType>::operator=(nsTHashtable<EntryType>&& aOther)
{
mTable = std::move(aOther.mTable);
return *this;
}
template<class EntryType>
nsTHashtable<EntryType>::~nsTHashtable()
{