Merge inbound to mozilla-central. a=merge

This commit is contained in:
Oana Pop Rus 2019-06-13 12:55:51 +03:00
Родитель 97cbd21e24 73bc7c8dc2
Коммит 1133b6716d
22 изменённых файлов: 477 добавлений и 147 удалений

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

@ -60,6 +60,7 @@
#include "mozilla/TextEvents.h"
#include "mozilla/TouchEvents.h"
#include "mozilla/Unused.h"
#include "Units.h"
#include "nsBrowserStatusFilter.h"
#include "nsContentUtils.h"
#include "nsDocShell.h"
@ -436,7 +437,7 @@ BrowserChild::Observe(nsISupports* aSubject, const char* aTopic,
nsCOMPtr<Document> subject(do_QueryInterface(aSubject));
nsCOMPtr<Document> doc(GetTopLevelDocument());
if (subject == doc) {
if (subject == doc && doc->IsTopLevelContentDocument()) {
RefPtr<PresShell> presShell = doc->GetPresShell();
if (presShell) {
presShell->SetIsFirstPaint(true);
@ -2741,7 +2742,7 @@ bool BrowserChild::IsVisible() {
}
void BrowserChild::UpdateVisibility(bool aForceRepaint) {
bool shouldBeVisible = mIsTopLevel ? mRenderLayers : mEffectsInfo.mVisible;
bool shouldBeVisible = mIsTopLevel ? mRenderLayers : mEffectsInfo.IsVisible();
bool isVisible = IsVisible();
if (shouldBeVisible != isVisible) {
@ -3328,6 +3329,17 @@ ScreenIntSize BrowserChild::GetInnerSize() {
innerSize, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
};
nsRect BrowserChild::GetVisibleRect() {
bool isForceRendering = mIsTopLevel && mRenderLayers;
if (isForceRendering && !mEffectsInfo.IsVisible()) {
// We are forced to render even though we are not visible. In this case, we
// don't have an accurate visible rect, so we must be conservative.
return nsRect(nsPoint(), CSSPixel::ToAppUnits(mUnscaledInnerSize));
} else {
return mEffectsInfo.mVisibleRect;
}
}
ScreenIntRect BrowserChild::GetOuterRect() {
LayoutDeviceIntRect outerRect =
RoundedToInt(mUnscaledOuterRect * mPuppetWidget->GetDefaultScale());

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

@ -418,6 +418,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
bool IsTransparent() const { return mIsTransparent; }
const EffectsInfo& GetEffectsInfo() const { return mEffectsInfo; }
void GetMaxTouchPoints(uint32_t* aTouchPoints) {
*aTouchPoints = mMaxTouchPoints;
}
@ -547,6 +549,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
ScreenIntSize GetInnerSize();
nsRect GetVisibleRect();
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow(const ShowInfo& aShowInfo);

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

@ -7,6 +7,8 @@
#ifndef mozilla_dom_EffectsInfo_h
#define mozilla_dom_EffectsInfo_h
#include "nsRect.h"
namespace mozilla {
namespace dom {
@ -14,29 +16,37 @@ namespace dom {
* An EffectsInfo contains information for a remote browser about the graphical
* effects that are being applied to it by ancestor browsers in different
* processes.
*
* TODO: This struct currently only reports visibility, and should be extended
* with information on clipping and scaling.
*/
class EffectsInfo {
public:
EffectsInfo() { *this = EffectsInfo::FullyHidden(); }
static EffectsInfo FullyVisible() { return EffectsInfo{true}; }
static EffectsInfo FullyHidden() { return EffectsInfo{false}; }
static EffectsInfo VisibleWithinRect(const nsRect& aVisibleRect,
float aScaleX, float aScaleY) {
return EffectsInfo{aVisibleRect, aScaleX, aScaleY};
}
static EffectsInfo FullyHidden() { return EffectsInfo{nsRect(), 1.0f, 1.0f}; }
bool operator==(const EffectsInfo& aOther) {
return mVisible == aOther.mVisible;
return mVisibleRect == aOther.mVisibleRect && mScaleX == aOther.mScaleX &&
mScaleY == aOther.mScaleY;
}
bool operator!=(const EffectsInfo& aOther) { return !(*this == aOther); }
// If you add new state here, you must also update operator==
bool mVisible;
/*
* TODO: Add information for ancestor scaling and clipping.
*/
bool IsVisible() const { return !mVisibleRect.IsEmpty(); }
// The visible rect of this browser relative to the root frame. If this is
// empty then the browser can be considered invisible.
nsRect mVisibleRect;
// The desired scale factors to apply to rasterized content to match
// transforms applied in ancestor browsers.
float mScaleX;
float mScaleY;
// If you add new fields here, you must also update operator==
private:
explicit EffectsInfo(bool aVisible) : mVisible(aVisible) {}
EffectsInfo(const nsRect& aVisibleRect, float aScaleX, float aScaleY)
: mVisibleRect(aVisibleRect), mScaleX(aScaleX), mScaleY(aScaleY) {}
};
} // namespace dom

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

@ -81,12 +81,16 @@ struct ParamTraits<mozilla::dom::EffectsInfo> {
typedef mozilla::dom::EffectsInfo paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mVisible);
WriteParam(aMsg, aParam.mVisibleRect);
WriteParam(aMsg, aParam.mScaleX);
WriteParam(aMsg, aParam.mScaleY);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
return ReadParam(aMsg, aIter, &aResult->mVisible);
return ReadParam(aMsg, aIter, &aResult->mVisibleRect) &&
ReadParam(aMsg, aIter, &aResult->mScaleX) &&
ReadParam(aMsg, aIter, &aResult->mScaleY);
}
};

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

@ -1433,6 +1433,12 @@ class Connection final {
void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(Connection); }
QuotaClient* GetQuotaClient() const {
MOZ_ASSERT(mQuotaClient);
return mQuotaClient;
}
ArchivedOriginScope* GetArchivedOriginScope() const {
return mArchivedOriginScope;
}
@ -1479,6 +1485,12 @@ class Connection final {
nsresult GetCachedStatement(const nsACString& aQuery,
CachedStatement* aCachedStatement);
nsresult BeginWriteTransaction();
nsresult CommitWriteTransaction();
nsresult RollbackWriteTransaction();
private:
// Only created by ConnectionThread.
Connection(ConnectionThread* aConnectionThread, const nsACString& aSuffix,
@ -2819,6 +2831,30 @@ class QuotaClient::MatchFunction final : public mozIStorageFunction {
NS_DECL_MOZISTORAGEFUNCTION
};
/*******************************************************************************
* Helper classes
******************************************************************************/
class MOZ_STACK_CLASS AutoWriteTransaction final {
Connection* mConnection;
Maybe<MutexAutoLock> mShadowDatabaseLock;
bool mShadowWrites;
public:
explicit AutoWriteTransaction(bool aShadowWrites);
~AutoWriteTransaction();
nsresult Start(Connection* aConnection);
nsresult Commit();
private:
nsresult LockAndAttachShadowDatabase(Connection* aConnection);
nsresult DetachShadowDatabaseAndUnlock();
};
/*******************************************************************************
* Globals
******************************************************************************/
@ -4342,6 +4378,60 @@ nsresult Connection::GetCachedStatement(const nsACString& aQuery,
return NS_OK;
}
nsresult Connection::BeginWriteTransaction() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mStorageConnection);
CachedStatement stmt;
nsresult rv = GetCachedStatement(NS_LITERAL_CSTRING("BEGIN IMMEDIATE;"),
&stmt);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult Connection::CommitWriteTransaction() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mStorageConnection);
CachedStatement stmt;
nsresult rv = GetCachedStatement(NS_LITERAL_CSTRING("COMMIT;"), &stmt);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult Connection::RollbackWriteTransaction() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mStorageConnection);
CachedStatement stmt;
nsresult rv = GetCachedStatement(NS_LITERAL_CSTRING("ROLLBACK;"), &stmt);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// This may fail if SQLite already rolled back the transaction so ignore any
// errors.
Unused << stmt->Execute();
return NS_OK;
}
void Connection::ScheduleFlush() {
AssertIsOnOwningThread();
MOZ_ASSERT(mWriteOptimizer.HasWrites());
@ -4497,69 +4587,9 @@ nsresult Connection::FlushOp::DoDatastoreWork() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mConnection);
class MOZ_STACK_CLASS AutoDetach final {
nsCOMPtr<mozIStorageConnection> mConnection;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoWriteTransaction autoWriteTransaction(mShadowWrites);
public:
explicit AutoDetach(
mozIStorageConnection* aConnection MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mConnection(aConnection) {
MOZ_ASSERT(aConnection);
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoDetach() {
if (mConnection) {
nsresult rv = DetachShadowDatabase(mConnection);
Unused << NS_WARN_IF(NS_FAILED(rv));
}
}
void release() { mConnection = nullptr; }
private:
explicit AutoDetach(const AutoDetach&) = delete;
AutoDetach& operator=(const AutoDetach&) = delete;
AutoDetach& operator=(AutoDetach&&) = delete;
};
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
nsCOMPtr<mozIStorageConnection> storageConnection =
mConnection->StorageConnection();
MOZ_ASSERT(storageConnection);
nsresult rv;
Maybe<MutexAutoLock> shadowDatabaseLock;
Maybe<AutoDetach> autoDetach;
if (mShadowWrites) {
MOZ_ASSERT(mConnection->mQuotaClient);
shadowDatabaseLock.emplace(
mConnection->mQuotaClient->ShadowDatabaseMutex());
rv = AttachShadowDatabase(quotaManager->GetBasePath(), storageConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
autoDetach.emplace(storageConnection);
}
CachedStatement stmt;
rv = mConnection->GetCachedStatement(NS_LITERAL_CSTRING("BEGIN IMMEDIATE;"),
&stmt);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
nsresult rv = autoWriteTransaction.Start(mConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4588,34 +4618,19 @@ nsresult Connection::FlushOp::DoDatastoreWork() {
return rv;
}
rv = mConnection->GetCachedStatement(NS_LITERAL_CSTRING("COMMIT;"), &stmt);
rv = autoWriteTransaction.Commit();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mShadowWrites) {
autoDetach->release();
rv = DetachShadowDatabase(storageConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
autoDetach.reset();
shadowDatabaseLock.reset();
}
rv = usageJournalFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
RefPtr<Runnable> runnable =
NS_NewRunnableFunction("dom::localstorage::UpdateUsageRunnable",
[origin = mConnection->Origin(), usage]() {
@ -9351,5 +9366,124 @@ QuotaClient::MatchFunction::OnFunctionCall(
return NS_OK;
}
/*******************************************************************************
* AutoWriteTransaction
******************************************************************************/
AutoWriteTransaction::AutoWriteTransaction(bool aShadowWrites)
: mConnection(nullptr)
, mShadowWrites(aShadowWrites)
{
AssertIsOnConnectionThread();
MOZ_COUNT_CTOR(mozilla::dom::AutoWriteTransaction);
}
AutoWriteTransaction::~AutoWriteTransaction() {
AssertIsOnConnectionThread();
MOZ_COUNT_DTOR(mozilla::dom::AutoWriteTransaction);
if (mConnection) {
if (NS_FAILED(mConnection->RollbackWriteTransaction())) {
NS_WARNING("Failed to rollback write transaction!");
}
if (mShadowWrites && NS_FAILED(DetachShadowDatabaseAndUnlock())) {
NS_WARNING("Failed to detach shadow database!");
}
}
}
nsresult AutoWriteTransaction::Start(Connection* aConnection) {
AssertIsOnConnectionThread();
MOZ_ASSERT(aConnection);
MOZ_ASSERT(!mConnection);
nsresult rv;
if (mShadowWrites) {
rv = LockAndAttachShadowDatabase(aConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
rv = aConnection->BeginWriteTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mConnection = aConnection;
return NS_OK;
}
nsresult AutoWriteTransaction::Commit() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mConnection);
nsresult rv = mConnection->CommitWriteTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mShadowWrites) {
rv = DetachShadowDatabaseAndUnlock();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
mConnection = nullptr;
return NS_OK;
}
nsresult AutoWriteTransaction::LockAndAttachShadowDatabase(Connection* aConnection) {
AssertIsOnConnectionThread();
MOZ_ASSERT(aConnection);
MOZ_ASSERT(!mConnection);
MOZ_ASSERT(mShadowDatabaseLock.isNothing());
MOZ_ASSERT(mShadowWrites);
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
nsCOMPtr<mozIStorageConnection> storageConnection =
aConnection->StorageConnection();
MOZ_ASSERT(storageConnection);
mShadowDatabaseLock.emplace(
aConnection->GetQuotaClient()->ShadowDatabaseMutex());
nsresult rv = AttachShadowDatabase(quotaManager->GetBasePath(), storageConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult AutoWriteTransaction::DetachShadowDatabaseAndUnlock() {
AssertIsOnConnectionThread();
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mShadowDatabaseLock.isSome());
MOZ_ASSERT(mShadowWrites);
nsCOMPtr<mozIStorageConnection> storageConnection =
mConnection->StorageConnection();
MOZ_ASSERT(storageConnection);
nsresult rv = DetachShadowDatabase(storageConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mShadowDatabaseLock.reset();
return NS_OK;
}
} // namespace dom
} // namespace mozilla

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

@ -85,6 +85,18 @@ function resetOriginLimit() {
Services.prefs.clearUserPref("dom.storage.default_quota");
}
function setTimeout(callback, timeout) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback({
notify() {
callback();
},
}, timeout, Ci.nsITimer.TYPE_ONE_SHOT);
return timer;
}
function init() {
let request = Services.qms.init();

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

@ -0,0 +1,67 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/* eslint-disable mozilla/no-arbitrary-setTimeout */
/**
* This test is mainly to verify that the flush operation detaches the shadow
* database in the event of early return due to error. See bug 1559029.
*/
async function testSteps() {
const principal1 = getPrincipal("http://example1.com");
const usageFile1 =
getRelativeFile("storage/default/http+++example1.com/ls/usage");
const principal2 = getPrincipal("http://example2.com");
const data = {
key: "foo",
value: "bar",
};
const flushSleepTimeSec = 6;
info("Setting prefs");
Services.prefs.setBoolPref("dom.storage.next_gen", true);
info("Getting storage 1");
let storage1 = getLocalStorage(principal1);
info("Adding item");
storage1.setItem(data.key, data.value);
info("Creating usage as a directory");
// This will cause a failure during the flush for first principal.
usageFile1.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
info("Getting storage 2");
let storage2 = getLocalStorage(principal2);
info("Adding item");
storage2.setItem(data.key, data.value);
// The flush for second principal shouldn't be affected by failed flush for
// first principal.
info("Sleeping for " + flushSleepTimeSec + " seconds to let all flushes " +
"finish");
await new Promise(function(resolve) {
setTimeout(resolve, flushSleepTimeSec * 1000);
});
info("Resetting");
// Wait for all database connections to close.
let request = reset();
await requestFinished(request);
}

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

@ -33,6 +33,7 @@ run-sequentially = test_databaseShadowing_clearOriginsByPrefix2.js depends on a
[test_databaseShadowing_clearOriginsByPrefix2.js]
run-sequentially = this test depends on a file produced by test_databaseShadowing_clearOriginsByPrefix1.js
[test_eviction.js]
[test_flushing.js]
[test_groupLimit.js]
[test_groupMismatch.js]
[test_largeItems.js]

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

@ -406,7 +406,7 @@ void APZCCallbackHelper::InitializeRootDisplayport(PresShell* aPresShell) {
&viewId)) {
nsPresContext* pc = aPresShell->GetPresContext();
// This code is only correct for root content or toplevel documents.
MOZ_ASSERT(!pc || pc->IsRootContentDocument() ||
MOZ_ASSERT(!pc || pc->IsRootContentDocumentCrossProcess() ||
!pc->GetParentPresContext());
nsIFrame* frame = aPresShell->GetRootScrollFrame();
if (!frame) {

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

@ -1992,7 +1992,7 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::getDirective(
}
if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
if (unicode::IsSpaceOrBOM2(unit)) {
if (unicode::IsSpace(AssertedCast<Latin1Char>(unit))) {
break;
}
@ -2016,13 +2016,13 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::getDirective(
// This ignores encoding errors: subsequent caller-side code to
// handle the remaining source text in the comment will do so.
PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint();
if (peeked.isNone() || unicode::IsSpaceOrBOM2(peeked.codePoint())) {
if (peeked.isNone() || unicode::IsSpace(peeked.codePoint())) {
break;
}
MOZ_ASSERT(!IsLineTerminator(peeked.codePoint()),
"!IsSpaceOrBOM2 must imply !IsLineTerminator or else we'll "
"fail to maintain line-info/flags for EOL");
"!IsSpace must imply !IsLineTerminator or else we'll fail to "
"maintain line-info/flags for EOL");
this->sourceUnits.consumeKnownCodePoint(peeked);
if (!appendCodePointToCharBuffer(peeked.codePoint())) {
@ -2743,12 +2743,11 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::getTokenInternal(
}
if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) {
// Non-ASCII code points can only be identifiers or whitespace.
// It would be nice to compute these *after* discarding whitespace,
// but IN A WORLD where |unicode::IsSpaceOrBOM2| requires consuming
// a variable number of code points, it's easier to assume it's an
// identifier and maybe do a little wasted work, than to unget and
// compute and reget if whitespace.
// Non-ASCII code points can only be identifiers or whitespace. It would
// be nice to compute these *after* discarding whitespace, but IN A WORLD
// where |unicode::IsSpace| requires consuming a variable number of code
// units, it's easier to assume it's an identifier and maybe do a little
// wasted work, than to unget and compute and reget if whitespace.
TokenStart start(this->sourceUnits, 0);
const Unit* identStart = this->sourceUnits.addressOfNextCodeUnit();
@ -2760,7 +2759,7 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::getTokenInternal(
}
char32_t cp = peeked.codePoint();
if (unicode::IsSpaceOrBOM2(cp)) {
if (unicode::IsSpace(cp)) {
this->sourceUnits.consumeKnownCodePoint(peeked);
if (IsLineTerminator(cp)) {
if (!updateLineInfoForEOL()) {

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

@ -19,8 +19,7 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
var bomchars = ['\uFFFE',
'\uFEFF'];
var bomchars = ['\uFEFF'];
for (var i = 0; i < bomchars.length; i++)
{

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

@ -80,7 +80,6 @@ constexpr char16_t GREEK_SMALL_LETTER_SIGMA = 0x03C3;
constexpr char16_t LINE_SEPARATOR = 0x2028;
constexpr char16_t PARA_SEPARATOR = 0x2029;
constexpr char16_t REPLACEMENT_CHARACTER = 0xFFFD;
constexpr char16_t BYTE_ORDER_MARK2 = 0xFFFE;
const char16_t LeadSurrogateMin = 0xD800;
const char16_t LeadSurrogateMax = 0xDBFF;
@ -204,19 +203,28 @@ inline bool IsUnicodeIDStart(uint32_t codePoint) {
return IsUnicodeIDStart(char16_t(codePoint));
}
// IsSpace checks if a code point is included in the merged set of WhiteSpace
// and LineTerminator specified by #sec-white-space and #sec-line-terminators.
// We combine them because nearly every calling function wants this, excepting
// only some tokenizer code that necessarily handles LineTerminator specially
// due to UTF-8/UTF-16 template specialization.
inline bool IsSpace(char16_t ch) {
/*
* IsSpace checks if some character is included in the merged set
* of WhiteSpace and LineTerminator, specified by ES2016 11.2 and 11.3.
* We combined them, because in practice nearly every
* calling function wants this, except some code in the tokenizer.
*
* We use a lookup table for ASCII-7 characters, because they are
* very common and must be handled quickly in the tokenizer.
* NO-BREAK SPACE is supposed to be the most common character not in
* this range, so we inline this case, too.
*/
// ASCII code points are very common and must be handled quickly, so use a
// lookup table for them.
if (ch < 128) {
return js_isspace[ch];
}
// NO-BREAK SPACE is supposed to be the most common non-ASCII WhiteSpace code
// point, so inline its handling too.
if (ch == NO_BREAK_SPACE) {
return true;
}
return CharInfo(ch).isSpace();
}
inline bool IsSpace(JS::Latin1Char ch) {
if (ch < 128) {
return js_isspace[ch];
}
@ -225,16 +233,20 @@ inline bool IsSpace(char16_t ch) {
return true;
}
return CharInfo(ch).isSpace();
MOZ_ASSERT(!CharInfo(ch).isSpace());
return false;
}
inline bool IsSpaceOrBOM2(char32_t ch) {
inline bool IsSpace(char ch) {
return IsSpace(static_cast<JS::Latin1Char>(ch));
}
inline bool IsSpace(char32_t ch) {
if (ch < 128) {
return js_isspace[ch];
}
/* We accept BOM2 (0xFFFE) for compatibility reasons in the parser. */
if (ch == NO_BREAK_SPACE || ch == BYTE_ORDER_MARK2) {
if (ch == NO_BREAK_SPACE) {
return true;
}

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

@ -26,6 +26,7 @@
#include "mozilla/StaticPrefs.h"
#include "mozilla/Unused.h"
#include "nsCharTraits.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "nsFontMetrics.h"
@ -3786,12 +3787,20 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
builder->SetInActiveDocShell(isActive);
}
nsRect rootVisualOverflow = aFrame->GetVisualOverflowRectRelativeToSelf();
// If we are in a remote browser, then apply clipping from ancestor browsers
if (BrowserChild* browserChild = BrowserChild::GetFrom(presShell)) {
rootVisualOverflow.IntersectRect(rootVisualOverflow,
browserChild->GetVisibleRect());
}
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
if (rootScrollFrame && !aFrame->GetParent()) {
nsIScrollableFrame* rootScrollableFrame =
presShell->GetRootScrollFrameAsScrollable();
MOZ_ASSERT(rootScrollableFrame);
nsRect displayPortBase = aFrame->GetVisualOverflowRectRelativeToSelf();
nsRect displayPortBase = rootVisualOverflow;
nsRect temp = displayPortBase;
Unused << rootScrollableFrame->DecideScrollableLayer(
builder, &displayPortBase, &temp,
@ -3806,7 +3815,7 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
// |ignoreViewportScrolling| and |usingDisplayPort| are persistent
// document-rendering state. We rely on PresShell to flush
// retained layers as needed when that persistent state changes.
visibleRegion = aFrame->GetVisualOverflowRectRelativeToSelf();
visibleRegion = rootVisualOverflow;
} else {
visibleRegion = aDirtyRegion;
}
@ -8465,10 +8474,9 @@ static bool UpdateCompositionBoundsForRCDRSF(ParentLayerRect& aCompBounds,
#endif
if (widget) {
LayoutDeviceIntRect widgetBounds = widget->GetBounds();
widgetBounds.MoveTo(0, 0);
aCompBounds = ParentLayerRect(ViewAs<ParentLayerPixel>(
widgetBounds,
LayoutDeviceIntRect(LayoutDeviceIntPoint(),
widget->GetCompositionSize()),
PixelCastJustification::LayoutDeviceIsParentLayerForRCDRSF));
return true;
}

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

@ -3801,8 +3801,12 @@ bool ScrollFrameHelper::DecideScrollableLayer(
if (aSetBase) {
nsRect displayportBase = *aVisibleRect;
nsPresContext* pc = mOuter->PresContext();
if (mIsRoot &&
(pc->IsRootContentDocument() || !pc->GetParentPresContext())) {
bool isContentRootDoc = pc->IsRootContentDocumentCrossProcess();
bool isChromeRootDoc =
!pc->Document()->IsContentDocument() && !pc->GetParentPresContext();
if (mIsRoot && (isContentRootDoc || isChromeRootDoc)) {
displayportBase =
nsRect(nsPoint(0, 0),
nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter));

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

@ -14,6 +14,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLFrameElement.h"
#include "mozilla/dom/BrowserParent.h"
@ -1404,8 +1405,20 @@ already_AddRefed<mozilla::layers::Layer> nsDisplayRemote::BuildLayer(
if (RefPtr<RemoteBrowser> remoteBrowser =
GetFrameLoader()->GetRemoteBrowser()) {
// Adjust mItemVisibleRect, which is relative to the reference frame, to be
// relative to this frame
nsRect visibleRect;
if (aContainerParameters.mItemVisibleRect) {
visibleRect = *aContainerParameters.mItemVisibleRect - ToReferenceFrame();
} else {
visibleRect = mFrame->GetContentRectRelativeToSelf();
}
// Generate an effects update notifying the browser it is visible
aBuilder->AddEffectUpdate(remoteBrowser, EffectsInfo::FullyVisible());
aBuilder->AddEffectUpdate(remoteBrowser,
EffectsInfo::VisibleWithinRect(
visibleRect, aContainerParameters.mXScale,
aContainerParameters.mYScale));
// FrameLayerBuilder will take care of notifying the browser when it is no
// longer visible
}
@ -1465,8 +1478,10 @@ bool nsDisplayRemote::CreateWebRenderCommands(
if (RefPtr<RemoteBrowser> remoteBrowser =
GetFrameLoader()->GetRemoteBrowser()) {
// Generate an effects update notifying the browser it is visible
aDisplayListBuilder->AddEffectUpdate(remoteBrowser,
EffectsInfo::FullyVisible());
// TODO - Gather visibleRect and scaling factors
aDisplayListBuilder->AddEffectUpdate(
remoteBrowser, EffectsInfo::VisibleWithinRect(
mFrame->GetContentRectRelativeToSelf(), 1.0f, 1.0f));
// Create a WebRenderRemoteData to notify the RemoteBrowser when it is no
// longer visible

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

@ -4657,6 +4657,7 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
transformNode = transformNode->Parent();
}
nsRect itemVisibleRectAu = itemContent;
if (transformNode) {
// If we are within transform, transform itemContent and itemDrawRect.
MOZ_ASSERT(transformNode);
@ -4818,6 +4819,15 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
ContainerLayerParameters params = mParameters;
params.mBackgroundColor = uniformColor;
params.mLayerCreationHint = GetLayerCreationHint(itemAGR);
if (!transformNode) {
params.mItemVisibleRect = &itemVisibleRectAu;
} else {
// We only use mItemVisibleRect for getting the visible rect for
// remote browsers (which should never have inactive transforms), so we
// avoid doing transforms on itemVisibleRectAu above and can't report
// an accurate bounds here.
params.mItemVisibleRect = nullptr;
}
params.mScrollMetadataASR =
ActiveScrolledRoot::IsAncestor(scrollMetadataASR,
mContainerScrollMetadataASR)

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

@ -285,6 +285,7 @@ struct ContainerLayerParameters {
: mXScale(aXScale),
mYScale(aYScale),
mLayerContentsVisibleRect(nullptr),
mItemVisibleRect(nullptr),
mBackgroundColor(NS_RGBA(0, 0, 0, 0)),
mScrollMetadataASR(nullptr),
mCompositorASR(nullptr),
@ -298,6 +299,7 @@ struct ContainerLayerParameters {
: mXScale(aXScale),
mYScale(aYScale),
mLayerContentsVisibleRect(nullptr),
mItemVisibleRect(nullptr),
mOffset(aOffset),
mBackgroundColor(aParent.mBackgroundColor),
mScrollMetadataASR(aParent.mScrollMetadataASR),
@ -320,6 +322,11 @@ struct ContainerLayerParameters {
*/
nsIntRect* mLayerContentsVisibleRect;
/**
* If non-null, the rectangle which stores the item's visible rect.
*/
nsRect* mItemVisibleRect;
/**
* An offset to apply to all child layers created.
*/

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

@ -101,7 +101,8 @@ enum class PartialUpdateFailReason {
RebuildLimit,
FrameType,
Disabled,
Content
Content,
VisibleRect,
};
struct RetainedDisplayListMetrics {
@ -146,6 +147,8 @@ struct RetainedDisplayListMetrics {
return "Disabled";
case PartialUpdateFailReason::Content:
return "Content";
case PartialUpdateFailReason::VisibleRect:
return "VisibleRect";
default:
MOZ_ASSERT_UNREACHABLE("Enum value not handled!");
}
@ -254,6 +257,7 @@ struct RetainedDisplayListBuilder {
nsDisplayListBuilder mBuilder;
RetainedDisplayList mList;
nsRect mPreviousVisibleRect;
WeakFrame mPreviousCaret;
RetainedDisplayListMetrics mMetrics;
};

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

@ -2882,11 +2882,19 @@ FrameLayerBuilder* nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
rootLayer->SetScrollMetadata(nsTArray<ScrollMetadata>());
}
float rootLayerResolution = StaticPrefs::LayoutUseContainersForRootFrames()
? presShell->GetResolution()
: 1.0f;
ContainerLayerParameters containerParameters(rootLayerResolution,
rootLayerResolution);
float resolutionUniform = StaticPrefs::LayoutUseContainersForRootFrames()
? presShell->GetResolution()
: 1.0f;
float resolutionX = resolutionUniform;
float resolutionY = resolutionUniform;
// If we are in a remote browser, then apply scaling from ancestor browsers
if (BrowserChild* browserChild = BrowserChild::GetFrom(presShell)) {
resolutionX *= browserChild->GetEffectsInfo().mScaleX;
resolutionY *= browserChild->GetEffectsInfo().mScaleY;
}
ContainerLayerParameters containerParameters(resolutionX, resolutionY);
{
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
@ -2906,11 +2914,10 @@ FrameLayerBuilder* nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
if (!root) {
return nullptr;
}
// Root is being scaled up by the X/Y resolution. Scale it back down.
root->SetPostScale(1.0f / resolutionX, 1.0f / resolutionY);
if (StaticPrefs::LayoutUseContainersForRootFrames()) {
// Root is being scaled up by the X/Y resolution. Scale it back down.
root->SetPostScale(1.0f / containerParameters.mXScale,
1.0f / containerParameters.mYScale);
root->SetScaleToResolution(containerParameters.mXScale);
root->SetScaleToResolution(resolutionUniform);
}
auto callback = [root](ScrollableLayerGuid::ViewID aScrollId) -> bool {

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

@ -1158,6 +1158,15 @@ LayoutDeviceIntRect PuppetWidget::GetScreenBounds() {
return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size());
}
LayoutDeviceIntSize PuppetWidget::GetCompositionSize() {
if (!mBrowserChild) {
return nsBaseWidget::GetCompositionSize();
}
CSSSize visibleSize =
CSSPixel::FromAppUnits(mBrowserChild->GetVisibleRect().Size());
return RoundedToInt(visibleSize * GetDefaultScale());
}
uint32_t PuppetWidget::GetMaxTouchPoints() const {
uint32_t maxTouchPoints = 0;
if (mBrowserChild) {

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

@ -242,6 +242,8 @@ class PuppetWidget : public nsBaseWidget,
virtual LayoutDeviceIntRect GetScreenBounds() override;
virtual LayoutDeviceIntSize GetCompositionSize() override;
virtual MOZ_MUST_USE nsresult StartPluginIME(
const mozilla::WidgetKeyboardEvent& aKeyboardEvent, int32_t aPanelX,
int32_t aPanelY, nsString& aCommitted) override;

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

@ -937,6 +937,16 @@ class nsIWidget : public nsISupports {
return GetClientBounds().Size();
}
/**
* Get the size of the bounds of this widget that will be visible when
* rendered.
*
* @return the width and height of the composition size of this widget.
*/
virtual LayoutDeviceIntSize GetCompositionSize() {
return GetBounds().Size();
}
/**
* Set the background color for this widget
*